summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--AUTHORS3
-rw-r--r--CHANGES.md133
-rw-r--r--LICENSE502
-rw-r--r--Makefile.preprocess46
-rw-r--r--README.md26
-rw-r--r--debian/changelog (renamed from changelog)0
-rw-r--r--debian/control (renamed from control)0
-rw-r--r--debian/copyright (renamed from copyright)0
-rw-r--r--debian/gbp.conf (renamed from gbp.conf)0
-rw-r--r--debian/libppx-visitors-ocaml-doc.doc-base (renamed from libppx-visitors-ocaml-doc.doc-base)0
-rw-r--r--debian/libppx-visitors-ocaml-doc.docs (renamed from libppx-visitors-ocaml-doc.docs)0
-rw-r--r--debian/patches/series (renamed from patches/series)0
-rwxr-xr-xdebian/rules (renamed from rules)0
-rw-r--r--debian/source/format (renamed from source/format)0
-rw-r--r--debian/tests/control (renamed from tests/control)0
-rwxr-xr-xdebian/tests/weight (renamed from tests/weight)0
-rw-r--r--debian/tests/weight.ml (renamed from tests/weight.ml)0
-rw-r--r--debian/watch (renamed from watch)0
-rw-r--r--doc/.gitignore27
-rw-r--r--doc/Makefile22
-rw-r--r--doc/OOinfererror.ml6
-rw-r--r--doc/OOinfererroragain.ml6
-rw-r--r--doc/convention.tex49
-rw-r--r--doc/dune1
-rw-r--r--doc/dune.manual14
-rw-r--r--doc/english.bib15090
-rw-r--r--doc/from-visitors-to-iterators.md493
-rw-r--r--doc/listings-ocaml.tex24
-rw-r--r--doc/local.bib23
-rw-r--r--doc/macros.tex126
-rw-r--r--doc/manual.pdfbin0 -> 297421 bytes
-rw-r--r--doc/manual.tex2410
-rw-r--r--doc/plain.bst1106
-rw-r--r--doc/types.tex38
-rw-r--r--doc/version.tex1
-rw-r--r--dune5
-rw-r--r--dune-project12
-rw-r--r--runtime/Makefile3
-rw-r--r--runtime/VisitorsRuntime.ml1139
-rw-r--r--runtime/dune7
-rw-r--r--src/Makefile3
-rw-r--r--src/Visitors.ml1288
-rw-r--r--src/Visitors.mli1
-rw-r--r--src/VisitorsAnalysis.ml408
-rw-r--r--src/VisitorsCompatibility.ml103
-rw-r--r--src/VisitorsGeneration.ml586
-rw-r--r--src/VisitorsList.ml125
-rw-r--r--src/VisitorsPlugin.ml4
-rw-r--r--src/VisitorsSettings.ml371
-rw-r--r--src/VisitorsString.ml70
-rw-r--r--src/dune22
-rw-r--r--test/Makefile3
-rw-r--r--test/OOinfer.ml5
-rw-r--r--test/OOinferfixed.ml6
-rw-r--r--test/OOinferfixedagain.ml6
-rw-r--r--test/OOinferfixedagaincheck.ml6
-rw-r--r--test/OOinferself.ml6
-rw-r--r--test/OOinfervirtual.ml6
-rw-r--r--test/VisitorsRuntimeBootstrap.cppo.ml30
-rw-r--r--test/attic/expr07.ml23
-rw-r--r--test/bad/Makefile7
-rw-r--r--test/bad/conflict.ml25
-rw-r--r--test/bad/conflict_at_name.ml17
-rw-r--r--test/bad/conflict_atat_name.ml15
-rw-r--r--test/bad/datacon.ml11
-rw-r--r--test/bad/datacon_at_name.ml10
-rw-r--r--test/bad/visitors.t49
-rw-r--r--test/bench.ml136
-rw-r--r--test/build.ml10
-rw-r--r--test/cil_types.ml1811
-rw-r--r--test/cil_types.ml.orig1775
-rw-r--r--test/cil_types_polymorphic.ml1780
-rw-r--r--test/cloud.cppo.ml22
-rw-r--r--test/delayed_tree.ml435
-rw-r--r--test/dictionary.ml14
-rw-r--r--test/dune115
-rw-r--r--test/expr.ml3
-rw-r--r--test/expr00.ml4
-rw-r--r--test/expr00.mli9
-rw-r--r--test/expr00endo.ml4
-rw-r--r--test/expr00fold.ml4
-rw-r--r--test/expr00fold2.ml4
-rw-r--r--test/expr01.ml4
-rw-r--r--test/expr01use.ml25
-rw-r--r--test/expr01use_variant.ml20
-rw-r--r--test/expr02.ml4
-rw-r--r--test/expr03.ml4
-rw-r--r--test/expr04.ml13
-rw-r--r--test/expr05.ml4
-rw-r--r--test/expr05lexico.ml20
-rw-r--r--test/expr05lexico_test.ml11
-rw-r--r--test/expr06.ml16
-rw-r--r--test/expr08.ml18
-rw-r--r--test/expr08double.ml10
-rw-r--r--test/expr08extra.ml15
-rw-r--r--test/expr11.ml4
-rw-r--r--test/expr12.ml4
-rw-r--r--test/expr13.ml10
-rw-r--r--test/expr13double.ml10
-rw-r--r--test/expr13extra.ml26
-rw-r--r--test/expr14.ml20
-rw-r--r--test/expr15.ml4
-rw-r--r--test/expr15b.ml10
-rw-r--r--test/expr15c.ml5
-rw-r--r--test/expr16.ml4
-rw-r--r--test/expr17.ml4
-rw-r--r--test/expr_info.ml8
-rw-r--r--test/expr_info_mapreduce.ml8
-rw-r--r--test/expr_info_mapreduce_test.ml29
-rw-r--r--test/expr_info_mapreduce_use.ml15
-rw-r--r--test/expr_info_polymorphic.ml9
-rw-r--r--test/expr_info_polymorphic_use.ml15
-rw-r--r--test/expr_info_polymorphic_use_test.ml27
-rw-r--r--test/expr_info_use.ml17
-rw-r--r--test/expr_redef.ml4
-rw-r--r--test/fold.ml18
-rw-r--r--test/hexpr_polymorphic.ml52
-rw-r--r--test/mapReduce.ml9
-rw-r--r--test/map_from_fold.ml37
-rw-r--r--test/map_from_fold.mli6
-rw-r--r--test/monomorphic.ml11
-rw-r--r--test/monopoly.ml18
-rw-r--r--test/oexpr_polymorphic.ml21
-rw-r--r--test/opaque.ml21
-rw-r--r--test/point.ml4
-rw-r--r--test/point.mli2
-rw-r--r--test/polyclass.ml8
-rw-r--r--test/ppx_import/dune11
-rw-r--r--test/ppx_import/expr.ml3
-rw-r--r--test/ppx_import/expr_import.ml3
-rw-r--r--test/ppx_import/expr_import_opaque.ml3
-rw-r--r--test/prefixes.ml23
-rw-r--r--test/test00.ml11
-rw-r--r--test/test01.ml11
-rw-r--r--test/test02.cppo.ml33
-rw-r--r--test/test03.ml63
-rw-r--r--test/test04.ml16
-rw-r--r--test/test05.ml16
-rw-r--r--test/test06.ml38
-rw-r--r--test/test07.ml49
-rw-r--r--test/testallprims.cppo.ml30
-rw-r--r--visitors.opam23
143 files changed, 31587 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..80a7f4c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+*~
+_build
+.merlin
+*.processed.ml
+doc/manual.pdf
+dune-workspace.versions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..dd8061e
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,3 @@
+François Pottier
+Inria Paris
+francois.pottier@inria.fr
diff --git a/CHANGES.md b/CHANGES.md
new file mode 100644
index 0000000..83289db
--- /dev/null
+++ b/CHANGES.md
@@ -0,0 +1,133 @@
+# Changes
+
+## 2021/06/08
+
+* Replace a reference to the `Parser` module in `ppxlib` with a reference to
+ the `Parser` module in `compiler-libs`, so as to remain compatible with the
+ next version of `ppxlib` (> 0.22.0), where the type `token` is abstract.
+ (Contributed by Sonja Heinze.)
+
+## 2021/01/27
+
+* Switch to version 0.22.0 of `ppxlib`, which internally uses the abstract
+ syntax tree of OCaml 4.12.
+ (Contributed by Sonja Heinze.)
+
+* Relax our requirement from OCaml 4.07 to OCaml 4.05.
+
+## 2021/01/27
+
+* Switch to version 5.0 of `ppx_deriving`.
+ (At present, this implies requiring OCaml 4.07, but this may be relaxed
+ to OCaml 4.05 in the future, I am told.)
+ Depend on `ppxlib` instead of `ppx_tools`.
+ Remove the dependency on `cppo`.
+ (Contributed by Kate Deplaix.)
+
+## 2020/02/07
+
+* Avoid references to `Pervasives` in the generated code.
+
+* Switch from `ocamlbuild` to `dune` to compile `visitors`.
+
+## 2018/05/13
+
+* Fixes in `_tags` and `META` so as to allow `visitors`
+ to be used in `jbuilder` (`dune`) projects.
+ (Contributed by Armaël Guéneau.)
+
+## 2018/03/06
+
+* Warn when the visitor methods for two distinct types or two distinct data
+ constructors have the same name, as this results in an OCaml type error
+ or multiply-defined-method error. (Reported by Gabriel Radanne.)
+
+## 2017/11/24
+
+* Added compatibility with OCaml 4.06.0.
+
+* Fixed the internal function `occurs_type` in the case of polymorphic types.
+ This should make no observable difference, as this function is used only
+ to produce an error message in a corner case.
+
+## 2017/08/28
+
+* Added compatibility with OCaml 4.05.0.
+
+## 2017/07/25
+
+* Updated `src/Makefile` to allow compilation on systems where `ocamlopt` is
+ missing. (Suggested by Ralf Treinen.)
+
+## 2017/04/20
+
+* New settings `visit_prefix`, `build_prefix`, and `fail_prefix` can be used
+ to control which prefixes are used in generated method names. (This feature
+ was suggested by Philip Hölzenspies.)
+
+## 2017/04/04
+
+* Extended backward compatibility to OCaml 4.02.2. (Thanks to Benjamin Farinier.)
+
+## 2017/03/17
+
+* New attributes `@build` and `@@build` can be attached to record type
+ declarations and data constructors, so as to alter the construction code that
+ is used in `map`, `endo`, and `mapreduce` visitors. See the documentation for
+ details. (This feature was suggested by Reuben Rowe.)
+
+## 2017/03/15
+
+* New attributes `@name` and `@@name` can be attached to types, type declarations,
+ and data constructors, so as to alter the names of the generated methods. See
+ the documentation for details. (This feature was suggested by Reuben Rowe.)
+
+## 2017/03/08
+
+* A new option `polymorphic = true` allows generating visitor methods with
+ polymorphic types. With `polymorphic = true`, a type variable `'a` is
+ handled by a visitor *function* `visit_'a`, which is passed as an argument
+ to every visitor method; whereas, with `polymorphic = false`, a type
+ variable `'a` is handled by a virtual visitor *method* `visit_'a`.
+ With `polymorphic = true`, visitor classes compose better,
+ and irregular algebraic data types are supported.
+ See the documentation for more details.
+ (This feature was suggested by Reuben Rowe.)
+
+## 2017/03/03
+
+* A new option `data = false` allows suppressing the generation of visitor
+ methods for data constructors. This makes the generated visitor slightly
+ simpler and faster, but less customizable.
+
+* A new option `nude = true` allows *not* implicitly inheriting the class
+ `VisitorsRuntime.<variety>`.
+
+## 2017/02/15
+
+* `Makefile.preprocess` is now installed with the package, so users can rely on it
+ without needing to copy it. See the documentation for instructions.
+
+## 2017/02/13
+
+* Added a new variety of visitors, `mapreduce`. This visitor computes a pair of a
+ data structure (like a `map` visitor) and a summary (like a `reduce` visitor).
+ This can be used to annotate every tree node with information about the
+ subtree that lies below it. See the documentation for an example.
+
+## 2017/02/09
+
+* Documentation: added a new subsection on OCaml objects,
+ entitled "Where the expressiveness of OCaml's type system falls short".
+ This section explains why `map` cannot be a subclass of `fold`,
+ even though it should be.
+
+## 2017/01/31
+
+* Documentation: added an example of constructing a lexicographic ordering.
+
+* Documentation: discussed generating visitors for existing types and `ppx_import`.
+
+## 2017/01/26
+
+* Initial release.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..4362b49
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,502 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/Makefile.preprocess b/Makefile.preprocess
new file mode 100644
index 0000000..655c7aa
--- /dev/null
+++ b/Makefile.preprocess
@@ -0,0 +1,46 @@
+# This Makefile allows running visitors as a preprocessor,
+# so as to inspect the generated code and possibly include
+# it in a TeX document.
+
+# This assumes the visitors package is installed.
+
+# The rewriting command.
+PPX := `ocamlfind query ppx_deriving`/ppx_deriving \
+ `ocamlfind query visitors`/ppx/ppx_deriving_visitors.cma
+REWRITE := ocamlfind ppx_tools/rewriter -ppx '$(PPX)'
+
+# Use GNU sed to extract the generated code.
+# This requires GNU sed 3.95 or above, I am told.
+SED := $(shell if command -v gsed >/dev/null ; then echo gsed ; else echo sed ; fi)
+EXTRACT := $(SED) -e '/VISITORS.BEGIN/,/VISITORS.END/!d;//d'
+
+# Fix some deficiencies of OCaml's code printer.
+# -- Force a space after a comma.
+# -- Force a space after an ordinary letter and before [=].
+# -- Replace multiple consecutive spaces with a single space.
+# This destroys indentation; we restore it afterwards.
+# -- Remove a space before a comma or closing parenthesis.
+# -- Force a line break after [in], unless there is one already.
+# -- Force a line break after [| ... ->] on a line by itself, unless there is one already.
+# -- Force a line break after [method ... =], unless there is one already.
+# -- Remove the line break between [=] and [object].
+# -- Replace [fun x y -> fun ] with [fun x y ], so multiple-argument functions are prettier.
+# Do this twice, so we can handle functions of arity up to 3. (Yes, this is very ad hoc.)
+BEAUTIFY := \
+ | $(SED) -e 's/,/, /g' \
+ | $(SED) -e 's/\([a-zA-Z_)]\)=/\1 =/g' \
+ | $(SED) -e 's/ / /g' \
+ | $(SED) -e 's/ \([,)]\)/\1/g' \
+ | $(SED) -e 's/ in / in\n/g' \
+ | $(SED) -e 's/^\( *|.* ->\) /\1\n/g' \
+ | $(SED) -e 's/\(method[^=]*=\) /\1\n/g' \
+ | perl -0777 -pe 's/=\n *object/= object/gs' \
+ | perl -0777 -pe "s/fun ([a-zA-Z0-9_' ]+) ->\n *fun /fun \1 /gs" \
+ | perl -0777 -pe "s/fun ([a-zA-Z0-9_' ]+) ->\n *fun /fun \1 /gs" \
+
+# Use ocp-indent to beautify the generated code.
+INDENT := ocp-indent --config=JaneStreet,match_clause=4
+
+%.processed.ml: %.ml
+ @ echo Preprocessing $<...
+ @ $(REWRITE) $< | $(EXTRACT) $(BEAUTIFY) | $(INDENT) > $@
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0fa8da4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,26 @@
+An OCaml syntax extension (technically, a ppx_deriving plugin) which generates
+object-oriented visitors for traversing and transforming data structures.
+
+Here is the [documentation of the latest released version](http://gallium.inria.fr/~fpottier/visitors/manual.pdf).
+
+The easiest way of installing the latest released version of this package is
+via `opam`, the OCaml package manager.
+```bash
+opam update
+opam install visitors
+```
+
+To install the latest development version, also via `opam`, please proceed as follows:
+```bash
+ git clone https://gitlab.inria.fr/fpottier/visitors.git
+ cd visitors
+ make pin
+```
+
+To install the latest development version, outside of `opam`, please proceed as follows:
+```bash
+ git clone https://gitlab.inria.fr/fpottier/visitors.git
+ cd visitors
+ opam install . --deps-only
+ make install
+```
diff --git a/changelog b/debian/changelog
index db45044..db45044 100644
--- a/changelog
+++ b/debian/changelog
diff --git a/control b/debian/control
index 36a2d78..36a2d78 100644
--- a/control
+++ b/debian/control
diff --git a/copyright b/debian/copyright
index fa1ca82..fa1ca82 100644
--- a/copyright
+++ b/debian/copyright
diff --git a/gbp.conf b/debian/gbp.conf
index cec628c..cec628c 100644
--- a/gbp.conf
+++ b/debian/gbp.conf
diff --git a/libppx-visitors-ocaml-doc.doc-base b/debian/libppx-visitors-ocaml-doc.doc-base
index 1931a08..1931a08 100644
--- a/libppx-visitors-ocaml-doc.doc-base
+++ b/debian/libppx-visitors-ocaml-doc.doc-base
diff --git a/libppx-visitors-ocaml-doc.docs b/debian/libppx-visitors-ocaml-doc.docs
index 56a14e1..56a14e1 100644
--- a/libppx-visitors-ocaml-doc.docs
+++ b/debian/libppx-visitors-ocaml-doc.docs
diff --git a/patches/series b/debian/patches/series
index e69de29..e69de29 100644
--- a/patches/series
+++ b/debian/patches/series
diff --git a/rules b/debian/rules
index 330b78b..330b78b 100755
--- a/rules
+++ b/debian/rules
diff --git a/source/format b/debian/source/format
index 163aaf8..163aaf8 100644
--- a/source/format
+++ b/debian/source/format
diff --git a/tests/control b/debian/tests/control
index dceeccc..dceeccc 100644
--- a/tests/control
+++ b/debian/tests/control
diff --git a/tests/weight b/debian/tests/weight
index b5b614b..b5b614b 100755
--- a/tests/weight
+++ b/debian/tests/weight
diff --git a/tests/weight.ml b/debian/tests/weight.ml
index 33eb9b1..33eb9b1 100644
--- a/tests/weight.ml
+++ b/debian/tests/weight.ml
diff --git a/watch b/debian/watch
index 581a47b..581a47b 100644
--- a/watch
+++ b/debian/watch
diff --git a/doc/.gitignore b/doc/.gitignore
new file mode 100644
index 0000000..4eb332a
--- /dev/null
+++ b/doc/.gitignore
@@ -0,0 +1,27 @@
+# TeX.
+main.pdf
+talk.pdf
+*.aux
+*.aux.bak
+*.bbl
+*.blg
+*.log
+*.out
+*.nav
+*.snm
+*.toc
+*.vrb
+
+# WhizzyTeX.
+._whizzy*
+_whizzy*
+*.raux
+*.wdvi
+*.dvi
+*.waux
+*.fmt
+
+# latexmk
+*.fdb_latexmk
+*.fls
+*.synctex.gz
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..e7eaa77
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,22 @@
+export VISITORS_BUILDING_DOCUMENTATION=true
+
+include ../Makefile.preprocess
+
+export TEXINPUTS=.:../test:../test/ppx_import:
+
+SOURCEDIRS := ../test,../test/ppx_import
+ML := $(shell ls {$(SOURCEDIRS)}/*.ml | grep -v cppo | grep -v processed)
+PROCESSED := $(patsubst %.ml,%.processed.ml,$(ML))
+
+.PHONY: all loop clean sources
+
+all: sources
+ latexmk -g -pdf manual
+
+loop: sources
+ latexmk -pdf -pvc manual
+
+clean:
+ rm -f *.log *.aux *.bbl *.blg *.out *.toc *~ manual.pdf
+
+sources: $(wildcard *.tex) $(wildcard *.bib) $(wildcard *.sty) $(ML) $(PROCESSED)
diff --git a/doc/OOinfererror.ml b/doc/OOinfererror.ml
new file mode 100644
index 0000000..38d0d65
--- /dev/null
+++ b/doc/OOinfererror.ml
@@ -0,0 +1,6 @@
+class virtual int_cell = object (self)
+ val mutable x = 0
+ method get = x
+ method set y = x <- self#check y
+ method virtual check: _
+end
diff --git a/doc/OOinfererroragain.ml b/doc/OOinfererroragain.ml
new file mode 100644
index 0000000..ff90009
--- /dev/null
+++ b/doc/OOinfererroragain.ml
@@ -0,0 +1,6 @@
+class virtual ['a] cell (init) = object (self)
+ val mutable x = init
+ method get = x
+ method set y = x <- self#check y
+ method virtual check: 'a -> _
+end
diff --git a/doc/convention.tex b/doc/convention.tex
new file mode 100644
index 0000000..a01c0f3
--- /dev/null
+++ b/doc/convention.tex
@@ -0,0 +1,49 @@
+\begin{figure}[p]
+\begin{mdframed}[backgroundcolor=green!10]
+\begin{lstlisting}
+class ['self] iter : object ('self)
+ method private visit_list: 'env 'a .
+ ('env -> 'a -> unit) -> 'env -> 'a list -> unit
+end
+class ['self] map : object ('self)
+ method private visit_list: 'env 'a 'b .
+ ('env -> 'a -> 'b) -> 'env -> 'a list -> 'b list
+end
+class ['self] endo : object ('self)
+ method private visit_list: 'env 'a .
+ ('env -> 'a -> 'a) -> 'env -> 'a list -> 'a list
+end
+class virtual ['self] reduce : object ('self)
+ inherit ['s] monoid
+ method private visit_list: 'env 'a .
+ ('env -> 'a -> 's) -> 'env -> 'a list -> 's
+end
+class virtual ['self] mapreduce : object ('self)
+ inherit ['s] monoid
+ method private visit_list: 'env 'a 'b .
+ ('env -> 'a -> 'b * 's) -> 'env -> 'a list -> 'b list * 's
+end
+class ['self] iter2 : object ('self)
+ method private visit_list: 'env 'a 'b .
+ ('env -> 'a -> 'b -> unit) -> 'env -> 'a list -> 'b list -> unit
+end
+class ['self] map2 : object ('self)
+ method private visit_list: 'env 'a 'b 'c .
+ ('env -> 'a -> 'b -> 'c) -> 'env -> 'a list -> 'b list -> 'c list
+end
+class virtual ['self] reduce2 : object ('self)
+ inherit ['s] monoid
+ method private visit_list: 'env 'a 'b .
+ ('env -> 'a -> 'b -> 's) -> 'env -> 'a list -> 'b list -> 's
+end
+class virtual ['self] mapreduce2 : object ('self)
+ inherit ['s] monoid
+ method private visit_list: 'env 'a 'b 'c .
+ ('env -> 'a -> 'b -> 'c * 's) ->
+ 'env -> 'a list -> 'b list -> 'c list * 's
+end
+\end{lstlisting}
+\end{mdframed}
+\caption{Conventional types of polymorphic visitor methods}
+\label{fig:convention}
+\end{figure}
diff --git a/doc/dune b/doc/dune
new file mode 100644
index 0000000..a62d561
--- /dev/null
+++ b/doc/dune
@@ -0,0 +1 @@
+(include dune.manual)
diff --git a/doc/dune.manual b/doc/dune.manual
new file mode 100644
index 0000000..b52ddb9
--- /dev/null
+++ b/doc/dune.manual
@@ -0,0 +1,14 @@
+;; This file is concatenated at the end of the file "dune"
+;; by the release script, so the documentation is installed
+;; only on release branches.
+
+;; The documentation is currently built outside of dune's control
+;; by doc/Makefile.
+
+(install
+ (section doc)
+ (files
+ manual.pdf
+ )
+ (package visitors)
+)
diff --git a/doc/english.bib b/doc/english.bib
new file mode 100644
index 0000000..1d5f136
--- /dev/null
+++ b/doc/english.bib
@@ -0,0 +1,15090 @@
+@String{acmp = "ACM Press"}
+
+@String{acsac = "Annual Computer Security Applications Conference"}
+
+@String{acta = "Acta Informatica"}
+
+@String{afp = "Advanced Functional Programming"}
+
+@String{amast = "International Conference on Algebraic Methodology and
+ Software Technology (AMAST)"}
+
+@String{ams = "American Mathematical Society"}
+
+@String{ap = "Academic Press"}
+
+@String{apal = "Annals of Pure and Applied Logic"}
+
+@String{aplas = "Asian Symposium on Programming Languages and Systems
+ (APLAS)"}
+
+@String{asian = "Asian Computer Science Conference ({ASIAN})"}
+
+@String{aw = "Addison-Wesley"}
+
+@String{cacm = "Communications of the {ACM}"}
+
+@String{cade = "International Conference on Automated Deduction
+ (CADE)"}
+
+@String{carleton = "Carleton Scientific"}
+
+@String{cassis = "Construction and Analysis of Safe, Secure and
+ Interoperable Smart devices (CASSIS)"}
+
+@String{cav = "Computer Aided Verification (CAV)"}
+
+@String{cc = "Compiler Construction (CC)"}
+
+@String{cdcs = "International Conference on Distributed Computing
+ Systems (CDCS)"}
+
+@String{cj = "Computer Journal"}
+
+@String{computer = "Computer"}
+
+@String{concur = "International Conference on Concurrency Theory
+ (CONCUR)"}
+
+@String{cpp = "Certified Programs and Proofs (CPP)"}
+
+@String{csfw = "{IEEE} Computer Security Foundations Workshop"}
+
+@String{csl = "Computer Science Logic"}
+
+@String{cup = "Cambridge University Press"}
+
+@String{dac = "Design Automation Conference (DAC)"}
+
+@String{decsrc = "Digital Equipment Corporation, Systems Research
+ Center"}
+
+@String{dls = "Symposium on Dynamic Languages"}
+
+@String{dspg = "Domain-Specific Program Generation (DSPG)"}
+
+@String{ecoop = "European Conference on Object-Oriented Programming
+ (ECOOP)"}
+
+@String{ellis = "Ellis Horwood"}
+
+@String{elsevier = "Elsevier Science"}
+
+@String{entcs = "Electronic Notes in Theoretical Computer Science"}
+
+@String{esop = "European Symposium on Programming (ESOP)"}
+
+@String{esorics = "European Symposium on Research in Computer Security"}
+
+@String{eurosys = "EuroSys"}
+
+@String{fac = "Formal Aspects of Computing"}
+
+@String{fics = "International workshop on Fixed Points in Computer
+ Science (FICS)"}
+
+@String{flops = "Functional and Logic Programming"}
+
+@String{fm = "Formal Methods (FM)"}
+
+@String{fmco = "Formal Methods for Components and Objects"}
+
+@String{fmsd = "Formal Methods in System Design"}
+
+@String{fool = "Foundations of Object-Oriented Languages (FOOL)"}
+
+@String{fopara = "Foundational and Practical Aspects of Resource
+ Analysis"}
+
+@String{fosad = "Foundations of Security Analysis and Design"}
+
+@String{fossacs = "Foundations of Software Science and Computation
+ Structures ({FOSSACS})"}
+
+@String{fpca = "Functional Programming Languages and Computer
+ Architecture (FPCA)"}
+
+@String{fse = "Workshop on Foundations of Software Engineering"}
+
+@String{fsttcs = "Foundations of Software Technology and Theoretical
+ Computer Science (FSTTCS)"}
+
+@String{ftfjp = "Formal Techniques for {Java}-like Programs"}
+
+@String{fundamenta = "Fundamenta Informaticæ"}
+
+@String{gcse = "Generative and Component-Based Software Engineering"}
+
+@String{gpce = "Generative Programming and Component Engineering
+ (GPCE)"}
+
+@String{hav = "Heap Analysis and Verification (HAV)"}
+
+@String{hilt = "ACM SIGAda Annual Conference on High Integrity
+ Language Technology (HILT)"}
+
+@String{hlcl = "High-Level Concurrent Languages (HLCL)"}
+
+@String{hoots = "Higher Order Operational Techniques in Semantics
+ (HOOTS)"}
+
+@String{hopl = "History of Programming Languages"}
+
+@String{hosc = "Higher-Order and Symbolic Computation"}
+
+@String{hotpar = "USENIX Conference on Hot Topics in Parallelism
+ (HotPar)"}
+
+@String{hs = "Haskell symposium"}
+
+@String{hw = "Haskell workshop"}
+
+@String{ic = "Information and Computation"}
+
+@String{icalp = "International Colloquium on Automata, Languages and
+ Programming"}
+
+@String{icfem = "International Conference on Formal Engineering Methods
+ (ICFEM)"}
+
+@String{icfp = "International Conference on Functional Programming
+ (ICFP)"}
+
+@String{iclp = "International Conference on Logic Programming (ICLP)"}
+
+@String{icse = "International Conference on Software Engineering
+ ({ICSE})"}
+
+@String{ictl = "International Conference on Temporal Logic (ICTL)"}
+
+@String{ie = "InterEditions"}
+
+@String{ifiptcs = "IFIP International Conference on Theoretical Computer
+ Science (TCS)"}
+
+@String{ifl = "Implementation of Functional Languages (IFL)"}
+
+@String{ijcai = "International Joint Conferences on Artificial
+ Intelligence"}
+
+@String{ijfcs = "International Journal of Foundations of Computer
+ Science"}
+
+@String{ipl = "Information Processing Letters"}
+
+@String{issta = "International Symposium on Software Testing and
+ Analysis (ISSTA)"}
+
+@String{ist = "Information and Software Technology"}
+
+@String{ita = "Informatique théorique et applications"}
+
+@String{itp = "Interactive Theorem Proving (ITP)"}
+
+@String{itrs = "Workshop on Intersection Types and Related Systems
+ (ITRS)"}
+
+@String{jacm = "Journal of the {ACM}"}
+
+@String{jar = "Journal of Automated Reasoning"}
+
+@String{jfla = "Journées Françaises des Langages Applicatifs
+ (JFLA)"}
+
+@String{jfp = "Journal of Functional Programming"}
+
+@String{jfr = "Journal of Formalized Reasoning"}
+
+@String{jlap = "Journal of Logic and Algebraic Programming"}
+
+@String{jlc = "Journal of Logic and Computation"}
+
+@String{jlp = "Journal of Logic Programming"}
+
+@String{jot = "Journal of Object Technology"}
+
+@String{jsc = "Journal of Symbolic Computation"}
+
+@String{jucs = "Journal of Universal Computer Science"}
+
+@String{kluwer = "Kluwer"}
+
+@String{lfm = "Workshop on Logical Frameworks and Meta-Languages
+ (LFM)"}
+
+@String{lfp = "ACM Symposium on Lisp and Functional Programming
+ (LFP)"}
+
+@String{lics = "Logic in Computer Science (LICS)"}
+
+@String{lipics = "{Leibniz} International Proceedings in Informatics"}
+
+@String{lmcs = "Logical Methods in Computer Science"}
+
+@String{lnai = "Lecture Notes in Artificial Intelligence"}
+
+@String{lncs = "Lecture Notes in Computer Science"}
+
+@String{lola = "Workshop on Syntax and Semantics of Low Level
+ Languages"}
+
+@String{loplas = "ACM Letters on Programming Languages and Systems"}
+
+@String{lpar = "Logic for Programming Artificial Intelligence and
+ Reasoning (LPAR)"}
+
+@String{lsc = "Lisp and Symbolic Computation"}
+
+@String{merlin = "ACM Workshop on Mechanized Reasoning about Languages
+ with Variable Binding"}
+
+@String{mfcs = "International Symposium on Mathematical Foundations of
+ Computer Science"}
+
+@String{mfps = "Mathematical Foundations of Programming Semantics"}
+
+@String{mitp = "MIT Press"}
+
+@String{ml = "ACM Workshop on ML"}
+
+@String{mlapp = "ACM Workshop on ML and its Applications"}
+
+@String{mpc = "Mathematics of Program Construction (MPC)"}
+
+@String{mscs = "Mathematical Structures in Computer Science"}
+
+@String{msfp = "ACM SIGPLAN Workshop on Mathematically Structured
+ Functional Programming (MSFP)"}
+
+@String{ndss = "Internet Society Symposium on Network and Distributed
+ System Security"}
+
+@String{nfm = "{NASA} Formal Methods (NFM)"}
+
+@String{njc = "Nordic Journal of Computing"}
+
+@String{notices = "{ACM} {SIGPLAN} Notices"}
+
+@String{nspw = "New Security Paradigms Workshop"}
+
+@String{onward = "{ACM} Symposium on New Ideas in Programming and
+ Reflections on Software (Onward!)"}
+
+@String{oopsla = "Object-Oriented Programming, Systems, Languages, and
+ Applications (OOPSLA)"}
+
+@String{oopslacomp = "Companion to Object-Oriented Programming, Systems,
+ Languages, and Applications (OOPSLA)"}
+
+@String{padl = "Practical Aspects of Declarative Languages (PADL)"}
+
+@String{palgrave = "Palgrave Macmillan"}
+
+@String{pcc = "International Workshop on Proof-Carrying Code (PCC)"}
+
+@String{pepm = "{ACM} Workshop on Evaluation and Semantics-Based
+ Program Manipulation ({PEPM})"}
+
+@String{pi = "Proceedings in Informatics"}
+
+@String{pieee = "Proceedings of the IEEE"}
+
+@String{pldi = "{Programming Language Design and Implementation
+ (PLDI)}"}
+
+@String{plilp = "Programming Languages: Implementations, Logics, and
+ Programs (PLILP)"}
+
+@String{plpv = "Programming Languages Meets Program Verification
+ (PLPV)"}
+
+@String{popl = "Principles of Programming Languages ({POPL})"}
+
+@String{ppcp = "International Workshop on Principles and Practice of
+ Constraint Programming (PPCP)"}
+
+@String{ppdp = "Principles and Practice of Declarative Programming
+ (PPDP)"}
+
+@String{prentice = "Prentice Hall"}
+
+@String{rairo = "RAIRO Theoretical Informatics and Applications"}
+
+@String{rta = "Rewriting Techniques and Applications (RTA)"}
+
+@String{saig = "International Workshop on Semantics, Applications, and
+ Implementation of Program Generation (SAIG)"}
+
+@String{sas = "Static Analysis Symposium (SAS)"}
+
+@String{scp = "Science of Computer Programming"}
+
+@String{siamjc = "SIAM Journal on Computing"}
+
+@String{sigops = "ACM Operating Systems Review"}
+
+@String{sle = "Software Language Engineering"}
+
+@String{snapl = "Summit on Advances in Programming Languages (SNAPL)"}
+
+@String{soda = "Symposium on Discrete Algorithms (SODA)"}
+
+@String{sp = "{IEEE} Symposium on Security and Privacy (S\&P)"}
+
+@String{spe = "Software: Practice and Experience"}
+
+@String{springer = "Springer"}
+
+@String{stoc = "ACM Symposium on Theory of Computing"}
+
+@String{sttt = "Software Tools for Technology Transfer"}
+
+@String{surveys = "{ACM} Computing Surveys"}
+
+@String{tacas = "Tools and Algorithms for Construction and Analysis of
+ Systems (TACAS)"}
+
+@String{tacs = "International Symposium on Theoretical Aspects of
+ Computer Software (TACS)"}
+
+@String{tams = "Transactions of the American Mathematical Society"}
+
+@String{taoop = "Theoretical Aspects Of Object-Oriented Programming:
+ Types, Semantics and Language Design"}
+
+@String{tapos = "Theory and Practice of Object Systems"}
+
+@String{tapsoft = "Theory and Practice of Software Development
+ ({TAPSOFT})"}
+
+@String{tcs = "Theoretical Computer Science"}
+
+@String{tcsconf = "IFIP International Conference on Theoretical Computer
+ Science (TCS)"}
+
+@String{tfp = "Trends in Functional Programming (TFP)"}
+
+@String{tic = "Types in Compilation (TIC)"}
+
+@String{tissec = "ACM Transactions on Information and System Security"}
+
+@String{tlca = "Typed Lambda Calculi and Applications (TLCA)"}
+
+@String{tldi = "Types in Language Design and Implementation (TLDI)"}
+
+@String{tocl = "ACM Transactions on Computational Logic"}
+
+@String{tods = "ACM Transactions on Database Systems"}
+
+@String{toplas = "ACM Transactions on Programming Languages and
+ Systems"}
+
+@String{tose = "IEEE Transactions on Software Engineering"}
+
+@String{tosem = "ACM Transactions on Software Engineering and
+ Methodology"}
+
+@String{tphol = "Theorem Proving in Higher Order Logics (TPHOLs)"}
+
+@String{types = "Types for Proofs and Programs"}
+
+@String{vmcai = "Verification, Model Checking and Abstract
+ Interpretation (VMCAI)"}
+
+@String{vstte = "Verified Software: Theories, Tools and Experiments"}
+
+@String{wgp = "Workshop on Generic Programming"}
+
+@String{wollic = "Workshop on Logic, Language, Information and
+ Computation (WoLLIC)"}
+
+@String{wrla = "International Workshop on Rewriting Logic and its
+ Applications (WRLA)"}
+
+@String{wsa = "International Workshop on Static Analysis (WSA)"}
+
+@String{wwv = "Workshop on Automated Specification and Verification
+ of Web Systems"}
+
+@InProceedings{abadi-blanchet-01,
+ author = "Martín Abadi and Bruno Blanchet",
+ title = "Secrecy Types for Asymmetric Communication",
+ booktitle = fossacs,
+ year = "2001",
+ volume = "2030",
+ series = lncs,
+ publisher = springer,
+ pages = "25--41",
+ URL = "http://www.di.ens.fr/~blanchet/publications/AbadiBlanchetFOSSACS01.html",
+}
+
+@Article{abadi-cardelli-94,
+ author = "Mart{\'\i}n Abadi and Luca Cardelli",
+ title = "A Theory of Primitive Objects: Untyped and First-Order
+ Systems",
+ journal = ic,
+ year = "1996",
+ volume = "125",
+ number = "2",
+ pages = "78--102",
+ URL = "http://research.microsoft.com/Users/luca/Papers/PrimObj1stOrder.pdf",
+}
+
+@Article{abadi-cardelli-94b,
+ author = "Mart{\'\i}n Abadi and Luca Cardelli",
+ title = "A Theory of Primitive Objects: Second-Order Systems",
+ journal = scp,
+ year = "1995",
+ volume = "25",
+ number = "2--3",
+ pages = "81--116",
+ URL = "http://research.microsoft.com/Users/luca/Papers/PrimObj2ndOrder.pdf",
+}
+
+@InProceedings{abadi-dcc-99,
+ title = "A Core Calculus of Dependency",
+ author = "Martín Abadi and Anindya Banerjee and Nevin Heintze
+ and Jon G. Riecke",
+ booktitle = popl,
+ year = "1999",
+ pages = "147--160",
+ URL = "http://www.soe.ucsc.edu/~abadi/Papers/flowpopl.ps",
+}
+
+@InProceedings{abadi-fiore-96,
+ author = "Mart{\'\i}n Abadi and Marcelo P. Fiore",
+ title = "Syntactic Considerations on Recursive Types",
+ booktitle = lics,
+ pages = "242--252",
+ year = "1996",
+ URL = "http://www.soe.ucsc.edu/~abadi/Papers/rec.ps",
+}
+
+@InProceedings{abadi-lampson-levy-96,
+ title = "Analysis and Caching of Dependencies",
+ author = "Martín Abadi and Butler Lampson and Jean-Jacques
+ Lévy",
+ pages = "83--91",
+ booktitle = icfp,
+ year = "1996",
+ URL = "http://www.soe.ucsc.edu/~abadi/Papers/make-preprint.ps",
+}
+
+@Article{abadi-pierce-plotkin-91,
+ author = "Martín Abadi and Benjamin Pierce and Gordon Plotkin",
+ title = "Faithful Ideal Models for Recursive Polymorphic
+ Types",
+ journal = "International Journal of Foundations of Computer
+ Science",
+ volume = "2",
+ number = "1",
+ year = "1991",
+ pages = "1--21",
+ URL = "http://www.cis.upenn.edu/~bcpierce/papers/ideals.ps",
+}
+
+@Article{abel-04,
+ author = "Andreas Abel",
+ title = "Termination Checking with Types",
+ journal = rairo,
+ year = "2004",
+ volume = "38",
+ number = "4",
+ pages = "277--319",
+ URL = "http://www2.tcs.ifi.lmu.de/~abel/rairo04.pdf",
+}
+
+@InProceedings{abel-haskell-05,
+ author = "Andreas Abel and Marcin Benke and Ana Bove and John
+ Hughes and Ulf Norell",
+ title = "Verifying {Haskell} programs using constructive type
+ theory",
+ booktitle = hw,
+ year = "2005",
+ pages = "62--73",
+ URL = "http://www.tcs.informatik.uni-muenchen.de/~abel/haskell05.pdf",
+}
+
+@InProceedings{abel-miniagda-10,
+ author = "Andreas Abel",
+ title = "{MiniAgda}: Integrating Sized and Dependent Types",
+ booktitle = "Workshop on Partiality And Recursion in Interactive
+ Theorem Provers (PAR)",
+ year = "2010",
+ URL = "http://www2.tcs.ifi.lmu.de/~abel/par10.pdf",
+}
+
+@Article{abramsky-91,
+ author = "Samson Abramsky",
+ title = "Domain Theory in Logical Form",
+ journal = apal,
+ year = "1991",
+ volume = "51",
+ pages = "1--77",
+ URL = "http://web.comlab.ox.ac.uk/oucl/work/samson.abramsky/dtlf.ps.gz",
+}
+
+@InProceedings{abramsky-honda-mccusker-98,
+ author = "Samson Abramsky and Kohei Honda and Guy McCusker",
+ title = "A fully abstract game semantics for general
+ references",
+ booktitle = lics,
+ pages = "334--344",
+ year = "1998",
+ URL = "http://web.comlab.ox.ac.uk/people/Samson.Abramsky/lics98.ps.gz",
+}
+
+@Article{achten-plasmeijer-95,
+ author = "Peter Achten and Marinus J. Plasmeijer",
+ title = "The Ins and Outs of {Clean} {I/O}",
+ journal = jfp,
+ volume = "5",
+ number = "1",
+ year = "1995",
+ pages = "81--110",
+ URL = "http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.17.935",
+}
+
+@TechReport{agerholm-examples-94,
+ author = "Sten Agerholm",
+ title = "{LCF} Examples in {HOL}",
+ institution = "BRICS",
+ year = "1994",
+ number = "RS-94-18",
+ URL = "http://www.brics.dk/RS/94/18/BRICS-RS-94-18.ps.gz",
+}
+
+@TechReport{agerholm-holcpo-94,
+ author = "Sten Agerholm",
+ title = "A {HOL} Basis for Reasoning about Functional
+ Programs",
+ institution = "BRICS",
+ year = "1994",
+ number = "RS-94-44",
+ URL = "http://www.brics.dk/RS/94/44/BRICS-RS-94-44.ps.gz",
+}
+
+@PhdThesis{ahmed-04,
+ author = "Amal Jamil Ahmed",
+ title = "Semantics of Types for Mutable State",
+ school = "Princeton University",
+ year = "2004",
+ URL = "http://www.cs.indiana.edu/~amal/ahmedsthesis.pdf",
+}
+
+@InProceedings{ahmed-appel-virga-02,
+ author = "Amal J. Ahmed and Andrew W. Appel and Roberto Virga",
+ title = "A Stratified Semantics of General References
+ Embeddable in Higher-Order Logic",
+ booktitle = lics,
+ pages = "75--86",
+ year = "2002",
+ URL = "http://www.cs.princeton.edu/sip/pub/stratified-lics02.pdf",
+}
+
+@InProceedings{ahmed-blume-08,
+ author = "Amal Ahmed and Matthias Blume",
+ title = "Typed closure conversion preserves observational
+ equivalence",
+ booktitle = icfp,
+ year = "2008",
+ pages = "157--168",
+ URL = "http://ttic.uchicago.edu/~amal/papers/tccpoe.pdf",
+}
+
+@InProceedings{ahmed-dreyer-rossberg-09,
+ author = "Amal Ahmed and Derek Dreyer and Andreas Rossberg",
+ title = "State-dependent representation independence",
+ booktitle = popl,
+ year = "2009",
+ pages = "340--353",
+ URL = "http://ttic.uchicago.edu/~amal/papers/sdri.pdf",
+}
+
+@InProceedings{ahmed-fluet-morrisett-05,
+ author = "Amal J. Ahmed and Matthew Fluet and Greg Morrisett",
+ title = "A step-indexed model of substructural state",
+ booktitle = icfp,
+ year = "2005",
+ pages = "78--91",
+ URL = "http://www.cs.rit.edu/~mtf/research/substruct-state/ICFP05/icfp05.pdf",
+}
+
+@Article{ahmed-semantic-tal-10,
+ author = "Amal Ahmed and Andrew W. Appel and Christopher D.
+ Richards and Kedar N. Swadi and Gang Tan and Daniel C.
+ Wang",
+ title = "Semantic foundations for typed assembly languages",
+ journal = toplas,
+ volume = "32",
+ number = "3",
+ year = "2010",
+ URL = "http://www.cs.princeton.edu/~appel/papers/sftal.pdf",
+}
+
+@Book{aho-86,
+ author = "Alfred V. Aho and Ravi Sethi and Jeffrey D. Ullman",
+ title = "Compilers: Principles, Techniques, and Tools",
+ publisher = aw,
+ year = "1986",
+}
+
+@Book{aho-89,
+ author = "Alfred Aho and Ravi Sethi and Jeffrey Ullman",
+ title = "Compilateurs: principes, techniques et outils",
+ publisher = ie,
+ year = "1989",
+}
+
+@Book{aho-hopcroft-ullman-74,
+ author = "Alfred V. Aho and John E. Hopcroft and Jeffrey D.
+ Ullman",
+ title = "The Design and Analysis of Computer Algorithms",
+ publisher = aw,
+ year = "1974",
+}
+
+@Book{aho-hopcroft-ullman-83,
+ author = "Alfred V. Aho and John E. Hopcroft and Jeffrey D.
+ Ullman",
+ title = "Data Structures and Algorithms",
+ year = "1983",
+ publisher = aw,
+}
+
+@Article{aho-optim-72,
+ author = "Alfred V. Aho and Jeffrey D. Ullman",
+ title = "Optimization of {LR(k)} parsers",
+ journal = "Journal of Computer and System Sciences",
+ volume = "6",
+ number = "6",
+ pages = "573--602",
+ year = "1972",
+ URL = "http://www.sciencedirect.com/science/article/pii/S002200007280031X",
+}
+
+@Book{aho-ullman-72,
+ author = "Alfred V. Aho and Jeffrey D. Ullman",
+ title = "The theory of parsing, translation, and compiling",
+ year = "1972",
+ publisher = prentice,
+ URL = "http://portal.acm.org/citation.cfm?id=SERIES11430.578789",
+}
+
+@Article{aho-ullman-73,
+ author = "Alfred V. Aho and Jeffrey D. Ullman",
+ title = "A Technique for Speeding up {LR(k)} Parsers",
+ journal = siamjc,
+ volume = "2",
+ number = "2",
+ pages = "106--127",
+ year = "1973",
+ URL = "http://dx.doi.org/10.1137/0202010",
+}
+
+@Article{aiken-bane-98,
+ author = "Alexander Aiken and Manuel Fähndrich and Jeffrey S.
+ Foster and Zhendong Su",
+ title = "A Toolkit for Constructing Type- and Constraint-Based
+ Program Analyses",
+ journal = lncs,
+ volume = "1473",
+ pages = "76--96",
+ year = "1998",
+ URL = "http://theory.stanford.edu/~aiken/publications/papers/tic98.pdf",
+}
+
+@Article{aiken-faehndrich-levien-95,
+ author = "Alexander Aiken and Manuel F{\"a}hndrich and Raph
+ Levien",
+ title = "Better static memory management: improving
+ region-based analysis of higher-order languages",
+ journal = notices,
+ volume = "30",
+ number = "6",
+ pages = "174--185",
+ year = "1995",
+ URL = "http://www.eecs.berkeley.edu/Pubs/TechRpts/1995/CSD-95-866.pdf",
+}
+
+@InProceedings{aiken-faehndrich-mixed-97,
+ author = "Alexander S. Aiken and Manuel F{\"a}hndrich",
+ title = "Program Analysis Using Mixed Term and Set
+ Constraints",
+ pages = "114--126",
+ booktitle = sas,
+ year = "1997",
+ URL = "http://theory.stanford.edu/~aiken/publications/papers/sas97.pdf",
+}
+
+@TechReport{aiken-faehndrich-scale-96,
+ number = "CSD-96-917",
+ institution = "University of California, Berkeley",
+ title = "Making Set-Constraint Based Program Analyses Scale",
+ year = "1996",
+ author = "Alexander S. Aiken and Manuel F{\"a}hndrich",
+ URL = "http://research.microsoft.com/pubs/67469/scw96.pdf",
+}
+
+@TechReport{aiken-faehndrich-subtyping-96,
+ number = "CSD-96-898",
+ institution = "University of California, Berkeley",
+ title = "Subtyping Polymorphic Constrained Types",
+ year = "1996",
+ author = "Alexander S. Aiken and Manuel F{\"a}hndrich",
+}
+
+@Misc{aiken-illyria,
+ author = "Alexander S. Aiken",
+ title = "The {Illyria} system",
+ year = "1994",
+ URL = "http://http.cs.berkeley.edu:80/~aiken/Illyria-demo.html",
+}
+
+@Article{aiken-intro-99,
+ author = "Alexander Aiken",
+ title = "Introduction to Set Constraint-Based Program
+ Analysis",
+ journal = scp,
+ year = "1999",
+ volume = "35",
+ pages = "79--111",
+ URL = "http://theory.stanford.edu/~aiken/publications/papers/scp99.pdf",
+}
+
+@TechReport{aiken-palsberg-wimmers-optimal-96,
+ number = "CSD-96-909",
+ institution = "University of California, Berkeley",
+ title = "Optimal Representations of Polymorphic Types with
+ Subtyping",
+ year = "1996",
+ pages = "31",
+ author = "Alexander S. Aiken and Edward L. Wimmers and Jens
+ Palsberg",
+ URL = "http://digitalassets.lib.berkeley.edu/techreports/ucb/text/CSD-96-909.pdf",
+}
+
+@InProceedings{aiken-wimmers-92,
+ author = "Alexander S. Aiken and Edward L. Wimmers",
+ title = "Solving Systems of Set Constraints",
+ pages = "329--340",
+ booktitle = lics,
+ year = "1992",
+ URL = "http://theory.stanford.edu/~aiken/publications/papers/lics92.pdf",
+}
+
+@InProceedings{aiken-wimmers-93,
+ author = "Alexander S. Aiken and Edward L. Wimmers",
+ booktitle = fpca,
+ publisher = acmp,
+ title = "Type Inclusion Constraints and Type Inference",
+ year = "1993",
+ pages = "31--41",
+ URL = "http://theory.stanford.edu/~aiken/publications/papers/fpca93.pdf",
+}
+
+@InProceedings{aiken-wimmers-lakshman-94,
+ author = "Alexander S. Aiken and Edward L. Wimmers and T. K.
+ Lakshman",
+ booktitle = popl,
+ title = "Soft Typing with Conditional Types",
+ year = "1994",
+ pages = "163--173",
+ URL = "http://theory.stanford.edu/~aiken/publications/papers/popl94.pdf",
+}
+
+@InProceedings{aldrich-borrowing-12,
+ title = "A type system for borrowing permissions",
+ author = "Karl Naden and Robert Bocchino and Jonathan Aldrich
+ and Kevin Bierhoff",
+ booktitle = popl,
+ year = "2012",
+ pages = "557--570",
+ URL = "http://cs.cmu.edu/afs/cs.cmu.edu/Web/People/kbn/pubs/poplBorrowing.pdf",
+}
+
+@InProceedings{aldrich-objects-13,
+ author = "Jonathan Aldrich",
+ title = "The power of interoperability: why objects are
+ inevitable",
+ booktitle = onward,
+ year = "2013",
+ pages = "101--116",
+ URL = "http://www.cs.cmu.edu/~aldrich/papers/objects-essay.pdf",
+}
+
+@Unpublished{aldrich-plaid-10,
+ author = "Jonathan Aldrich",
+ title = "Resource-Based Programming in {Plaid}",
+ note = "Fun Ideas and Thoughts",
+ year = "2010",
+ URL = "http://www.cs.cmu.edu/~aldrich/papers/pldi-fit10.pdf",
+}
+
+@InProceedings{aldrich-typestate-09,
+ author = "Jonathan Aldrich and Joshua Sunshine and Darpan Saini
+ and {Zacha\-ry} Sparks",
+ title = "Typestate-Oriented Programming",
+ booktitle = oopslacomp,
+ pages = "1015--1022",
+ year = "2009",
+ URL = "http://www.cs.cmu.edu/~aldrich/papers/onward2009-state.pdf",
+}
+
+@InProceedings{alias-types-00,
+ author = "Frederick Smith and David Walker and Greg Morrisett",
+ title = "Alias Types",
+ booktitle = esop,
+ pages = "366--381",
+ year = "2000",
+ volume = "1782",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.cs.cornell.edu/talc/papers/alias.pdf",
+}
+
+@InProceedings{allais-cpp-17,
+ author = "Guillaume Allais and James Chapman and Conor McBride
+ and James McKinna",
+ title = "Type-and-scope Safe Programs and Their Proofs",
+ booktitle = cpp,
+ pages = "195--207",
+ year = "2017",
+ URL = "http://gallais.github.io/pdf/cpp2017.pdf",
+}
+
+@InProceedings{almeida-97,
+ author = "Paulo S{\'e}rgio Almeida",
+ title = "Balloon Types: Controlling Sharing of State in Data
+ Types",
+ booktitle = ecoop,
+ year = "1997",
+ pages = "32--59",
+ publisher = springer,
+ series = lncs,
+ volume = "1241",
+ URL = "http://gsd.di.uminho.pt/publications/gsd-1997-04/file/at_download",
+}
+
+@Article{alstrup-al-14,
+ author = "Stephen Alstrup and Mikkel Thorup and Inge Li G{\o}rtz
+ and Theis Rauhe and Uri Zwick",
+ title = "Union-Find with Constant Time Deletions",
+ journal = "{ACM} Transactions on Algorithms",
+ volume = "11",
+ number = "1",
+ pages = "6:1--6:28",
+ year = "2014",
+ URL = "http://doi.acm.org/10.1145/2636922",
+}
+
+@InProceedings{altenkirch-pisigma-10,
+ author = "Thorsten Altenkirch and Nils Anders Danielsson and
+ Andres L{\"o}h and Nicolas Oury",
+ title = "{$\Pi$}{$\Sigma$}: Dependent Types Without the Sugar",
+ booktitle = flops,
+ pages = "40--55",
+ year = "2010",
+ publisher = springer,
+ series = lncs,
+ volume = "6009",
+ URL = "http://www.cs.nott.ac.uk/~txa/publ/pisigma-new.pdf",
+}
+
+@InProceedings{altenkirch-reus-99,
+ author = "Thorsten Altenkirch and Bernhard Reus",
+ title = "Monadic Presentations of Lambda Terms Using
+ Generalized Inductive Types",
+ booktitle = csl,
+ year = "1999",
+ pages = "453--468",
+ publisher = springer,
+ series = lncs,
+ volume = "1683",
+ URL = "http://www.cs.nott.ac.uk/~txa/publ/csl99.pdf",
+}
+
+@Article{amadio-cardelli-93,
+ author = "Roberto M. Amadio and Luca Cardelli",
+ title = "Subtyping Recursive Types",
+ journal = toplas,
+ volume = "15",
+ number = "4",
+ pages = "575--631",
+ year = "1993",
+ URL = "http://research.microsoft.com/Users/luca/Papers/SRT.pdf",
+}
+
+@InProceedings{amadio-regis-gianas-11,
+ author = "Roberto Amadio and Yann R{\'{e}}gis{-}Gianas",
+ title = "Certifying and Reasoning on Cost Annotations of
+ Functional Programs",
+ booktitle = fopara,
+ pages = "72--89",
+ year = "2011",
+ series = lncs,
+ volume = "7177",
+ publisher = springer,
+ URL = "https://hal.inria.fr/inria-00629473v1",
+}
+
+@Article{amadio-regis-gianas-13,
+ title = "Certifying and reasoning about cost annotations of
+ functional programs",
+ author = "Roberto Amadio and Yann R{\'e}gis-Gianas",
+ URL = "https://hal.inria.fr/inria-00629473",
+ journal = hosc,
+ year = "2013",
+}
+
+@InProceedings{america-rutten-88,
+ author = "Pierre America and Jan Rutten",
+ title = "Solving reflexive domain equations in a category of
+ complete metric spaces",
+ booktitle = mfps,
+ pages = "254--288",
+ year = "1988",
+ volume = "298",
+ series = lncs,
+ publisher = springer,
+ URL = "http://dx.doi.org/10.1007/3-540-19020-1_13",
+}
+
+@Article{amighi-15,
+ author = "Afshin Amighi and Christian Haack and Marieke Huisman
+ and Clément Hurlin",
+ title = "Permission-based separation logic for multithreaded
+ {Java} programs",
+ journal = lmcs,
+ year = "2015",
+ volume = "11",
+ number = "1",
+ pages = "1--66",
+ URL = "http://arxiv.org/abs/1411.0851",
+}
+
+@InProceedings{amin-essence-16,
+ author = "Nada Amin and Samuel Gr{\"{u}}tter and Martin Odersky
+ and Tiark Rompf and Sandro Stucki",
+ title = "The Essence of Dependent Object Types",
+ booktitle = "A List of Successes That Can Change the World --
+ Essays Dedicated to {Philip Wadler} on the Occasion of
+ His 60th Birthday",
+ series = lncs,
+ volume = "9600",
+ publisher = springer,
+ pages = "249--272",
+ year = "2016",
+ URL = "https://infoscience.epfl.ch/record/215280/files/paper_1.pdf",
+}
+
+@InProceedings{amin-rompf-17,
+ author = "Nada Amin and Tiark Rompf",
+ title = "Type Soundness Proofs with Definitional Interpreters",
+ booktitle = popl,
+ year = "2017",
+ pages = "666--679",
+ URL = "http://lampwww.epfl.ch/~amin/pub/big-step.pdf",
+}
+
+@Article{andersen-94,
+ author = "Henrik Reif Andersen",
+ title = "Model checking and {Boolean} graphs",
+ journal = tcs,
+ volume = "126",
+ number = "1",
+ year = "1994",
+ pages = "3--30",
+ URL = "http://dx.doi.org/10.1016/0304-3975(94)90266-6",
+}
+
+@Article{anderson-eve-horning-73,
+ author = "T. Anderson and J. Eve and J. J. Horning",
+ title = "Efficient ${LR}(1)$ parsers",
+ journal = acta,
+ year = "1973",
+ volume = "2",
+ pages = "12--39",
+ URL = "http://dx.doi.org/10.1007/BF00571461",
+}
+
+@Book{andrews-00,
+ author = "Gregory R. Andrews",
+ title = "Foundations of Multithreaded, Parallel, and
+ Distributed Programming",
+ publisher = aw,
+ year = "2000",
+}
+
+@Book{andrews-86,
+ author = "Peter B. Andrews",
+ title = "An introduction to mathematical logic and type theory:
+ to truth through proof",
+ year = "1986",
+ publisher = ap,
+}
+
+@Article{andrews-reitman-80,
+ author = "Gregory R. Andrews and Richard P. Reitman",
+ title = "An Axiomatic Approach to Information Flow in
+ Programs",
+ journal = toplas,
+ volume = "2",
+ number = "1",
+ pages = "56--76",
+ year = "1980",
+}
+
+@Book{antlr,
+ author = "Terence Parr",
+ title = "The Definitive {ANTLR 4} Reference, 2nd edition",
+ year = "2013",
+ publisher = "Pragmatic Bookshelf",
+}
+
+@InProceedings{antonopoulos-14,
+ author = "Timos Antonopoulos and Nikos Gorogiannis and Christoph
+ Haase and Max I. Kanovich and Jo{\"{e}}l Ouaknine",
+ title = "Foundations for Decision Problems in Separation Logic
+ with General Inductive Predicates",
+ booktitle = fossacs,
+ pages = "411--425",
+ year = "2014",
+ series = lncs,
+ volume = "8412",
+ publisher = springer,
+ URL = "http://www.lsv.ens-cachan.fr/Publis/PAPERS/PDF/AGHKO-fossacs14.pdf",
+}
+
+@InProceedings{aponte-dicosmo-96,
+ author = "Maria-Virginia Aponte and Roberto {Di Cosmo}",
+ title = "Type isomorphisms for module signatures",
+ year = "1996",
+ booktitle = plilp,
+ publisher = springer,
+ series = lncs,
+ volume = "1140",
+ pages = "334--346",
+ URL = "http://dx.doi.org/10.1007/3-540-61756-6_95",
+}
+
+@Book{appel-92,
+ author = "Andrew W. Appel",
+ title = "Compiling with Continuations",
+ publisher = cup,
+ year = "1992",
+ URL = "http://www.cambridge.org/9780521033114",
+}
+
+@Article{appel-jim-97,
+ author = "Andrew W. Appel and Trevor Jim",
+ title = "Shrinking lambda expressions in linear time",
+ journal = jfp,
+ volume = "7",
+ number = "5",
+ year = "1997",
+ pages = "515--540",
+ URL = "http://www.research.att.com/~trevor/papers/shrinking.ps.gz",
+}
+
+@InProceedings{appel-major-07,
+ author = "Andrew W. Appel and Paul-Andr\'{e} Melli\`{e}s and
+ Christopher D. Richards and J\'{e}r\^{o}me Vouillon",
+ title = "A very modal model of a modern, major, general type
+ system",
+ booktitle = popl,
+ year = "2007",
+ pages = "109--122",
+ URL = "http://www.cs.princeton.edu/~appel/papers/modalmodel.pdf",
+}
+
+@Book{appel-tiger-98,
+ author = "Andrew Appel",
+ title = "Modern Compiler Implementation in {ML}",
+ publisher = cup,
+ year = "1998",
+ URL = "http://www.cs.princeton.edu/~appel/modern/ml/",
+}
+
+@InProceedings{appel-verismall-11,
+ author = "Andrew W. Appel",
+ title = "{VeriSmall}: Verified {Smallfoot} Shape Analysis",
+ booktitle = cpp,
+ year = "2011",
+ pages = "231--246",
+ publisher = springer,
+ series = lncs,
+ volume = "7086",
+ URL = "http://www.cs.princeton.edu/~appel/papers/verismall.pdf",
+}
+
+@InProceedings{appel-vst-11,
+ author = "Andrew W. Appel",
+ title = "Verified Software Toolchain",
+ booktitle = esop,
+ pages = "1--17",
+ year = "2011",
+ series = lncs,
+ volume = "6602",
+ publisher = springer,
+ URL = "https://www.cs.princeton.edu/~appel/papers/vst.pdf",
+}
+
+@Article{apt-81,
+ author = "Krzysztof R. Apt",
+ title = "Ten Years of {Hoare's} Logic: {A} Survey---Part {I}",
+ journal = toplas,
+ volume = "3",
+ number = "4",
+ year = "1981",
+ pages = "431--483",
+ URL = "http://doi.acm.org/10.1145/357146.357150",
+}
+
+@Article{ariola-klop-95,
+ author = "Zena M. Ariola and Jan Willem Klop",
+ title = "Equational term graph rewriting",
+ journal = fundamenta,
+ volume = "26",
+ number = "3--4",
+ year = "1996",
+ pages = "207--240",
+ URL = "http://www.cwi.nl/ftp/CWIreports/AP/CS-R9552.ps.Z",
+}
+
+@Article{arnold-crubille-88,
+ author = "Andr{\'e} Arnold and Paul Crubillé",
+ title = "A Linear Algorithm to Solve Fixed-Point Equations on
+ Transition Systems",
+ journal = ipl,
+ volume = "29",
+ number = "2",
+ year = "1988",
+ pages = "57--66",
+ URL = "http://dx.doi.org/10.1016/0020-0190(88)90029-4",
+}
+
+@Article{arnold-nivat-80,
+ author = "André Arnold and Maurice Nivat",
+ year = "1980",
+ journal = fundamenta,
+ volume = "3",
+ number = "4",
+ pages = "181--205",
+ title = "{T}he Metric Space of Infinite Trees. {A}lgebraic And
+ Topological Properties",
+}
+
+@InProceedings{asai-kameyama-07,
+ author = "Kenichi Asai and Yukiyoshi Kameyama",
+ title = "Polymorphic Delimited Continuations",
+ booktitle = aplas,
+ pages = "239--254",
+ year = "2007",
+ series = lncs,
+ volume = "4807",
+ publisher = springer,
+ URL = "http://logic.cs.tsukuba.ac.jp/~kam/paper/aplas07.pdf",
+}
+
+@Article{aspinall-07,
+ author = "David Aspinall and Lennart Beringer and Martin Hofmann
+ and Hans{-}Wolfgang Loidl and Alberto Momigliano",
+ title = "A program logic for resources",
+ journal = tcs,
+ volume = "389",
+ number = "3",
+ pages = "411--445",
+ year = "2007",
+ URL = "https://www.tcs.ifi.lmu.de/mitarbeiter/martin-hofmann/publikationen-pdfs/j25-ProgramLogisResources.pdf",
+}
+
+@InProceedings{aspinall-hofmann-02,
+ author = "David Aspinall and Martin Hofmann",
+ title = "Another Type System for In-Place Update",
+ booktitle = esop,
+ pages = "36--52",
+ year = "2002",
+ series = lncs,
+ volume = "2305",
+ publisher = springer,
+ URL = "https://www.tcs.ifi.lmu.de/mitarbeiter/martin-hofmann/publikationen-pdfs/c22-anothertypesystem.pdf",
+}
+
+@Article{aspinall-hofmann-konecky-08,
+ author = "David Aspinall and Martin Hofmann and Michal Kone{\v
+ c}n{\'{y}}",
+ title = "A type system with usage aspects",
+ journal = jfp,
+ volume = "18",
+ number = "2",
+ pages = "141--178",
+ year = "2008",
+ URL = "http://dx.doi.org/10.1017/S0956796807006399",
+}
+
+@Misc{astree,
+ author = "Patrick Cousot and Radhia Cousot and Jérôme Feret
+ and Antoine Miné and Xavier Rival",
+ title = "The {Astrée} Static Analyzer",
+ year = "2011",
+ note = "\url{http://www.astree.ens.fr/}",
+ URL = "http://www.astree.ens.fr/",
+}
+
+@Article{atkey-09,
+ author = "Robert Atkey",
+ title = "Parameterised Notions of Computation",
+ journal = jfp,
+ year = "2009",
+ volume = "19",
+ number = "3--4",
+ pages = "355--376",
+ URL = "http://homepages.inf.ed.ac.uk/ratkey/paramnotions-jfp.pdf",
+}
+
+@Article{atkey-11,
+ title = "Amortised Resource Analysis with Separation Logic",
+ author = "Robert Atkey",
+ year = "2011",
+ journal = lmcs,
+ volume = "7",
+ number = "2:17",
+ URL = "http://bentnib.org/amortised-sep-logic-journal.pdf",
+}
+
+@InProceedings{atkey-amortised-10,
+ author = "Robert Atkey",
+ title = "Amortised Resource Analysis with Separation Logic",
+ booktitle = esop,
+ pages = "85--103",
+ year = "2010",
+ volume = "6012",
+ series = lncs,
+ publisher = springer,
+ URL = "http://personal.cis.strath.ac.uk/~raa/amortised-sep-logic.pdf",
+}
+
+@InProceedings{atkey-hoas-09,
+ author = "Robert Atkey",
+ title = "Syntax for free: representing syntax with binding
+ using parametricity",
+ booktitle = tlca,
+ pages = "35--49",
+ year = "2009",
+ volume = "5608",
+ series = lncs,
+ publisher = springer,
+ URL = "https://personal.cis.strath.ac.uk/~raa/syntaxforfree.pdf",
+}
+
+@InProceedings{atkey-lindley-yallop-09,
+ author = "Robert Atkey and Sam Lindley and Jeremy Yallop",
+ title = "Unembedding Domain-Specific languages",
+ booktitle = hs,
+ pages = "37--48",
+ year = "2009",
+ URL = "http://personal.cis.strath.ac.uk/~raa/unembedding.pdf",
+}
+
+@InProceedings{augustsson-93,
+ author = "Lennart Augustsson",
+ title = "Implementing {Haskell} Overloading",
+ booktitle = fpca,
+ pages = "65--73",
+ year = "1993",
+ URL = "http://dl.acm.org/citation.cfm?id=165191",
+}
+
+@Book{autebert-94,
+ author = "Jean-Michel Autebert",
+ title = "Théorie des langages et des automates",
+ publisher = "Masson",
+ year = "1994",
+}
+
+@InCollection{autebert-97,
+ author = "Jean-Michel Autebert and Jean Berstel and Luc
+ Boasson",
+ booktitle = "Handbook of Formal Languages",
+ title = "Context-Free Languages and Push-Down Automata",
+ publisher = springer,
+ year = "1997",
+ volume = "1",
+ pages = "111--174",
+ URL = "http://www-igm.univ-mlv.fr/~berstel/Articles/CFLPDA.ps.gz",
+}
+
+@InProceedings{autosubst-15,
+ author = "Steven Sch{\"{a}}fer and Tobias Tebbi and Gert
+ Smolka",
+ title = "{Autosubst}: Reasoning with {de Bruijn} Terms and
+ Parallel Substitutions",
+ booktitle = itp,
+ pages = "359--374",
+ year = "2015",
+ series = lncs,
+ volume = "9236",
+ publisher = springer,
+ URL = "https://www.ps.uni-saarland.de/Publications/documents/SchaeferEtAl_2015_Autosubst_-Reasoning.pdf",
+}
+
+@InProceedings{ayache-amadio-regis-gianas-12,
+ author = "Nicholas Ayache and Roberto M. Amadio and Yann
+ R{\'{e}}gis{-}Gianas",
+ title = "Certifying and Reasoning on Cost Annotations in {C}
+ Programs",
+ booktitle = "Formal Methods for Industrial Critical Systems",
+ pages = "32--46",
+ year = "2012",
+ series = lncs,
+ volume = "7437",
+ publisher = springer,
+ URL = "https://hal.inria.fr/hal-00702665",
+}
+
+@InProceedings{aycock-horspool-00,
+ author = "John Aycock and Nigel Horspool",
+ title = "Simple Generation of Static Single-Assignment Form",
+ booktitle = cc,
+ year = "2000",
+ volume = "1781",
+ series = lncs,
+ publisher = springer,
+ URL = "http://pages.cpsc.ucalgary.ca/~aycock/papers/ssa.ps",
+}
+
+@InProceedings{aydemir-08,
+ author = "Brian Aydemir and Arthur Chargu{\'e}raud and {Benjamin
+ C.} Pierce and Randy Pollack and Stephanie Weirich",
+ booktitle = popl,
+ title = "Engineering Formal Metatheory",
+ year = "2008",
+ pages = "3--15",
+ URL = "http://www.cis.upenn.edu/~bcpierce/papers/binders.pdf",
+}
+
+@Article{baker-77,
+ author = "Henry G. Baker",
+ title = "List Processing in Real Time on a Serial Computer",
+ journal = cacm,
+ volume = "21",
+ number = "4",
+ year = "1978",
+ pages = "280--294",
+ URL = "http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.468.2631&rep=rep1&type=pdf",
+}
+
+@InProceedings{baker-conquer-90,
+ author = "Henry G. Baker",
+ title = "Unify and conquer (Garbage, Updating, Aliasing,
+ \ldots) in Functional Languages",
+ booktitle = lfp,
+ year = "1990",
+ pages = "218--226",
+ URL = "http://home.pipeline.com/~hbaker1/Share-Unify.ps.gz",
+}
+
+@InProceedings{balabonski-pottier-protzenko-mezzo-14,
+ author = "Thibaut Balabonski and François Pottier and Jonathan
+ Protzenko",
+ title = "Type Soundness and Race Freedom for {Mezzo}",
+ booktitle = "Proceedings of the 12th International Symposium on
+ Functional and Logic Programming (FLOPS 2014)",
+ year = "2014",
+ series = lncs,
+ publisher = springer,
+ volume = "8475",
+ pages = "253--269",
+ URL = "http://gallium.inria.fr/~fpottier/publis/bpp-mezzo.pdf",
+}
+
+@Article{balabonski-pottier-protzenko-mezzo-journal-16,
+ author = "Thibaut Balabonski and François Pottier and Jonathan
+ Protzenko",
+ title = "The Design and Formalization of {Mezzo}, a
+ Permission-Based Programming Language",
+ journal = toplas,
+ volume = "38",
+ number = "4",
+ pages = "14:1--14:94",
+ year = "2016",
+ URL = "http://gallium.inria.fr/~fpottier/publis/bpp-mezzo-journal.pdf",
+}
+
+@InProceedings{balat-dicosmo-fiore-02,
+ author = "Vincent Balat and Roberto {Di Cosmo} and Marcelo
+ Fiore",
+ title = "Remarks on Isomorphisms in Typed Lambda Calculi with
+ Empty and Sum Type",
+ booktitle = lics,
+ year = "2002",
+ URL = "http://www.cl.cam.ac.uk/~mpf23/papers/Types/remarks.ps.gz",
+}
+
+@InProceedings{banatre-bryce-lemetayer-94,
+ author = "Jean-Pierre Banâtre and Ciarán Bryce and Daniel {Le
+ Métayer}",
+ title = "Compile-time detection of information flow in
+ sequential programs",
+ booktitle = esorics,
+ year = "1994",
+ publisher = springer,
+ pages = "55--74",
+ series = lncs,
+ volume = "875",
+ URL = "ftp://ftp.irisa.fr/local/lande/dlm-esorics94.ps.Z",
+}
+
+@InProceedings{banerjee-heintze-riecke-01,
+ author = "Anindya Banerjee and Nevin Heintze and Jon G. Riecke",
+ title = "Design and Correctness of Program Transformations
+ based on Control-flow Analysis",
+ booktitle = tacs,
+ pages = "420--447",
+ year = "2001",
+ volume = "2215",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.cis.ksu.edu/~ab/Publications/pcfa.ps.gz",
+}
+
+@InProceedings{banerjee-heintze-riecke-99,
+ author = "Anindya Banerjee and Nevin Heintze and Jon G. Riecke",
+ title = "Region Analysis and the Polymorphic Lambda Calculus",
+ booktitle = lics,
+ year = "1999",
+ pages = "88--97",
+ URL = "http://www.cs.ucla.edu/~palsberg/tba/papers/banerjee-heintze-riecke-lics99.pdf",
+}
+
+@TechReport{banerjee-naumann-01,
+ author = "Anindya Banerjee and David A. Naumann",
+ title = "A Simple Semantics and Static Analysis for {Java}
+ Security",
+ institution = "Stevens Institute of Technology",
+ number = "2001-1",
+ year = "2001",
+ URL = "http://guinness.cs.stevens-tech.edu/~naumann/publications/tr2001.ps",
+}
+
+@InProceedings{banerjee-naumann-05,
+ author = "Anindya Banerjee and David A. Naumann",
+ title = "State based ownership, reentrance, and encapsulation",
+ booktitle = ecoop,
+ pages = "387--411",
+ year = "2005",
+ volume = "3586",
+ series = lncs,
+ publisher = springer,
+ URL = "https://guinness.cs.stevens-tech.edu/~naumann/publications/ecoop.pdf",
+}
+
+@InProceedings{banerjee-naumann-csfw-02,
+ author = "Anindya Banerjee and David Naumann",
+ title = "Secure Information Flow and Pointer Confinement in a
+ {Java}-like Language",
+ booktitle = csfw,
+ pages = "253--267",
+ year = "2002",
+ URL = "http://www.cs.stevens-tech.edu/~naumann/publications/csfw15.ps",
+}
+
+@InProceedings{banerjee-naumann-popl-02,
+ author = "Anindya Banerjee and David A. Naumann",
+ title = "Representation Independence, Confinement, and Access
+ Control",
+ booktitle = popl,
+ year = "2002",
+ pages = "166--177",
+ URL = "http://guinness.cs.stevens-tech.edu/~naumann/publications/BanerjeeNaumann.ps",
+}
+
+@TechReport{barber-dill-96,
+ author = "Andrew Barber",
+ title = "Dual Intuitionistic Linear Logic",
+ institution = "Laboratory for Foundations of Computer Science, School
+ of Informatics at the University of Edinburgh",
+ year = "1996",
+ number = "ECS-LFCS-96-347",
+ URL = "http://www.lfcs.inf.ed.ac.uk/reports/96/ECS-LFCS-96-347/",
+}
+
+@Book{barendregt,
+ author = "Henk P. Barendregt",
+ title = "The Lambda Calculus, Its Syntax and Semantics",
+ publisher = elsevier,
+ year = "1984",
+ URL = "http://www.elsevier.com/wps/find/bookdescription.cws_home/501727/description",
+}
+
+@InCollection{barendregt-90,
+ author = "Henk P. Barendregt",
+ title = "Functional Programming and Lambda Calculus",
+ booktitle = "Handbook of Theoretical Computer Science",
+ pages = "321--363",
+ publisher = elsevier,
+ year = "1990",
+ editor = "J. Van Leeuwen",
+}
+
+@InProceedings{barendsen-smesters-95,
+ author = "Erik Barendsen and Sjaak Smetsers",
+ title = "Uniqueness Type Inference",
+ booktitle = plilp,
+ year = "1995",
+ pages = "189--206",
+ publisher = springer,
+ series = lncs,
+ volume = "982",
+ URL = "http://dx.doi.org/10.1007/BFb0026821",
+}
+
+@InProceedings{barnett-pure-04,
+ author = "Mike Barnett and David A. Naumann and Wolfram Schulte
+ and Qi Sun",
+ title = "99.44\% pure: Useful Abstractions in Specifications",
+ booktitle = ftfjp,
+ year = "2004",
+ URL = "http://www.cs.ru.nl/ftfjp/2004/Purity.pdf",
+}
+
+@InProceedings{barnett-spec-04,
+ author = "Mike Barnett and K. Rustan M. Leino and Wolfram
+ Schulte",
+ title = "The {Spec\#} programming system: An overview",
+ booktitle = cassis,
+ year = "2004",
+ volume = "3362",
+ pages = "49--69",
+ series = lncs,
+ publisher = springer,
+ URL = "http://research.microsoft.com/~leino/papers/krml136.pdf",
+}
+
+@Article{barrett-00,
+ author = "Chris Barrett and Riko Jacob and Madhav Marathe",
+ title = "Formal Language Constrained Path Problems",
+ journal = siamjc,
+ year = "2000",
+ volume = "30",
+ number = "3",
+ pages = "809--837",
+ URL = "http://www.brics.dk/~rjacob/Publications/regpath.ps.gz",
+ alturl = "http://epubs.siam.org/sam-bin/getfile/SICOMP/articles/33771.pdf",
+}
+
+@TechReport{bartels-96,
+ author = "Frank Bartels and Friedrich von Henke and Holger
+ Pfeifer and Harald Rue{\ss}",
+ title = "Mechanizing Domain Theory",
+ institution = "Universit{\"a}t Ulm, Fakult{\"a}t f{\"u}r Informatik",
+ year = "1996",
+ number = "96-10",
+ type = "Ulmer Informatik-Berichte",
+ URL = "http://www.csl.sri.com/users/ruess/papers/Fixpoints/fixpoints-domains3.ps.gz",
+}
+
+@InProceedings{barthe-06,
+ author = "Gilles Barthe and Julien Forest and David Pichardie
+ and Vlad Rusu",
+ title = "Defining and Reasoning About Recursive Functions: A
+ Practical Tool for the {Coq} Proof Assistant",
+ booktitle = flops,
+ pages = "114--129",
+ year = "2006",
+ series = lncs,
+ volume = "3945",
+ publisher = springer,
+ URL = "http://people.irisa.fr/David.Pichardie/papers/flops06.pdf",
+}
+
+@InProceedings{barthwal-norrish-09,
+ author = "Aditi Barthwal and Michael Norrish",
+ title = "Verified, Executable Parsing",
+ booktitle = esop,
+ year = "2009",
+ pages = "160--174",
+ series = lncs,
+ publisher = springer,
+ volume = "5502",
+ URL = "http://users.cecs.anu.edu.au/~aditi/esop09_submission_16.pdf",
+}
+
+@InProceedings{bartoletti-al-01,
+ author = "Massimo Bartoletti and Pierpaolo Degano and GianLuigi
+ Ferrari",
+ title = "Static Analysis for Stack Inspection",
+ booktitle = "International Workshop on Concurrency and
+ Coordination",
+ series = entcs,
+ volume = "54",
+ publisher = elsevier,
+ year = "2001",
+}
+
+@Article{bauer-pretnar-13,
+ author = "Andrej Bauer and Matija Pretnar",
+ title = "An Effect System for Algebraic Effects and Handlers",
+ journal = lmcs,
+ volume = "10",
+ number = "4",
+ year = "2014",
+ URL = "https://arxiv.org/pdf/1306.6316.pdf",
+}
+
+@Article{beaven-stansifer-93,
+ author = "Mike Beaven and Ryan Stansifer",
+ title = "Explaining type errors in polymorphic languages",
+ journal = "ACM Letters on Programming Languages and Systems",
+ volume = "2",
+ number = "4",
+ pages = "17--30",
+ year = "1993",
+ URL = "http://www.cs.fit.edu/~ryan/papers/explain.ps.gz",
+}
+
+@InProceedings{belanger-monnier-pientka-13,
+ author = "Olivier {Savary Belanger} and Stefan Monnier and
+ Brigitte Pientka",
+ title = "Programming Type-Safe Transformations Using
+ Higher-Order Abstract Syntax",
+ booktitle = cpp,
+ pages = "243--258",
+ year = "2013",
+ series = lncs,
+ volume = "8307",
+ publisher = springer,
+ URL = "https://link.springer.com/chapter/10.1007/978-3-319-03545-1_16",
+}
+
+@Article{belanger-monnier-pientka-15,
+ author = "Olivier {Savary Belanger} and Stefan Monnier and
+ Brigitte Pientka",
+ title = "Programming Type-Safe Transformations Using
+ Higher-Order Abstract Syntax",
+ journal = jfr,
+ year = "2015",
+ volume = "8",
+ number = "1",
+ URL = "https://jfr.unibo.it/article/view/5122/5330",
+}
+
+@InProceedings{bell-08,
+ author = "C. J. Bell and Robert Dockins and Aquinas Hobor and
+ Andrew W. Appel and David Walker",
+ title = "Comparing Semantic and Syntactic Methods in Mechanized
+ Proof Frameworks",
+ booktitle = pcc,
+ year = "2008",
+ URL = "http://www.cs.princeton.edu/~rdockins/pubs/semsyn.pdf",
+}
+
+@InProceedings{bell-bellegarde-hook-97,
+ author = "Jeffrey M. Bell and Françoise Bellegarde and James
+ Hook",
+ title = "Type-driven Defunctionalization",
+ booktitle = icfp,
+ year = "1997",
+ URL = "http://doi.acm.org/10.1145/258949.258953",
+}
+
+@TechReport{bell-lapadula-75,
+ author = "D. E. Bell and Leonard J. LaPadula",
+ title = "Secure Computer Systems: Unified Exposition and
+ {Multics} Interpretation",
+ year = "1975",
+ number = "MTR-2997",
+ institution = "The {MITRE} Corp.",
+ URL = "http://niatec.info/pdf/bell76.pdf",
+}
+
+@InProceedings{bengtson-12,
+ author = "Jesper Bengtson and Jonas Braband Jensen and Lars
+ Birkedal",
+ title = "Charge! {A} Framework for Higher-Order Separation
+ Logic in {Coq}",
+ booktitle = itp,
+ pages = "315--331",
+ year = "2012",
+ URL = "http://cs.au.dk/~birke/papers/charge-conf.pdf",
+}
+
+@InProceedings{berdine-calcagno-ohearn-05,
+ author = "Josh Berdine and Cristiano Calcagno and Peter W.
+ O'Hearn",
+ title = "Symbolic Execution with Separation Logic",
+ booktitle = aplas,
+ year = "2005",
+ publisher = springer,
+ series = lncs,
+ volume = "3780",
+ pages = "52--68",
+ URL = "http://www.dcs.qmul.ac.uk/~berdine/papers/execution.pdf",
+}
+
+@InProceedings{berdine-decidable-fragment-04,
+ author = "Josh Berdine and Cristiano Calcagno and Peter W.
+ O'Hearn",
+ title = "A Decidable Fragment of Separation Logic",
+ booktitle = fsttcs,
+ year = "2004",
+ pages = "97--109",
+ publisher = springer,
+ series = lncs,
+ volume = "3328",
+ URL = "http://www.cs.ucl.ac.uk/staff/p.ohearn/papers/unroll_collapse.pdf",
+}
+
+@Article{berdine-linear-continuations-02,
+ author = "Josh Berdine and Peter W. O'Hearn and Uday S. Reddy
+ and Hayo Thielecke",
+ title = "Linear Continuation-Passing",
+ journal = hosc,
+ year = "2002",
+ volume = "15",
+ number = "2--3",
+ pages = "181--208",
+ URL = "http://www.cs.bham.ac.uk/~hxt/research/LinCP.pdf",
+}
+
+@InProceedings{berdine-ohearn-06,
+ author = "Josh Berdine and Peter W. O'Hearn",
+ title = "Strong Update, Disposal, and Encapsulation in Bunched
+ Typing",
+ booktitle = mfps,
+ series = entcs,
+ publisher = elsevier,
+ volume = "158",
+ year = "2006",
+ pages = "81--98",
+ URL = "http://research.microsoft.com/pubs/73584/bil.pdf",
+}
+
+@InProceedings{berger-honda-yoshida-05,
+ author = "Martin Berger and Kohei Honda and Nobuko Yoshida",
+ title = "A logical analysis of aliasing in imperative
+ higher-order functions",
+ booktitle = icfp,
+ year = "2005",
+ pages = "280--293",
+ URL = "http://doi.acm.org/10.1145/1086365.1086401",
+}
+
+@InProceedings{bergeron-al-00,
+ author = "M. Debbabi and E. Giasson and B. Ktari and F. Michaud
+ and N. Tawbi",
+ title = "Secure Self-Certified {COTS}",
+ booktitle = "IEEE International Workshop on Enterprise Security
+ (WETICE'00)",
+ year = "2000",
+ URL = "http://www.ift.ulaval.ca/~lsfm/lsfm_eng/Publications/wetice2000_2.pdf",
+}
+
+@Unpublished{bernstein-stark-95,
+ author = "K. Bernstein and E. W. Stark",
+ title = "Debugging Type Errors",
+ year = "1995",
+ URL = "http://bsd7.starkhome.cs.sunysb.edu/~stark/REPORTS/debugtype.ps.gz",
+ note = "Unpublished",
+}
+
+@InProceedings{berthomieu-sagazan-95,
+ author = "Bernard Berthomieu and Camille {le Moniès de
+ Sagazan}",
+ title = "A Calculus of Tagged Types, with applications to
+ process languages",
+ booktitle = "Workshop on Types for Program Analysis",
+ pages = "1--15",
+ year = "1995",
+ URL = "http://www.laas.fr/~bernard/lcs/papers/tpa95.ps.gz",
+}
+
+@Article{besson-al-01,
+ author = "Frédéric Besson and Thomas P. Jensen and Daniel {Le
+ Métayer} and Tommy Thorn",
+ title = "Model Checking Security Properties of Control Flow
+ Graphs",
+ journal = "Journal of Computer Security",
+ volume = "9",
+ number = "3",
+ year = "2001",
+ pages = "217--250",
+ URL = "http://www.irisa.fr/lande/jensen/jcs.pdf",
+}
+
+@InProceedings{besson-al-02,
+ author = "Frédéric Besson and Thomas {de Grenier de Latour}
+ and Thomas Jensen",
+ title = "Secure Calling Contexts for Stack Inspection",
+ pages = "76--87",
+ booktitle = ppdp,
+ year = "2002",
+ URL = "http://www.irisa.fr/lande/jensen/ppdp02.pdf",
+}
+
+@Article{bhamidipaty-proebsting-98,
+ author = "Achyutram Bhamidipaty and Todd A. Proebsting",
+ title = "Very Fast {YACC}-Compatible Parsers (For Very Little
+ Effort)",
+ journal = spe,
+ year = "1998",
+ volume = "28",
+ number = "2",
+ pages = "181--190",
+ URL = "http://www.cs.arizona.edu/people/todd/papers/TR95-09.ps",
+}
+
+@InProceedings{bhargavan-fournet-gordon-10,
+ author = "Karthik Bhargavan and Cédric Fournet and Andy
+ Gordon",
+ title = "Modular Verification of Security Protocol Code by
+ Typing",
+ booktitle = popl,
+ pages = "445--456",
+ year = "2010",
+ URL = "http://moscova.inria.fr/~karthik/pubs/modular-verification-of-security-protocols-by-typing-popl10.pdf",
+}
+
+@InProceedings{bhat-cleaveland-96,
+ author = "Girish Bhat and Rance Cleaveland",
+ title = "Efficient Local Model-Checking for Fragments of the
+ Modal $\mu$-Calculus",
+ booktitle = tacas,
+ pages = "107--126",
+ year = "1996",
+ volume = "1055",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.cs.umd.edu/~rance/publications/papers/tacas96a.ps.gz",
+}
+
+@InProceedings{biere-bmc-99,
+ author = "Armin Biere and Alessandro Cimatti and Edmund Clarke
+ and Yunshan Zhu",
+ title = "Symbolic Model Checking Without {BDDs}",
+ booktitle = tacas,
+ pages = "193--207",
+ year = "1999",
+ volume = "1579",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.inf.ethz.ch/personal/biere/papers/BiereCimattiClarkeZhu-TACAS99.pdf",
+}
+
+@InProceedings{bierhoff-aldrich-07,
+ author = "Kevin Bierhoff and Jonathan Aldrich",
+ title = "Modular typestate checking of aliased objects",
+ booktitle = oopsla,
+ year = "2007",
+ pages = "301--320",
+ URL = "http://www.cs.cmu.edu/~kbierhof/papers/typestate-verification.pdf",
+}
+
+@InProceedings{bierhoff-beckman-aldrich-09,
+ author = "Kevin Bierhoff and Nels E. Beckman and Jonathan
+ Aldrich",
+ title = "Practical {API} Protocol Checking with Access
+ Permissions",
+ booktitle = ecoop,
+ year = "2009",
+ pages = "195--219",
+ publisher = springer,
+ series = lncs,
+ volume = "5653",
+ URL = "http://www.cs.cmu.edu/~kbierhof/papers/permission-practice.pdf",
+}
+
+@InProceedings{biering-05,
+ author = "Bodil Biering and Lars Birkedal and Noah Torp-Smith",
+ title = "{BI} Hyperdoctrines and Higher-Order Separation
+ Logic",
+ booktitle = esop,
+ year = "2005",
+ pages = "233--247",
+ publisher = springer,
+ series = lncs,
+ volume = "3444",
+ URL = "http://www.itu.dk/people/noah/papers/hyperdocs.pdf",
+}
+
+@Article{bird-hughes-87,
+ author = "Richard S. Bird and John Hughes",
+ title = "The alpha-beta Algorithm: An Exercise in Program
+ Transformation",
+ journal = ipl,
+ volume = "24",
+ number = "1",
+ year = "1987",
+ pages = "53--57",
+ URL = "http://dx.doi.org/10.1016/0020-0190(87)90198-0",
+}
+
+@InProceedings{bird-meertens-98,
+ author = "Richard Bird and Lambert Meertens",
+ title = "Nested Datatypes",
+ booktitle = mpc,
+ pages = "52--67",
+ year = "1998",
+ volume = "1422",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.cs.ox.ac.uk/richard.bird/online/BirdMeertens98Nested.pdf",
+}
+
+@Article{bird-paterson-99,
+ title = "{de Bruijn} Notation as a Nested Datatype",
+ author = "Richard Bird and Ross Paterson",
+ URL = "http://dx.doi.org/10.1017/S0956796899003366",
+ journal = jfp,
+ volume = "9",
+ number = "1",
+ pages = "77--91",
+ year = "1999",
+}
+
+@TechReport{birkedal-alii-93,
+ author = "Lars Birkedal and Nick Rothwell and Mads Tofte and
+ David N. Turner",
+ semno = "D-181",
+ title = "The {ML} Kit (Version 1)",
+ institution = "Department of Computer Science, University of
+ Copenhagen",
+ year = "1993",
+ number = "DIKU 93/14",
+ URL = "http://www.it-c.dk/research/mlkit/",
+}
+
+@Article{birkedal-hoframe-06,
+ author = "Lars Birkedal and Noah Torp-Smith and Hongseok Yang",
+ title = "Semantics of separation-logic typing and higher-order
+ frame rules for {Algol}-like languages",
+ journal = lmcs,
+ year = "2006",
+ volume = "2",
+ number = "5",
+ URL = "http://arxiv.org/pdf/cs.LO/0610081",
+}
+
+@Unpublished{birkedal-nakano-10,
+ author = "Lars Birkedal and Jan Schwinghammer and Kristian
+ Støvring",
+ title = "A Metric Model of Lambda Calculus with Guarded
+ Recursion",
+ note = "Presented at FICS 2010",
+ year = "2010",
+ URL = "http://www.itu.dk/~birkedal/papers/nakano-conf.pdf",
+}
+
+@InProceedings{birkedal-popl-11,
+ author = "Lars Birkedal and Bernhard Reus and Jan Schwinghammer
+ and Kristian Støvring and Jacob Thamsborg and Hongseok
+ Yang",
+ title = "Step-indexed {Kripke} models over recursive worlds",
+ booktitle = popl,
+ pages = "119--132",
+ year = "2011",
+ URL = "http://www.eecs.qmul.ac.uk/~hyang/paper/popl11-long.pdf",
+}
+
+@InProceedings{birkedal-stovring-thamsborg-09,
+ author = "Lars Birkedal and Kristian St{\o}vring and Jacob
+ Thamsborg",
+ title = "Realizability Semantics of Parametric Polymorphism,
+ General References, and Recursive Types",
+ booktitle = fossacs,
+ pages = "456--470",
+ year = "2009",
+ volume = "5504",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.itu.dk/~birkedal/papers/parametricity-state-metric-conf.pdf",
+}
+
+@Article{birkedal-stovring-thamsborg-10,
+ author = "Lars Birkedal and Kristian St{\o}vring and Jacob
+ Thamsborg",
+ title = "Realisability Semantics of Parametric Polymorphism,
+ General References, and Recursive Types",
+ journal = mscs,
+ year = "2010",
+ volume = "20",
+ number = "4",
+ pages = "655--703",
+ URL = "http://www.itu.dk/~birkedal/papers/parametricity-state-metric-journal.pdf",
+}
+
+@TechReport{birkedal-stovring-thamsborg-solution-09,
+ author = "Lars Birkedal and Kristian St{\o}vring and Jacob
+ Thamsborg",
+ title = "The category-theoretic solution of recursive
+ metric-space quations",
+ institution = "IT University of Copenhagen",
+ year = "2009",
+ number = "ITU-2009-119",
+ URL = "http://www.itu.dk/~birkedal/papers/ITU-TR-2009-119.pdf",
+}
+
+@Article{birkedal-tofte-01,
+ author = "Lars Birkedal and Mads Tofte",
+ title = "A constraint-based region inference algorithm",
+ journal = tcs,
+ year = "2001",
+ volume = "258",
+ pages = "299--392",
+ URL = "http://www.itu.dk/people/birkedal/papers/conria.ps.gz",
+}
+
+@Unpublished{birrell-03,
+ author = "Andrew D. Birrell",
+ title = "An Introduction to Programming with {C\#} Threads",
+ note = "Manuscript",
+ year = "2003",
+ URL = "http://birrell.org/andrew/papers/ThreadsCSharp.pdf",
+}
+
+@Manual{bison,
+ title = "Bison",
+ author = "Charles Donnelly and Richard Stallman",
+ year = "2015",
+ URL = "http://www.gnu.org/software/bison/manual/",
+}
+
+@PhdThesis{biswas-97,
+ school = "University of Pennsylvania",
+ title = "Dynamic Slicing in Higher-Order Programming
+ Languages",
+ year = "1997",
+ pages = "151",
+ author = "Sandip K. Biswas",
+}
+
+@InProceedings{blelloch-greiner-95,
+ author = "Guy E. Blelloch and John Greiner",
+ title = "Parallelism in Sequential Functional Languages",
+ booktitle = fpca,
+ pages = "226--237",
+ year = "1995",
+ URL = "http://www.cs.cmu.edu/afs/cs.cmu.edu/project/scandal/public/papers/fpca-pal.ps.gz",
+}
+
+@Article{bobot-why3-15,
+ author = "Fran{\c{c}}ois Bobot and Jean-Christophe
+ Filli{\^{a}}tre and Claude March{\'{e}} and Andrei
+ Paskevich",
+ title = "Let's verify this with {Why3}",
+ journal = sttt,
+ volume = "17",
+ number = "6",
+ pages = "709--727",
+ year = "2015",
+ URL = "https://hal.inria.fr/hal-00967132/",
+}
+
+@InProceedings{bocchino-09,
+ author = "Robert L. {Bocchino Jr.} and Vikram S. Adve and Sarita
+ V. Adve and Marc Snir",
+ title = "Parallel Programming Must Be Deterministic by
+ Default",
+ booktitle = hotpar,
+ year = "2009",
+ pages = "1--6",
+ URL = "http://dpj.cs.illinois.edu/DPJ/Publications_files/DPJ-HotPar-2009.pdf",
+}
+
+@InCollection{bocchino-13,
+ author = "Robert L. {Bocchino Jr.}",
+ title = "Alias Control for Deterministic Parallelism",
+ editor = "Dave Clarke and James Noble and Tobias Wrigstad",
+ booktitle = "Aliasing in Object-Oriented Programming. Types,
+ Analysis and Verification",
+ pages = "156--195",
+ year = "2013",
+ URL = "http://dx.doi.org/10.1007/978-3-642-36946-9_7",
+ series = lncs,
+ volume = "7850",
+ publisher = springer,
+}
+
+@InProceedings{bocchino-adve-11,
+ author = "Robert L. {Bocchino Jr.} and Vikram S. Adve",
+ title = "Types, Regions, and Effects for Safe Programming with
+ Object-Oriented Parallel Frameworks",
+ booktitle = ecoop,
+ pages = "306--332",
+ year = "2011",
+ series = lncs,
+ volume = "6813",
+ publisher = springer,
+ URL = "http://rob-bocchino.net/Professional/Publications_files/DPJ-ECOOP-2011-Frameworks.pdf",
+}
+
+@InProceedings{bocchino-dpj-09,
+ author = "Robert L. {Bocchino Jr.} and Vikram S. Adve and Danny
+ Dig and Sarita V. Adve and Stephen Heumann and Rakesh
+ Komuravelli and Jeffrey Overbey and Patrick Simmons and
+ Hyojin Sung and Mohsen Vakilian",
+ title = "A type and effect system for deterministic parallel
+ {Java}",
+ booktitle = oopsla,
+ pages = "97--116",
+ year = "2009",
+ URL = "http://rob-bocchino.net/Professional/Publications_files/Bocchino-OOPSLA-2009.pdf",
+}
+
+@InProceedings{bocchino-safe-11,
+ author = "Robert L. {Bocchino Jr.} and Stephen Heumann and Nima
+ Honarmand and Sarita V. Adve and Vikram S. Adve and
+ Adam Welc and Tatiana Shpeisman",
+ title = "Safe nondeterminism in a deterministic-by-default
+ parallel language",
+ booktitle = popl,
+ pages = "535--548",
+ year = "2011",
+ URL = "http://rob-bocchino.net/Professional/Publications_files/Bocchino-POPL-2011.pdf",
+}
+
+@InProceedings{bodei-al-99,
+ author = "Chiara Bodei and Pierpaolo Degano and Flemming Nielson
+ and Hanne Riis Nielson",
+ title = "Static Analysis of Processes for No Read-Up and No
+ Write-Down",
+ booktitle = fossacs,
+ year = "1999",
+ volume = "1578",
+ series = lncs,
+ publisher = springer,
+ pages = "120--134",
+ URL = "http://www.di.unipi.it/~chiara/publ-40/BDNN99.ps",
+}
+
+@Article{boehm-adve-12,
+ author = "Hans-J. Boehm and Sarita V. Adve",
+ title = "You don't know jack about shared variables or memory
+ models",
+ journal = cacm,
+ volume = "55",
+ number = "2",
+ year = "2012",
+ pages = "48--54",
+ URL = "http://doi.acm.org/10.1145/2076450.2076465",
+}
+
+@InProceedings{bonniot-02,
+ author = "Daniel Bonniot",
+ title = "Type-checking multi-methods in {ML} (a modular
+ approach)",
+ booktitle = fool,
+ year = "2002",
+ URL = "http://gallium.inria.fr/~bonniot/bonniot02.ps",
+}
+
+@PhdThesis{boquist-99,
+ author = "Urban Boquist",
+ title = "Code Optimisation Techniques for Lazy Functional
+ Languages",
+ school = "Chalmers University of Technology",
+ year = "1999",
+ URL = "http://www.cs.uu.nl/docs/vakken/macc/boquist.pdf",
+}
+
+@Article{boreale-sangiorgi-98,
+ author = "Michele Boreale and Davide Sangiorgi",
+ title = "A fully abstract semantics for causality in the
+ $\pi$-calculus",
+ journal = acta,
+ volume = "35",
+ number = "5",
+ pages = "353--400",
+ year = "1998",
+ URL = "http://link.springer.de/link/service/journals/00236/papers/8035005/80350353.pdf",
+}
+
+@InProceedings{borgstrom-chen-swamy-11,
+ author = "Johannes Borgström and Juan Chen and and Nikhil
+ Swamy",
+ title = "Verified Stateful Programs with Substructural State
+ and {Hoare} Types",
+ booktitle = plpv,
+ year = "2011",
+ URL = "http://research.microsoft.com/pubs/135430/plpv11k-borgstrom.pdf",
+}
+
+@InProceedings{bornat-00,
+ author = "Richard Bornat",
+ title = "Proving Pointer Programs in {Hoare} Logic",
+ booktitle = mpc,
+ year = "2000",
+ pages = "102--126",
+ publisher = springer,
+ series = lncs,
+ volume = "1837",
+ URL = "http://www.cs.mdx.ac.uk/staffpages/r_bornat/papers/MPC2000.pdf",
+}
+
+@InProceedings{bornat-permission-accounting-05,
+ author = "Richard Bornat and Cristiano Calcagno and Peter
+ O'Hearn and Matthew Parkinson",
+ title = "Permission accounting in separation logic",
+ booktitle = popl,
+ year = "2005",
+ pages = "259--270",
+ URL = "http://www.cs.ucl.ac.uk/staff/p.ohearn/papers/permissions_paper.pdf",
+}
+
+@InProceedings{bouajjani-esparza-maler-97,
+ author = "Ahmed Bouajjani and Javier Esparza and Oded Maler",
+ title = "Reachability Analysis of Pushdown Automata:
+ Application to Model-Checking",
+ booktitle = concur,
+ pages = "135--150",
+ year = "1997",
+ URL = "http://www-verimag.imag.fr/~maler/Papers/pda.pdf",
+ series = lncs,
+ volume = "1243",
+ publisher = springer,
+}
+
+@Unpublished{boudol-castellani-01,
+ author = "Gérard Boudol and Ilaria Castellani",
+ title = "Non-interference for concurrent programs and thread
+ systems",
+ year = "2001",
+ note = "To appear",
+ URL = "ftp://ftp-sop.inria.fr/mimosa/personnel/gbo/non-interf-threads.ps.gz",
+}
+
+@Article{boudol-stratified-regions,
+ author = "Gérard Boudol",
+ title = "Typing termination in a higher-order concurrent
+ imperative language",
+ journal = ic,
+ year = "2009",
+ note = "To appear",
+ URL = "ftp://ftp-sop.inria.fr/mimosa/personnel/gbo/ttiahocil.pdf",
+}
+
+@InProceedings{boulme-07,
+ author = "Sylvain Boulmé",
+ title = "Intuitionistic Refinement Calculus",
+ booktitle = tlca,
+ year = "2007",
+ pages = "54--69",
+ volume = "4583",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www-lsr.imag.fr/users/Sylvain.Boulme/horefinement/dsm.pdf",
+}
+
+@Misc{bound,
+ author = "Edward Kmett",
+ title = "Bound",
+ howpublished = "Blog post",
+ year = "2014",
+ URL = "https://www.fpcomplete.com/user/edwardk/bound",
+}
+
+@TechReport{bourdoncle-merz-96,
+ author = "François Bourdoncle and Stephan Merz",
+ title = "On the integration of functional programming,
+ class-based object-oriented programming, and
+ multi-methods",
+ institution = "Centre de Mathématiques Appliquées, Ecole des Mines
+ de Paris",
+ year = "1996",
+ type = "Research Report",
+ number = "26",
+ URL = "http://www.loria.fr/~merz/papers/mlsub.html",
+}
+
+@InProceedings{bourdoncle-merz-97,
+ author = "François Bourdoncle and Stephan Merz",
+ title = "Type Checking Higher-Order Polymorphic Multi-Methods",
+ booktitle = popl,
+ year = "1997",
+ pages = "302--315",
+ URL = "http://www.exalead.com/Francois.Bourdoncle/popl97.html",
+}
+
+@InProceedings{boyapati-lee-rinard-02,
+ author = "Chandrasekhar Boyapati and Robert Lee and Martin
+ Rinard",
+ title = "Ownership types for safe programming: preventing data
+ races and deadlocks",
+ booktitle = oopsla,
+ year = "2002",
+ pages = "211--230",
+ URL = "http://doi.acm.org/10.1145/582419.582440",
+}
+
+@InProceedings{boyapati-liskov-shrira-03,
+ author = "Chandrasekhar Boyapati and Barbara Liskov and Liuba
+ Shrira",
+ title = "Ownership types for object encapsulation",
+ booktitle = popl,
+ year = "2003",
+ pages = "213--223",
+ URL = "http://www.pmg.lcs.mit.edu/~chandra/publications/popl03.pdf",
+}
+
+@Article{boyland-burying-01,
+ author = "John Boyland",
+ title = "Alias burying: Unique variables without destructive
+ reads",
+ journal = scp,
+ year = "2001",
+ volume = "31",
+ number = "6",
+ pages = "533--553",
+ URL = "http://www.cs.uwm.edu/faculty/boyland/papers/unique-preprint.ps",
+}
+
+@InProceedings{boyland-fractions-03,
+ author = "John Boyland",
+ title = "Checking Interference with Fractional Permissions",
+ booktitle = sas,
+ year = "2003",
+ series = lncs,
+ publisher = springer,
+ volume = "2694",
+ pages = "55--72",
+ URL = "http://www.cs.uwm.edu/~boyland/papers/permissions.pdf",
+}
+
+@Article{boyland-nesting-10,
+ author = "John Tang Boyland",
+ title = "Semantics of fractional permissions with nesting",
+ journal = toplas,
+ volume = "32",
+ number = "6",
+ pages = "22:1--22:33",
+ year = "2010",
+ URL = "http://dx.doi.org/10.1145/1749608.1749611",
+}
+
+@InProceedings{boyland-noble-retert-01,
+ author = "John Boyland and James Noble and William Retert",
+ title = "Capabilities for Sharing: {A} Generalisation of
+ Uniqueness and Read-Only",
+ booktitle = ecoop,
+ pages = "2--27",
+ year = "2001",
+ series = lncs,
+ volume = "2072",
+ publisher = springer,
+ URL = "http://www.cs.uwm.edu/~boyland/papers/capability.ps",
+}
+
+@InProceedings{boyland-retert-05,
+ author = "John Tang Boyland and William Retert",
+ title = "Connecting Effects and Uniqueness with Adoption",
+ booktitle = popl,
+ year = "2005",
+ pages = "283--295",
+ URL = "http://www.cs.uwm.edu/~boyland/papers/connecting2.pdf",
+}
+
+@InProceedings{bracha-cook-90,
+ author = "Gilad Bracha and William Cook",
+ title = "Mixin-based inheritance",
+ booktitle = oopsla,
+ pages = "303--311",
+ year = "1990",
+ URL = "http://www.bracha.org/oopsla90.ps",
+}
+
+@TechReport{bracha-lindstrom-91,
+ author = "Gilad Bracha and Gary Lindstrom",
+ title = "Modularity Meets Inheritance",
+ institution = "University of Utah",
+ year = "1991",
+ number = "UUCS-91-017",
+ URL = "http://www.bracha.org/modularity-meets-inheritance.ps",
+}
+
+@Book{bradley-manna-07,
+ author = "Aaron R. Bradley and Zohar Manna",
+ title = "The Calculus of Computation",
+ publisher = springer,
+ year = "2007",
+ URL = "http://www.springerlink.com/content/wv0127/?p=77473ec707e949ae8856c880fe4e7649&pi=0",
+}
+
+@InProceedings{braibant-pous-11,
+ author = "Thomas Braibant and Damien Pous",
+ title = "Tactics for Reasoning Modulo {AC} in {Coq}",
+ booktitle = cpp,
+ year = "2011",
+ pages = "167--182",
+ publisher = springer,
+ series = lncs,
+ volume = "7086",
+ URL = "http://arxiv.org/abs/1106.4448",
+}
+
+@Article{brandis-mossenbock-94,
+ author = "Marc M. Brandis and Hanspeter Mössenböck",
+ title = "Single-pass generation of static single-assignment
+ form for structured languages",
+ journal = toplas,
+ volume = "16",
+ number = "6",
+ year = "1994",
+ pages = "1684--1698",
+ URL = "ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe94.ps.gz",
+}
+
+@Article{brandt-henglein-98,
+ author = "Michael Brandt and Fritz Henglein",
+ year = "1998",
+ title = "Coinductive axiomatization of recursive type equality
+ and subtyping",
+ journal = fundamenta,
+ pages = "309--338",
+ volume = "33",
+ URL = "ftp://ftp.diku.dk/diku/semantics/papers/D-353.ps.gz",
+}
+
+@Article{breazu-tannen-91,
+ author = "Val Breazu-Tannen and Thierry Coquand and Carl A.
+ Gunter and Andre Scedrov",
+ title = "Inheritance as Implicit Coercion",
+ journal = ic,
+ year = "1991",
+ volume = "93",
+ number = "1",
+ pages = "172--221",
+ URL = "http://seclab.uiuc.edu/cgunter/publications/documents/Breazu-TannenCGS91.pdf",
+}
+
+@InProceedings{brookes-04,
+ author = "Stephen D. Brookes",
+ title = "A Semantics for Concurrent Separation Logic",
+ booktitle = concur,
+ year = "2004",
+ pages = "16--34",
+ publisher = springer,
+ series = lncs,
+ volume = "3170",
+ URL = "http://dx.doi.org/10.1007/978-3-540-28644-8_2",
+}
+
+@Article{brookes-ohearn-16,
+ author = "Stephen Brookes and Peter W. O'Hearn",
+ title = "Concurrent separation logic",
+ journal = "{SIGLOG} News",
+ volume = "3",
+ number = "3",
+ pages = "47--65",
+ year = "2016",
+ URL = "http://siglog.hosting.acm.org/wp-content/uploads/2016/07/siglog_news_9.pdf#page=49",
+}
+
+@InProceedings{brotherston-cyclic-11,
+ author = "James Brotherston and Dino Distefano and Rasmus
+ Lerchedahl Petersen",
+ title = "Automated Cyclic Entailment Proofs in Separation
+ Logic",
+ booktitle = cade,
+ year = "2011",
+ pages = "131--146",
+ publisher = springer,
+ series = lncs,
+ volume = "6803",
+ URL = "http://www.eecs.qmul.ac.uk/~rusmus/articles/Cyclic.pdf",
+}
+
+@TechReport{bruce-alii-binary-methods,
+ key = "Bruce, {\em et al.}",
+ author = "Kim Bruce and Luca Cardelli and Giuseppe Castagna and
+ The Hopkins Object Group and Gary T. Leavens and
+ Benjamin Pierce",
+ title = "On Binary Methods",
+ year = "1995",
+ institution = "Department of Computer Science, Iowa State
+ University",
+ number = "95-08a",
+ URL = "ftp://ftp.cs.iastate.edu/pub/techreports/TR95-08/TR.ps.Z",
+}
+
+@Article{bruce-cardelli-pierce-99,
+ author = "Kim B. Bruce and Luca Cardelli and Benjamin C.
+ Pierce",
+ title = "Comparing Object Encodings",
+ journal = ic,
+ year = "1999",
+ volume = "155",
+ number = "1/2",
+ pages = "108--133",
+ URL = "http://www.cis.upenn.edu/~bcpierce/papers/compobj.ps",
+}
+
+@Article{bruce-dicosmo-longo-92,
+ author = "Kim Bruce and Roberto {Di Cosmo} and Giuseppe Longo",
+ title = "Provable isomorphisms of types",
+ journal = mscs,
+ year = "1992",
+ volume = "2",
+ number = "2",
+ pages = "231--247",
+ URL = "http://www.dicosmo.org/Articles/MSCS.dvi",
+}
+
+@Article{buchlovsky-thielecke-06,
+ author = "Peter Buchlovsky and Hayo Thielecke",
+ title = "A type-theoretic reconstruction of the Visitor
+ pattern",
+ journal = entcs,
+ volume = "155",
+ pages = "309--329",
+ year = "2006",
+ URL = "http://www.cs.bham.ac.uk/~hxt/research/mfps-visitors.pdf",
+}
+
+@Unpublished{bugliesi-affine-15,
+ author = "Michele Bugliesi and Stefano Calzavara and Fabienne
+ Eigner and Matteo Maffei",
+ title = "Affine Refinement Types for Secure Distributed
+ Programming",
+ note = "To appear",
+ year = "2015",
+ URL = "http://www.sps.cs.uni-saarland.de/affine-rcf/resources/long.pdf",
+}
+
+@InProceedings{bugliesi-crafa-dynamic-99,
+ author = "Michele Bugliesi and Silvia Crafa",
+ title = "Object Calculi for Dynamic Messages",
+ booktitle = fool,
+ year = "1999",
+}
+
+@Article{bugliesi-pericas-02,
+ author = "Michele Bugliesi and Santiago M.
+ Peric{\'a}s-Geertsen",
+ title = "Type Inference for Variant Object Types",
+ journal = ic,
+ year = "2002",
+ volume = "177",
+ number = "1",
+ pages = "2--27",
+ URL = "http://www.dsi.unive.it/~michele/Papers/PS/SplitTypes-ic02.ps.gz",
+}
+
+@Article{buisse-11,
+ author = "Alexandre Buisse and Lars Birkedal and Kristian
+ St{\o}vring",
+ title = "A Step-Indexed {Kripke} Model of Separation Logic for
+ Storable Locks",
+ journal = entcs,
+ volume = "276",
+ year = "2011",
+ pages = "121--143",
+ URL = "http://www.itu.dk/~birkedal/papers/locks.pdf",
+}
+
+@InProceedings{bulwahn-08,
+ author = "Lukas Bulwahn and Alexander Krauss and Florian
+ Haftmann and Levent Erk{\"{o}}k and John Matthews",
+ title = "Imperative Functional Programming with
+ {Isabelle/HOL}",
+ booktitle = tphol,
+ pages = "134--149",
+ year = "2008",
+ series = lncs,
+ volume = "5170",
+ publisher = springer,
+ URL = "http://www21.in.tum.de/~krauss/imperative/imperative.pdf",
+}
+
+@Article{buneman-ohori-96,
+ author = "Peter Buneman and Atsushi Ohori",
+ title = "Polymorphism and Type Inference in Database
+ Programming",
+ journal = tods,
+ year = "1996",
+ volume = "21",
+ number = "1",
+ pages = "30--76",
+ URL = "http://www.jaist.ac.jp/~ohori/research/tods96.pdf",
+}
+
+@InProceedings{burstall-hope-80,
+ author = "R. M. Burstall and D. B. MacQueen and D. T. Sannella",
+ title = "{HOPE}: An experimental applicative language",
+ booktitle = lfp,
+ year = "1980",
+ pages = "136--143",
+ URL = "http://portal.acm.org/citation.cfm?id=802799",
+}
+
+@Article{cai-paige-89,
+ author = "Jiazhen Cai and Robert Paige",
+ title = "Program derivation by fixed point computation",
+ journal = scp,
+ volume = "11",
+ number = "3",
+ year = "1989",
+ pages = "197--261",
+ URL = "http://cs.nyu.edu/paige/papers/fixpoint.ps",
+}
+
+@InProceedings{caires-seco-13,
+ author = "Lu\'{\i}s Caires and Jo{\~a}o Costa Seco",
+ title = "The type discipline of behavioral separation",
+ booktitle = popl,
+ year = "2013",
+ pages = "275--286",
+ URL = "http://dx.doi.org/10.1145/2429069.2429103",
+}
+
+@InProceedings{cakeml-new-16,
+ author = "Yong Kiam Tan and Magnus O. Myreen and Ramana Kumar
+ and Anthony C. J. Fox and Scott Owens and Michael
+ Norrish",
+ title = "A new verified compiler backend for {CakeML}",
+ booktitle = icfp,
+ pages = "60--73",
+ year = "2016",
+ URL = "https://cakeml.org/icfp16.pdf",
+}
+
+@Article{calcagno-02,
+ author = "Cristiano Calcagno and Simon Helsen and Peter
+ Thiemann",
+ title = "Syntactic Type Soundness Results for the Region
+ Calculus",
+ journal = ic,
+ year = "2002",
+ volume = "173",
+ number = "2",
+ pages = "199--221",
+ URL = "http://www.dcs.qmw.ac.uk/~ccris/ftp/iac_calhelthi.pdf",
+}
+
+@InProceedings{calcagno-11,
+ author = "Cristiano Calcagno and Dino Distefano",
+ title = "Infer: An Automatic Program Verifier for Memory Safety
+ of {C} Programs",
+ booktitle = nfm,
+ pages = "459--465",
+ year = "2011",
+ series = lncs,
+ volume = "6617",
+ publisher = springer,
+ URL = "http://www.eecs.qmul.ac.uk/~ddino/papers/nasa-infer.pdf",
+}
+
+@InProceedings{calcagno-15,
+ author = "Cristiano Calcagno and Dino Distefano and
+ J{\'{e}}r{\'{e}}my Dubreil and Dominik Gabi and Pieter
+ Hooimeijer and Martino Luca and Peter W. O'Hearn and
+ Irene Papakonstantinou and Jim Purbrick and Dulma
+ Rodriguez",
+ title = "Moving Fast with Software Verification",
+ booktitle = nfm,
+ pages = "3--11",
+ year = "2015",
+ series = lncs,
+ volume = "9058",
+ publisher = springer,
+ URL = "https://research.facebook.com/publications/moving-fast-with-software-verification/",
+}
+
+@Article{calcagno-closed-03,
+ author = "Cristiano Calcagno and Eugenio Moggi and Tim Sheard",
+ title = "Closed Types for a Safe Imperative {MetaML}",
+ journal = jfp,
+ year = "2003",
+ volume = "13",
+ number = "3",
+ pages = "545--571",
+ URL = "http://dx.doi.org/10.1017/S0956796802004598",
+}
+
+@InProceedings{calcagno-distefano-ohearn-yang-09,
+ author = "Cristiano Calcagno and Dino Distefano and Peter W.
+ O'Hearn and Hongseok Yang",
+ title = "Compositional shape analysis by means of
+ bi-abduction",
+ booktitle = popl,
+ year = "2009",
+ pages = "289--300",
+ URL = "http://www.doc.ic.ac.uk/~ccris/ftp/popl09.pdf",
+}
+
+@Article{calcagno-distefano-ohearn-yang-11,
+ author = "Cristiano Calcagno and Dino Distefano and Peter W.
+ O'Hearn and Hongseok Yang",
+ title = "Compositional Shape Analysis by Means of
+ Bi-Abduction",
+ journal = jacm,
+ volume = "58",
+ number = "6",
+ year = "2011",
+ URL = "http://www.doc.ic.ac.uk/~ccris/ftp/jacm-abduction.pdf",
+}
+
+@InProceedings{calcagno-distefano-vafeiadis-09,
+ author = "Cristiano Calcagno and Dino Distefano and Viktor
+ Vafeiadis",
+ title = "Bi-abductive Resource Invariant Synthesis",
+ booktitle = aplas,
+ year = "2009",
+ pages = "259--274",
+ publisher = springer,
+ series = lncs,
+ volume = "5904",
+ URL = "http://www.eecs.qmul.ac.uk/~ddino/papers/resinvariant.pdf",
+}
+
+@InProceedings{calcagno-inference-04,
+ author = "Cristiano Calcagno and Eugenio Moggi and Walid Taha",
+ title = "{ML}-Like Inference for Classifiers",
+ booktitle = esop,
+ year = "2004",
+ pages = "79--93",
+ series = lncs,
+ volume = "2986",
+ publisher = springer,
+ URL = "http://www.doc.ic.ac.uk/~ccris/ftp/esop04.pdf",
+}
+
+@InProceedings{calcagno-local-07,
+ author = "Cristiano Calcagno and Peter W. O'Hearn and Hongseok
+ Yang",
+ title = "Local Action and Abstract Separation Logic",
+ booktitle = lics,
+ year = "2007",
+ pages = "366--378",
+ URL = "http://www.doc.ic.ac.uk/~ccris/ftp/asl-short.pdf",
+}
+
+@InProceedings{calcagno-yang-ohearn-01,
+ author = "Cristiano Calcagno and Hongseok Yang and Peter W.
+ O'Hearn",
+ title = "Computability and Complexity Results for a Spatial
+ Assertion Language for Data Structures",
+ booktitle = aplas,
+ pages = "289--300",
+ year = "2001",
+ URL = "http://www.cs.ox.ac.uk/people/hongseok.yang/paper/decidability.ps",
+}
+
+@Misc{caml-light,
+ author = "Xavier Leroy and Damien Doligez and Michel Mauny and
+ Pierre Weis",
+ title = "The {Caml} {Light} system, release 0.75",
+ year = "2002",
+ URL = "http://caml.inria.fr/",
+}
+
+@InProceedings{carbonneaux-14,
+ author = "Quentin Carbonneaux and Jan Hoffmann and Tahina
+ Ramananandro and Zhong Shao",
+ title = "End-to-end verification of stack-space bounds for {C}
+ programs",
+ booktitle = pldi,
+ pages = "270--281",
+ year = "2014",
+ URL = "http://flint.cs.yale.edu/flint/publications/veristack.pdf",
+}
+
+@InCollection{cardelli-97,
+ author = "Luca Cardelli",
+ title = "Type Systems",
+ booktitle = "The Computer Science and Engineering Handbook",
+ publisher = "CRC Press",
+ year = "1997",
+ editor = "Allen B. Tucker",
+ pages = "2208--2236",
+ URL = "http://research.microsoft.com/Users/luca/Papers/TypeSystems.pdf",
+}
+
+@Article{cardelli-basic-87,
+ author = "Luca Cardelli",
+ title = "Basic polymorphic typechecking",
+ journal = scp,
+ year = "1987",
+ volume = "8",
+ number = "2",
+ pages = "147--172",
+ URL = "http://research.microsoft.com/Users/luca/Papers/BasicTypechecking.pdf",
+}
+
+@TechReport{cardelli-extensible-94,
+ author = "Luca Cardelli and Florian Matthes and Martín Abadi",
+ title = "Extensible syntax with lexical scoping",
+ institution = decsrc,
+ year = "1994",
+ type = "Research Report",
+ number = "121",
+ URL = "http://gatekeeper.dec.com/pub/compaq/SRC/research-reports/SRC-121.ps.gz",
+}
+
+@Article{cardelli-longo-91,
+ author = "Luca Cardelli and Giuseppe Longo",
+ title = "A semantic basis for {Quest}",
+ journal = jfp,
+ year = "1991",
+ volume = "1",
+ number = "4",
+ pages = "417--458",
+ URL = "http://research.microsoft.com/Users/luca/Papers/QuestSem.pdf",
+}
+
+@InCollection{cardelli-mitchell-records-91,
+ author = "Luca Cardelli and John Mitchell",
+ title = "Operations on Records",
+ booktitle = taoop,
+ publisher = mitp,
+ editor = "Carl A. Gunter and John C. Mitchell",
+ year = "1994",
+ URL = "http://research.microsoft.com/Users/luca/Papers/Records.pdf",
+}
+
+@Article{cardelli-multiple-88,
+ author = "Luca Cardelli",
+ title = "A Semantics of Multiple Inheritance",
+ journal = ic,
+ volume = "76",
+ number = "2/3",
+ year = "1988",
+ pages = "138--164",
+ URL = "http://research.microsoft.com/Users/luca/Papers/Inheritance.pdf",
+}
+
+@Misc{cardelli-quest-91,
+ author = "Luca Cardelli",
+ title = "The {Quest} Language and System",
+ year = "1991",
+ URL = "http://research.microsoft.com/Users/luca/Notes/QuestManual.pdf",
+}
+
+@InProceedings{cardelli-typeful-89,
+ author = "Luca Cardelli",
+ title = "Typeful programming",
+ booktitle = "Formal Description of Programming Concepts",
+ year = "1989",
+ series = "IFIP State of the Art Reports Series",
+ publisher = springer,
+ URL = "http://research.microsoft.com/Users/luca/Papers/TypefulProg.pdf",
+}
+
+@Article{cardelli-wegner-85,
+ author = "Luca Cardelli and Peter Wegner",
+ title = "On Understanding Types, Data Abstraction, and
+ Polymorphism",
+ journal = surveys,
+ volume = "17",
+ number = "4",
+ pages = "471--522",
+ year = "1985",
+ URL = "http://research.microsoft.com/Users/luca/Papers/OnUnderstanding.pdf",
+}
+
+@Article{cardone-02,
+ author = "Felice Cardone",
+ title = "A coinductive completeness proof for the equivalence
+ of recursive types",
+ journal = tcs,
+ volume = "275",
+ number = "1--2",
+ year = "2002",
+ pages = "575--587",
+ URL = "http://dx.doi.org/10.1016/S0304-3975(01)00298-5",
+ publisher = elsevier,
+}
+
+@Article{cardone-coppo-91,
+ author = "Felice Cardone and Mario Coppo",
+ title = "Type inference with recursive types: syntax and
+ semantics",
+ journal = ic,
+ volume = "92",
+ number = "1",
+ year = "1991",
+ pages = "48--80",
+ URL = "http://dx.doi.org/10.1016/0890-5401(91)90020-3",
+}
+
+@InProceedings{carette-finally-tagless-07,
+ author = "Jacques Carette and Oleg Kiselyov and Chung-chieh
+ Shan",
+ title = "Finally Tagless, Partially Evaluated",
+ booktitle = aplas,
+ year = "2007",
+ pages = "222--238",
+ publisher = springer,
+ series = lncs,
+ volume = "4807",
+ URL = "http://okmij.org/ftp/papers/tagless-final-APLAS.pdf",
+}
+
+@Article{carette-gauss-05,
+ author = "Jacques Carette",
+ title = "{Gaussian} Elimination: a case study in efficient
+ genericity with {MetaOCaml}",
+ journal = scp,
+ year = "2005",
+ volume = "62",
+ number = "1",
+ pages = "3--24",
+ URL = "http://www.cas.mcmaster.ca/~carette/publications/ge.pdf",
+}
+
+@InProceedings{carlier-04,
+ author = "Sébastien Carlier and Jeff Polakow and J. B. Wells
+ and A. J. Kfoury",
+ title = "{System E}: Expansion variables for flexible typing
+ with linear and non-linear types and intersection
+ types",
+ booktitle = esop,
+ year = "2004",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.macs.hw.ac.uk/~jbw/papers/Carlier+Polakow+Wells+Kfoury:System-E:ESOP-2004.pdf",
+}
+
+@TechReport{carlier-wells-04,
+ author = "Sébastien Carlier and J. B. Wells",
+ title = "Type inference with expansion variables and
+ intersection types in {System E} and an exact
+ correspondence with $\beta$-reduction",
+ institution = "Heriot-Watt University",
+ year = "2004",
+ number = "HW-MACS-TR-0012",
+ URL = "http://www.macs.hw.ac.uk:8080/techreps/docs/files/HW-MACS-TR-0012.pdf",
+}
+
+@Misc{cartwright-notes-00,
+ author = "Robert Cartwright",
+ title = "Notes on Object-Oriented Program Design",
+ URL = "http://www.cs.rice.edu/~cork/book/",
+ year = "2000",
+}
+
+@InProceedings{castagna-ampersand-93,
+ author = "Giuseppe Castagna",
+ title = "${F}_{\leq}^{\&}$ : integrating parametric and ``ad
+ hoc'' second order polymorphism",
+ booktitle = "International Workshop on Database Programming
+ Languages",
+ year = "1993",
+ publisher = springer,
+ series = "Workshops in Computing",
+}
+
+@Article{castagna-contravariance-95,
+ author = "Giuseppe Castagna",
+ title = "Covariance and Contravariance: Conflict without a
+ Cause",
+ journal = toplas,
+ volume = "17",
+ number = "3",
+ pages = "431--447",
+ year = "1995",
+ URL = "ftp://ftp.ens.fr/pub/di/users/castagna/covariance.ps.Z",
+}
+
+@InProceedings{castagna-frisch-05,
+ author = "Giuseppe Castagna and Alain Frisch",
+ title = "A gentle introduction to semantic subtyping",
+ booktitle = ppdp,
+ year = "2005",
+ pages = "198--199",
+ URL = "http://www.pps.univ-paris-diderot.fr/~gc/papers/icalp-ppdp05.pdf",
+}
+
+@InProceedings{cejtin-al-00,
+ author = "Henry Cejtin and Suresh Jagannathan and Stephen
+ Weeks",
+ title = "Flow-directed Closure Conversion for Typed Languages",
+ booktitle = esop,
+ publisher = springer,
+ series = lncs,
+ volume = "1782",
+ pages = "56--71",
+ year = "2000",
+ URL = "http://mlton.org/papers/00-esop.ps.gz",
+}
+
+@InProceedings{cerco,
+ author = "Roberto M. Amadio and Nicholas Ayache and
+ Fran{\c{c}}ois Bobot and Jaap Boender and Brian
+ Campbell and Ilias Garnier and Antoine Madet and James
+ McKinna and Dominic P. Mulligan and Mauro Piccolo and
+ Randy Pollack and Yann R{\'{e}}gis{-}Gianas and Claudio
+ Sacerdoti Coen and Ian Stark and Paolo Tranquilli",
+ title = "Certified Complexity ({CerCo})",
+ booktitle = fopara,
+ pages = "1--18",
+ year = "2014",
+ series = lncs,
+ publisher = springer,
+ volume = "8552",
+ URL = "http://dx.doi.org/10.1007/978-3-319-12466-7_1",
+}
+
+@Misc{cfml,
+ author = "Arthur Charguéraud",
+ title = "The {CFML} tool and library",
+ howpublished = "\url{http://www.chargueraud.org/softs/cfml/}",
+ year = "2016",
+}
+
+@InProceedings{chakravarty-associated-05,
+ author = "Manuel M. T. Chakravarty and Gabriele Keller and Simon
+ L. {Peyton Jones} and Simon Marlow",
+ title = "Associated types with class",
+ booktitle = popl,
+ pages = "1--13",
+ year = "2005",
+ URL = "https://research.microsoft.com/en-us/um/people/simonpj/papers/assoc-types/assoc.pdf",
+}
+
+@TechReport{chambers-leavens-96,
+ author = "Craig Chambers and Gary T. Leavens",
+ title = "{BeCecil}, a Core Object-Oriented Language with Block
+ Structure and Multimethods: Semantics and Typing",
+ institution = "University of Washington",
+ year = "1996",
+ number = "UW-CSE-96-12-02",
+ URL = "ftp://ftp.cs.washington.edu/pub/chambers/BeCecil.ps.gz",
+}
+
+@Misc{chameleon,
+ author = "Andreas Rossberg and Peter J. Stuckey and Martin
+ Sulzmann and Jeremy Wazny",
+ title = "The {Chameleon} language",
+ URL = "http://taichi.ddns.comp.nus.edu.sg/taichiwiki/ChameleonHomePage",
+}
+
+@InProceedings{chang-rival-08,
+ author = "Bor-Yuh Evan Chang and Xavier Rival",
+ title = "Relational inductive shape analysis",
+ booktitle = popl,
+ year = "2008",
+ pages = "247--260",
+ URL = "http://xisa.cs.colorado.edu/papers/popl08-relational.pdf",
+}
+
+@PhdThesis{chargueraud-10,
+ author = "Arthur Charguéraud",
+ title = "Characteristic Formulae for Mechanized Program
+ Verification",
+ school = "Université Paris 7",
+ year = "2010",
+ URL = "http://www.chargueraud.org/research/2010/thesis/thesis_final.pdf",
+}
+
+@InProceedings{chargueraud-10-cfml,
+ author = "Arthur Chargu{\'e}raud",
+ title = "Program Verification Through Characteristic Formulae",
+ booktitle = icfp,
+ year = "2010",
+ pages = "321--332",
+ URL = "http://www.chargueraud.org/research/2010/cfml/main.pdf",
+}
+
+@InProceedings{chargueraud-11-cfml,
+ author = "Arthur Chargu{\'e}raud",
+ title = "Characteristic Formulae for the Verification of
+ Imperative Programs",
+ booktitle = icfp,
+ year = "2011",
+ pages = "418--430",
+ URL = "http://www.chargueraud.org/research/2011/cfml/main.pdf",
+}
+
+@Misc{chargueraud-cfml,
+ author = "Arthur Charguéraud",
+ title = "Characteristic Formulae for the Verification of
+ Imperative Programs",
+ year = "2013",
+ note = "Unpublished.
+ \url{http://www.chargueraud.org/research/2013/cf/cf.pdf}",
+}
+
+@Article{chargueraud-ln-11,
+ author = "Arthur Chargu{\'e}raud",
+ title = "The Locally Nameless Representation",
+ year = "2012",
+ journal = jar,
+ volume = "49",
+ number = "3",
+ pages = "363--408",
+ URL = "http://www.chargueraud.org/arthur/research/2009/ln/main.pdf",
+}
+
+@InProceedings{chargueraud-pottier-08,
+ author = "Arthur Charguéraud and François Pottier",
+ title = "Functional Translation of a Calculus of Capabilities",
+ booktitle = icfp,
+ year = "2008",
+ pages = "213--224",
+ URL = "http://gallium.inria.fr/~fpottier/publis/chargueraud-pottier-capabilities.pdf",
+}
+
+@InProceedings{chargueraud-pottier-15,
+ author = "Arthur Charguéraud and François Pottier",
+ title = "Machine-Checked Verification of the Correctness and
+ Amortized Complexity of an Efficient Union-Find
+ Implementation",
+ booktitle = itp,
+ year = "2015",
+ volume = "9236",
+ series = lncs,
+ publisher = springer,
+ pages = "137--153",
+ URL = "http://gallium.inria.fr/~fpottier/publis/chargueraud-pottier-uf.pdf",
+}
+
+@TechReport{chen-al-99,
+ author = "Martin Odersky and Christoph Zenger and Matthias
+ Zenger and Gang Chen",
+ title = "A Functional View Of Join",
+ institution = "University of South Australia",
+ year = "1999",
+ number = "ACRC-99-016",
+ URL = "http://www.christoph-zenger.de/papers/tr-acrc-99-016.ps.gz",
+}
+
+@InProceedings{chen-crash-16,
+ author = "Haogang Chen and Daniel Ziegler and Tej Chajed and
+ Adam Chlipala and M. Frans Kaashoek and Nickolai
+ Zeldovich",
+ title = "Using {Crash Hoare logic} for certifying the {FSCQ}
+ file system",
+ booktitle = sosp,
+ pages = "18--37",
+ year = "2015",
+ URL = "https://people.csail.mit.edu/nickolai/papers/chen-fscq.pdf",
+}
+
+@InProceedings{chen-hudak-97,
+ author = "Chih-Ping Chen and Paul Hudak",
+ title = "Rolling your own mutable {ADT}---a connection between
+ linear types and monads",
+ booktitle = popl,
+ year = "1997",
+ pages = "54--66",
+ URL = "http://www.cs.yale.edu/homes/hudak-paul/hudak-dir/popl97.ps",
+}
+
+@InProceedings{chen-shi-xi-04,
+ author = "Chiyan Chen and Rui Shi and Hongwei Xi",
+ title = "A Typeful Approach to Object-Oriented Programming with
+ Multiple Inheritance",
+ booktitle = padl,
+ publisher = springer,
+ series = lncs,
+ volume = "3057",
+ year = "2004",
+ URL = "http://www.cs.bu.edu/~hwxi/academic/papers/OBJwMI/OBJwMI.pdf",
+}
+
+@InProceedings{chen-tarditi-05,
+ author = "Juan Chen and David Tarditi",
+ title = "A simple typed intermediate language for
+ object-oriented languages",
+ booktitle = popl,
+ year = "2005",
+ pages = "38--49",
+ URL = "http://research.microsoft.com/pubs/59934/lilc_popl05.pdf",
+}
+
+@InProceedings{chen-xi-05,
+ author = "Chiyan Chen and Hongwei Xi",
+ title = "Combining Programming with Theorem Proving",
+ booktitle = icfp,
+ year = "2005",
+ pages = "66--77",
+ URL = "http://www.cs.bu.edu/~hwxi/academic/papers/icfp05.pdf",
+}
+
+@InProceedings{chen-xi-icfp-03,
+ author = "Chiyan Chen and Hongwei Xi",
+ title = "Meta-Programming through Typeful Code Representation",
+ booktitle = icfp,
+ year = "2003",
+ pages = "275--286",
+ URL = "http://www.cs.bu.edu/~hwxi/academic/papers/icfp03.pdf",
+}
+
+@InProceedings{chen-xi-pepm-03,
+ author = "Chiyan Chen and Hongwei Xi",
+ title = "Implementing Typeful Program Transformations",
+ booktitle = pepm,
+ year = "2003",
+ pages = "20--28",
+ URL = "http://www.cs.bu.edu/~hwxi/academic/papers/pepm03.pdf",
+}
+
+@InProceedings{cheney-05,
+ author = "James Cheney",
+ title = "Scrap your nameplate",
+ booktitle = icfp,
+ year = "2005",
+ pages = "180--191",
+ URL = "http://homepages.inf.ed.ac.uk/jcheney/publications/cheney05icfp.pdf",
+}
+
+@InProceedings{cheney-hinze-02,
+ author = "James Cheney and Ralf Hinze",
+ title = "A lightweight implementation of generics and
+ dynamics",
+ booktitle = hw,
+ year = "2002",
+ URL = "http://www.cs.cornell.edu/people/jcheney/papers/Dynamic-final.pdf",
+}
+
+@TechReport{cheney-hinze-03,
+ author = "James Cheney and Ralf Hinze",
+ title = "First-Class Phantom Types",
+ institution = "Cornell University",
+ year = "2003",
+ number = "1901",
+ URL = "http://techreports.library.cornell.edu:8081/Dienst/UI/1.0/Display/cul.cis/TR2003-1901",
+}
+
+@InProceedings{cheney-urban-04,
+ author = "James Cheney and Christian Urban",
+ title = "{$\alpha$Prolog}: {A} Logic Programming Language with
+ Names, Binding and $\alpha$-equivalence",
+ booktitle = iclp,
+ pages = "269--283",
+ year = "2004",
+ volume = "3132",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.cs.cornell.edu/people/jcheney/papers/alpnba.pdf",
+}
+
+@InProceedings{cheng-blelloch-01,
+ author = "Perry Cheng and Guy E. Blelloch",
+ title = "A Parallel, Real-Time Garbage Collector",
+ booktitle = pldi,
+ pages = "125--136",
+ year = "2001",
+ URL = "https://www.cs.cmu.edu/~guyb/papers/gc2001.pdf",
+}
+
+@Article{chin-khoo-01,
+ author = "Wei-Ngan Chin and Siau-Cheng Khoo",
+ title = "Calculating Sized Types",
+ journal = hosc,
+ volume = "14",
+ number = "2--3",
+ year = "2001",
+ pages = "261--300",
+ publisher = kluwer,
+ URL = "http://dx.doi.org/10.1023/A:1012996816178",
+}
+
+@InProceedings{chitil-01,
+ author = "Olaf Chitil",
+ title = "Compositional Explanation of Types and Algorithmic
+ Debugging of Type Errors",
+ booktitle = icfp,
+ pages = "193--204",
+ year = "2001",
+ URL = "http://www-users.cs.york.ac.uk/~olaf/PUBLICATIONS/explainTypes.ps.gz",
+}
+
+@InProceedings{chlipala-07,
+ author = "Adam Chlipala",
+ title = "A certified type-preserving compiler from lambda
+ calculus to assembly language",
+ booktitle = pldi,
+ year = "2007",
+ pages = "54--65",
+ URL = "http://www.cs.berkeley.edu/~adamc/papers/CtpcPLDI07/CtpcPLDI07.pdf",
+}
+
+@InProceedings{chlipala-08,
+ author = "Adam Chlipala",
+ title = "Parametric higher-order abstract syntax for mechanized
+ semantics",
+ booktitle = icfp,
+ year = "2008",
+ pages = "143--156",
+ URL = "http://adam.chlipala.net/papers/PhoasICFP08/PhoasICFP08.pdf",
+}
+
+@InProceedings{chlipala-15,
+ author = "Adam Chlipala",
+ title = "From Network Interface to Multithreaded Web
+ Applications: {A} Case Study in Modular Program
+ Verification",
+ booktitle = popl,
+ pages = "609--622",
+ year = "2015",
+ URL = "http://adam.chlipala.net/papers/BedrockPOPL15/BedrockPOPL15.pdf",
+}
+
+@InProceedings{chlipala-bedrock-13,
+ author = "Adam Chlipala",
+ title = "The {Bedrock} structured programming system: combining
+ generative metaprogramming and {Hoare} logic in an
+ extensible program verifier",
+ booktitle = icfp,
+ pages = "391--402",
+ year = "2013",
+ URL = "http://adam.chlipala.net/papers/BedrockICFP13/BedrockICFP13.pdf",
+}
+
+@Book{chlipala-cpdt-13,
+ author = "Adam Chlipala",
+ title = "Certified Programming and Dependent Types",
+ publisher = mitp,
+ year = "2013",
+ URL = "http://adam.chlipala.net/cpdt/",
+}
+
+@InProceedings{chlipala-ynot-09,
+ author = "Adam Chlipala and Gregory Malecha and Greg Morrisett
+ and Avraham Shinnar and Ryan Wisnesky",
+ title = "Effective interactive proofs for higher-order
+ imperative programs",
+ booktitle = icfp,
+ year = "2009",
+ pages = "79--90",
+ URL = "http://ynot.cs.harvard.edu/papers/icfp09.pdf",
+}
+
+@PhdThesis{choppella-02,
+ author = "Venkatesh Choppella",
+ title = "Unification Source-tracking with Application to
+ Diagnosis of Type Inference",
+ school = "Indiana University",
+ year = "2002",
+ URL = "http://www.cs.indiana.edu/cgi-bin/techreports/TRNNN.cgi?trnum=TR566",
+}
+
+@InProceedings{chrzaszcz-98,
+ author = "Jacek Chrzaszcz",
+ title = "Polymorphic Subtyping Without Distributivity",
+ booktitle = mfcs,
+ pages = "346--355",
+ year = "1998",
+ series = lncs,
+ volume = "1450",
+ publisher = springer,
+ URL = "http://www.mimuw.edu.pl/~chrzaszc/papers/Chrzaszcz_Polymorphic-subtyping-without-distributivity.ps.gz",
+}
+
+@Article{clarke-79,
+ author = "Edmund Clarke",
+ title = "Programming Language Constructs for Which It Is
+ Impossible To Obtain Good {Hoare} Axiom Systems",
+ journal = jacm,
+ volume = "26",
+ number = "1",
+ year = "1979",
+ pages = "129--147",
+ URL = "http://doi.acm.org/10.1145/322108.322121",
+}
+
+@InProceedings{clarke-drossopoulou-02,
+ author = "Dave Clarke and Sophia Drossopoulou",
+ title = "Ownership, encapsulation and the disjointness of type
+ and effect",
+ booktitle = oopsla,
+ year = "2002",
+ pages = "292--310",
+ URL = "http://pubs.doc.ic.ac.uk/ownershipAndEffects/ownershipAndEffects.ps",
+}
+
+@InProceedings{clarke-noble-potter-01,
+ author = "David G. Clarke and James Noble and John Potter",
+ title = "Simple Ownership Types for Object Containment",
+ booktitle = ecoop,
+ year = "2001",
+ pages = "53--76",
+ publisher = springer,
+ series = lncs,
+ volume = "2072",
+ URL = "http://www.cs.washington.edu/education/courses/cse590p/00wi/simple.pdf",
+}
+
+@InProceedings{clarke-potter-noble-98,
+ author = "David G. Clarke and John M. Potter and James Noble",
+ title = "Ownership types for flexible alias protection",
+ booktitle = oopsla,
+ year = "1998",
+ pages = "48--64",
+ URL = "http://doi.acm.org/10.1145/286936.286947",
+}
+
+@InCollection{clarke-survey-13,
+ author = "Dave Clarke and Johan {\"O}stlund and Ilya Sergey and
+ Tobias Wrigstad",
+ title = "Ownership Types: {A} Survey",
+ booktitle = "Aliasing in Object-Oriented Programming. Types,
+ Analysis and Verification",
+ year = "2013",
+ pages = "15--58",
+ publisher = springer,
+ series = lncs,
+ volume = "7850",
+ URL = "http://dx.doi.org/10.1007/978-3-642-36946-9_3",
+}
+
+@InProceedings{clarke-wrigstad-03,
+ author = "Dave Clarke and Tobias Wrigstad",
+ title = "External Uniqueness Is Unique Enough",
+ booktitle = ecoop,
+ year = "2003",
+ pages = "176--200",
+ publisher = springer,
+ series = lncs,
+ volume = "2743",
+ URL = "https://lirias.kuleuven.be/bitstream/123456789/203436/1/euiue.pdf",
+}
+
+@InProceedings{cleaveland-steffen-91,
+ author = "Rance Cleaveland and Bernhard Steffen",
+ title = "A linear-time model-checking algorithm for the
+ alternation-free modal mu-calculus",
+ booktitle = cav,
+ pages = "48--58",
+ year = "1991",
+ volume = "575",
+ series = lncs,
+ publisher = springer,
+ URL = "http://dx.doi.org/10.1007/3-540-55179-4_6",
+}
+
+@InProceedings{clement-despeyroux-kahn-86,
+ author = "Dominique Cl{\'e}ment and Jo{\"e}lle Despeyroux and
+ Thierry Despeyroux and Gilles Kahn",
+ title = "A simple applicative language: Mini-{ML}",
+ booktitle = lfp,
+ year = "1986",
+ pages = "13--27",
+}
+
+@InProceedings{clements-felleisen-03,
+ author = "John Clements and Matthias Felleisen",
+ title = "A Tail-Recursive Semantics for Stack Inspections",
+ booktitle = esop,
+ pages = "22--37",
+ year = "2003",
+ volume = "2618",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.ccs.neu.edu/scheme/pubs/esop2003-cf.ps.gz",
+}
+
+@InProceedings{clochard-filliatre-paskevich-15,
+ title = "How to avoid proving the absence of integer
+ overflows",
+ author = "Martin Clochard and Jean-Christophe Filli{\^a}tre and
+ Andrei Paskevich",
+ URL = "https://hal.inria.fr/hal-01162661",
+ booktitle = vstte,
+ year = "2015",
+ pages = "94--109",
+ series = lncs,
+ volume = "9593",
+ publisher = springer,
+}
+
+@InProceedings{clochard-marche-paskevich-14,
+ author = "Martin Clochard and Claude March{\'{e}} and Andrei
+ Paskevich",
+ title = "Verified programs with binders",
+ booktitle = plpv,
+ pages = "29--40",
+ year = "2014",
+ URL = "https://hal.inria.fr/hal-00913431",
+}
+
+@InProceedings{coblenz-16,
+ author = "Michael J. Coblenz and Joshua Sunshine and Jonathan
+ Aldrich and Brad A. Myers and Sam Weber and Forrest
+ Shull",
+ title = "Exploring language support for immutability",
+ booktitle = icse,
+ pages = "736--747",
+ year = "2016",
+ URL = "http://www.cs.cmu.edu/~aldrich/papers/icse16-immutability.pdf",
+}
+
+@Article{cohen-search-06,
+ author = "Albert Cohen and Sébastien Donadio and Maria-Jesus
+ Garzaran and Christoph Herrmann and Oleg Kiselyov and
+ David Padua",
+ title = "In search of a program generator to implement generic
+ transformations for high-performance computing",
+ journal = scp,
+ year = "2006",
+ volume = "62",
+ number = "1",
+ pages = "25--46",
+ URL = "http://www-rocq.inria.fr/~acohen/publications/CDGHKP06.ps.gz",
+}
+
+@InProceedings{cohen-vcc-09,
+ author = "Ernie Cohen and Markus Dahlweid and Mark A. Hillebrand
+ and Dirk Leinenbach and Michal Moskal and Thomas Santen
+ and Wolfram Schulte and Stephan Tobies",
+ title = "{VCC}: {A} Practical System for Verifying Concurrent
+ {C}",
+ booktitle = tphol,
+ year = "2009",
+ pages = "23--42",
+ publisher = springer,
+ series = lncs,
+ volume = "5674",
+ URL = "http://research.microsoft.com/apps/pubs/default.aspx?id=117859",
+}
+
+@InProceedings{colazzo-ghelli-99,
+ author = "Dario Colazzo and Giorgio Ghelli",
+ title = "Subtyping Recursive Types in {Kernel Fun}",
+ booktitle = lics,
+ pages = "137--146",
+ year = "1999",
+}
+
+@TechReport{collins-shao-02,
+ author = "Gregory D. Collins and Zhong Shao",
+ title = "Intensional Analysis of Higher-Kinded Recursive
+ Types",
+ institution = "Yale University",
+ year = "2002",
+ number = "YALEU/DCS/TR-1240",
+ URL = "http://flint.cs.yale.edu/flint/publications/collins02-ita-tr.pdf",
+}
+
+@InProceedings{colmerauer-84,
+ author = "Alain Colmerauer",
+ title = "Equations and Inequations on Finite and Infinite
+ Trees",
+ booktitle = "International Conference on Fifth Generation Computer
+ Systems (FGCS)",
+ pages = "85--99",
+ year = "1984",
+}
+
+@Article{color,
+ author = "Frédéric Blanqui and Adam Koprowski",
+ title = "{CoLoR}: a Coq library on well-founded rewrite
+ relations and its application to the automated
+ verification of termination certificates",
+ journal = mscs,
+ year = "2011",
+ volume = "21",
+ number = "4",
+ pages = "827--859",
+ URL = "https://who.rocq.inria.fr/Frederic.Blanqui/papers/mscs11.pdf",
+}
+
+@InProceedings{comon-93,
+ author = "Hubert Comon",
+ title = "Constraints in Term Algebras (Short Survey)",
+ booktitle = amast,
+ year = "1993",
+ publisher = springer,
+ series = "Workshops in Computing",
+ URL = "http://www.lsv.ens-cachan.fr/~comon/ftp.articles/amast93.ps",
+}
+
+@Article{comon-lescanne-89,
+ author = "Hubert Comon and Pierre Lescanne",
+ title = "Equational Problems and Disunification",
+ journal = jsc,
+ year = "1989",
+ volume = "7",
+ pages = "371--425",
+ URL = "http://perso.ens-lyon.fr/pierre.lescanne/PUBLICATIONS/jsc-diseq.pdf",
+}
+
+@Misc{compcert,
+ author = "Xavier Leroy",
+ title = "The {CompCert C} compiler",
+ year = "2015",
+ howpublished = "\url{http://compcert.inria.fr/}",
+}
+
+@InProceedings{conchon-filliatre-07,
+ author = "Sylvain Conchon and Jean{-}Christophe
+ Filli{\^{a}}tre",
+ title = "A persistent union-find data structure",
+ booktitle = ml,
+ pages = "37--46",
+ year = "2007",
+ URL = "https://www.lri.fr/~filliatr/puf/",
+}
+
+@Book{conchon-filliatre-ocaml-14,
+ author = "Sylvain Conchon et Jean-Christophe Filliâtre",
+ title = "Apprendre à programmer avec {OCaml}: Algorithmes et
+ structures de données",
+ publisher = "Eyrolles",
+ year = "2014",
+ URL = "http://programmer-avec-ocaml.lri.fr/",
+}
+
+@InProceedings{conchon-kanig-lescuyer-08,
+ author = "Sylvain Conchon and Johannes Kanig and Stéphane
+ Lescuyer",
+ title = "\textsc{Sat-Micro}: petit mais costaud!",
+ booktitle = jfla,
+ year = "2008",
+ URL = "http://www.lri.fr/~conchon/publis/conchon-jfla08.ps",
+}
+
+@InProceedings{conchon-le-fessant-99,
+ title = "Jocaml: Mobile Agents for {Objective-Caml}",
+ author = "Sylvain Conchon and Fabrice Le Fessant",
+ booktitle = "International Symposium on Agent Systems and
+ Applications and International Symposium on Mobile
+ Agents (ASA/MA)",
+ year = "1999",
+ pages = "22--29",
+ URL = "http://para.inria.fr/~conchon/publis/conchon-lefessant-asama99.ps.gz",
+}
+
+@InProceedings{conchon-pottier-01,
+ author = "Sylvain Conchon and François Pottier",
+ title = "{JOIN(X)}: Constraint-Based Type Inference for the
+ Join-Calculus",
+ booktitle = esop,
+ publisher = springer,
+ series = lncs,
+ volume = "2028",
+ pages = "221--236",
+ year = "2001",
+ URL = "http://gallium.inria.fr/~fpottier/publis/conchon-fpottier-esop01.ps.gz",
+}
+
+@TechReport{considine-00,
+ author = "Jeffrey Considine",
+ title = "Efficient Hash-Consing of Recursive Types",
+ institution = "Boston University",
+ year = "2000",
+ number = "2000-006",
+ URL = "http://www.cs.bu.edu/techreports/pdf/2000-006-hashconsing-recursive-types.pdf",
+}
+
+@InProceedings{cook-09,
+ author = "William R. Cook",
+ title = "On understanding data abstraction, revisited",
+ booktitle = oopsla,
+ year = "2009",
+ pages = "557--572",
+ URL = "http://www.cs.utexas.edu/~wcook/Drafts/2009/essay.pdf",
+}
+
+@InProceedings{cook-71,
+ author = "Stephen A. Cook",
+ title = "The Complexity of Theorem-Proving Procedures",
+ booktitle = stoc,
+ year = "1971",
+ pages = "151--158",
+ URL = "http://doi.acm.org/10.1145/800157.805047",
+}
+
+@InProceedings{cook-tractable-11,
+ author = "Byron Cook and Christoph Haase and Jo{\"{e}}l Ouaknine
+ and Matthew J. Parkinson and James Worrell",
+ title = "Tractable Reasoning in a Fragment of Separation
+ Logic",
+ booktitle = concur,
+ pages = "235--249",
+ year = "2011",
+ series = lncs,
+ volume = "6901",
+ publisher = springer,
+ URL = "http://www.cs.ox.ac.uk/files/4048/sl.pdf",
+}
+
+@TechReport{cooper-harvey-kennedy-04,
+ author = "Keith D. Cooper and Timothy J. Harvey and Ken
+ Kennedy",
+ title = "Iterative Data-flow Analysis, Revisited",
+ institution = "Rice University",
+ year = "2004",
+ number = "TR04-432",
+ URL = "http://www.cs.rice.edu/~harv/my_papers/worklist.pdf",
+}
+
+@Article{coppo-dezani-80,
+ author = "Mario Coppo and Mariangiola Dezani-Ciancaglini",
+ title = "An extension of the basic functionality theory for the
+ $\lambda$-calculus",
+ journal = "Notre Dame J. Formal Logic",
+ year = "1980",
+ volume = "21",
+ number = "4",
+ pages = "685--693",
+}
+
+@Manual{coq,
+ author = "{The {Coq} development team}",
+ title = "The {Coq} Proof Assistant",
+ year = "2016",
+ URL = "http://coq.inria.fr/",
+}
+
+@Book{coqart,
+ author = "Yves Bertot and Pierre Cast{\'{e}}ran",
+ title = "Interactive Theorem Proving and Program Development --
+ {Coq'Art}: The Calculus of Inductive Constructions",
+ series = "Texts in Theoretical Computer Science. An {EATCS}
+ Series",
+ publisher = springer,
+ year = "2004",
+ URL = "https://www.labri.fr/perso/casteran/CoqArt/coqartF.pdf",
+}
+
+@InProceedings{coquand-86,
+ author = "Thierry Coquand",
+ title = "An analysis of {Girard}'s paradox",
+ booktitle = lics,
+ pages = "227--236",
+ year = "1986",
+ URL = "http://hal.inria.fr/docs/00/07/60/23/PDF/RR-0531.pdf",
+}
+
+@Book{cormen-en,
+ author = "Thomas H. Cormen and Charles E. Leiserson and Ronald
+ L. Rivest and Clifford Stein",
+ title = "Introduction to Algorithms (Third Edition)",
+ publisher = "MIT Press",
+ year = "2009",
+ URL = "http://mitpress.mit.edu/catalog/item/
+ default.asp?ttype=2&tid=11866",
+}
+
+@Book{cormen-fr,
+ author = "Thomas H. Cormen and Charles E. Leiserson and Ronald
+ L. Rivest and Clifford Stein",
+ title = "Algorithmique (Troisième Édition)",
+ publisher = "Dunod",
+ year = "2010",
+ series = "Sciences Sup",
+ URL = "http://www.dunod.com/informatique-multimedia/fondements-de-linformatique/algorithmique/algorithmique",
+ note = "Traduction française",
+}
+
+@Article{courcelle-fundamental-trees,
+ title = "Fundamental Properties of Infinite Trees",
+ author = "Bruno Courcelle",
+ pages = "95--169",
+ journal = tcs,
+ year = "1983",
+ volume = "25",
+ number = "2",
+}
+
+@InCollection{cousot-90,
+ author = "Patrick Cousot",
+ title = "Methods and Logics for Proving Programs",
+ booktitle = "Formal Models and Semantics",
+ series = "Handbook of Theoretical Computer Science",
+ publisher = elsevier,
+ year = "1990",
+ pages = "841--993",
+ volume = "B",
+ chapter = "15",
+ URL = "http://www.di.ens.fr/~cousot/publications.www/Cousot-HTCS-vB-FMS-c15-p843--993-1990.pdf.gz",
+}
+
+@InProceedings{cousot-cousot-77,
+ author = "Patrick Cousot and Radhia Cousot",
+ title = "Abstract interpretation: a unified lattice model for
+ static analysis of programs by construction or
+ approximation of fixpoints",
+ pages = "238--252",
+ booktitle = popl,
+ year = "1977",
+ URL = "http://www.di.ens.fr/~cousot/publications.www/CousotCousot-POPL-77-ACM-p238--252-1977.pdf",
+}
+
+@Article{cousot-cousot-constructive-79,
+ author = "Patrick Cousot and Radhia Cousot",
+ title = "Constructive Versions of {Tarski}'s Fixed Point
+ Theorems",
+ journal = "Pacific Journal of Mathematics",
+ volume = "81",
+ number = "1",
+ pages = "43--57",
+ year = "1979",
+ URL = "http://www.di.ens.fr/~cousot/publications.www/CousotCousot-PacJMath-82-1-1979.pdf",
+}
+
+@InProceedings{cousot-gentle-09,
+ author = "Patrick Cousot and Radhia Cousot",
+ title = "A gentle introduction to formal verification of
+ computer systems by abstract interpretation",
+ booktitle = "Logics and Languages for Reliability and Security",
+ series = "{NATO} Science Series {III}: Computer and Systems
+ Sciences",
+ editor = "J.~Esparza and O.~Grumberg and M.~Broy",
+ publisher = "IOS Press",
+ year = "2010",
+ pages = "1--29",
+ URL = "http://www.di.ens.fr/~cousot/COUSOTpapers/MARKTOBERDORF-09.shtml",
+}
+
+@InProceedings{cousot-sba-95,
+ author = "Patrick Cousot and Radhia Cousot",
+ title = "Formal Language, Grammar and Set-Constraint-Based
+ Program Analysis by Abstract Interpretation",
+ pages = "170--181",
+ booktitle = fpca,
+ publisher = acmp,
+ year = "1995",
+}
+
+@InProceedings{coutts-07,
+ author = "Duncan Coutts and Roman Leshchinskiy and Don Stewart",
+ title = "Stream fusion: from lists to streams to nothing at
+ all",
+ booktitle = icfp,
+ pages = "315--326",
+ year = "2007",
+ URL = "http://dx.doi.org/10.1145/1291151.1291199",
+}
+
+@InProceedings{crank-felleisen-91,
+ author = "Erik Crank and Matthias Felleisen",
+ title = "Parameter-Passing and the Lambda Calculus",
+ booktitle = popl,
+ pages = "233--244",
+ year = "1991",
+ URL = "http://www.ccs.neu.edu/scheme/pubs/popl91-cf.ps.gz",
+}
+
+@TechReport{crary-99,
+ author = "Karl Crary",
+ title = "Simple, Efficient Object Encoding using Intersection
+ Types",
+ institution = "Carnegie Mellon University",
+ year = "1999",
+ number = "CMU-CS-99-100",
+ URL = "http://www-2.cs.cmu.edu/~crary/papers/1999/orei/orei.ps.gz",
+}
+
+@InProceedings{crary-cc-99,
+ author = "Karl Crary and David Walker and Greg Morrisett",
+ title = "Typed Memory Management in a Calculus of
+ Capabilities",
+ booktitle = popl,
+ pages = "262--275",
+ year = "1999",
+ URL = "http://www.cs.cornell.edu/talc/papers/capabilities.pdf",
+}
+
+@Article{crary-intensional-02,
+ author = "Karl Crary and Stephanie Weirich and Greg Morrisett",
+ title = "Intensional Polymorphism in Type Erasure Semantics",
+ journal = jfp,
+ year = "2002",
+ volume = "12",
+ number = "6",
+ pages = "567--600",
+ URL = "http://www-2.cs.cmu.edu/~crary/papers/2002/typepass/typepass.ps",
+}
+
+@InProceedings{crary-intensional-98,
+ author = "Karl Crary and Stephanie Weirich and Greg Morrisett",
+ title = "Intensional Polymorphism in Type-Erasure Semantics",
+ booktitle = icfp,
+ pages = "301--313",
+ year = "1998",
+ URL = "http://www.cis.upenn.edu/~sweirich/papers/typepass/typepass.ps",
+}
+
+@PhdThesis{crary-phd-98,
+ author = "Karl Crary",
+ title = "Type-Theoretic Methodology for Practical Programming
+ Languages",
+ school = "Cornell University",
+ year = "1998",
+ URL = "http://www.cs.cmu.edu/~crary/papers/1998/thesis/thesis.ps.gz",
+}
+
+@TechReport{crary-standard-09,
+ author = "Karl Crary",
+ title = "A Simple Proof of Call-by-Value Standardization",
+ institution = "Carnegie Mellon University",
+ year = "2009",
+ type = "Technical Report",
+ number = "CMU-CS-09-137",
+ URL = "https://www.cs.cmu.edu/~crary/papers/2009/standard.pdf",
+}
+
+@InProceedings{crary-weirich-00,
+ author = "Karl Crary and Stephanie Weirich",
+ title = "Resource bound certification",
+ booktitle = popl,
+ year = "2000",
+ pages = "184--198",
+ URL = "http://www.cs.cornell.edu/talc/papers/resource_bound/res.pdf",
+}
+
+@InProceedings{crary-weirich-99,
+ author = "Karl Crary and Stephanie Weirich",
+ title = "Flexible Type Analysis",
+ booktitle = icfp,
+ pages = "233--248",
+ year = "1999",
+ URL = "http://www-2.cs.cmu.edu/~crary/papers/1999/lx/lx.ps.gz",
+}
+
+@PhdThesis{cretin-14,
+ author = "Julien Cretin",
+ title = "Erasable coercions: a unified approach to type
+ systems",
+ school = "Université Paris Diderot",
+ year = "2014",
+ URL = "http://tel.archives-ouvertes.fr/tel-00940511",
+}
+
+@InProceedings{cretin-remy-12,
+ author = "Julien Cretin and Didier R{\'e}my",
+ title = "On the power of coercion abstraction",
+ booktitle = popl,
+ year = "2012",
+ pages = "361--372",
+ URL = "http://gallium.inria.fr/~remy/coercions/Cretin-Remy:coercions@popl2012.pdf",
+}
+
+@PhdThesis{curtis-90,
+ author = "Pavel Curtis",
+ title = "Constrained Quantification in Polymorphic Type
+ Analysis",
+ school = "Cornell University",
+ year = "1990",
+ URL = "http://www.parc.xerox.com/company/history/publications/bw-ps-gz/csl90-1.ps.gz",
+}
+
+@InProceedings{cyclone-regions-02,
+ author = "Dan Grossman and Greg Morrisett and Trevor Jim and
+ Michael Hicks and Yanling Wang and James Cheney",
+ title = "Region-Based Memory Management in {Cyclone}",
+ booktitle = pldi,
+ pages = "282--293",
+ year = "2002",
+ URL = "http://www.cs.cornell.edu/projects/cyclone/papers/cyclone-regions.pdf",
+}
+
+@InProceedings{dafny,
+ author = "K. Rustan M. Leino",
+ title = "{Dafny}: An Automatic Program Verifier for Functional
+ Correctness",
+ booktitle = lpar,
+ pages = "348--370",
+ year = "2010",
+ volume = "6355",
+ series = lncs,
+ publisher = springer,
+ URL = "http://research.microsoft.com/en-us/um/people/leino/papers/krml203.pdf",
+}
+
+@PhdThesis{damas-85,
+ author = "Luis Damas",
+ title = "Type Assignment in Programming Languages",
+ school = "University of Edinburgh",
+ year = "1985",
+}
+
+@InProceedings{damas-milner-82,
+ author = "Luis Damas and Robin Milner",
+ title = "Principal type-schemes for functional programs",
+ booktitle = popl,
+ year = "1982",
+ pages = "207--212",
+ URL = "http://doi.acm.org/10.1145/582153.582176",
+}
+
+@InProceedings{damm-josko-83,
+ author = "Werner Damm and Bernhard Josko",
+ title = "A Sound and Relatively$^*$ Complete Axiomatization of
+ {Clarke's} Language {L4}",
+ booktitle = "Logic of Programs",
+ pages = "161--175",
+ year = "1983",
+ volume = "164",
+ series = lncs,
+ publisher = springer,
+ URL = "http://dx.doi.org/10.1007/3-540-12896-4_362",
+}
+
+@InProceedings{danielsson-06,
+ author = "Nils Anders Danielsson and John Hughes and Patrik
+ Jansson and Jeremy Gibbons",
+ title = "Fast and loose reasoning is morally correct",
+ booktitle = popl,
+ year = "2006",
+ pages = "206--217",
+ URL = "http://web.comlab.ox.ac.uk/oucl/work/jeremy.gibbons/publications/fast+loose.pdf",
+}
+
+@InProceedings{danielsson-08,
+ author = "Nils Anders Danielsson",
+ title = "Lightweight Semiformal Time Complexity Analysis for
+ Purely Functional Data Structures",
+ booktitle = popl,
+ year = "2008",
+ URL = "http://www.cse.chalmers.se/~nad/publications/danielsson-popl2008.pdf",
+}
+
+@InProceedings{danielsson-altenkirch-10,
+ author = "Nils Anders Danielsson and Thorsten Altenkirch",
+ title = "Subtyping, Declaratively",
+ booktitle = mpc,
+ year = "2010",
+ pages = "100--118",
+ publisher = springer,
+ series = lncs,
+ volume = "6120",
+ URL = "http://www.cse.chalmers.se/~nad/publications/danielsson-altenkirch-subtyping.pdf",
+}
+
+@InProceedings{danner-13,
+ author = "Norman Danner and Jennifer Paykin and James S. Royer",
+ title = "A static cost analysis for a higher-order language",
+ booktitle = plpv,
+ pages = "25--34",
+ year = "2013",
+ URL = "http://cis.upenn.edu/~jpaykin/papers/danner_PLPV_2013.pdf",
+}
+
+@TechReport{danvy-98,
+ author = "Olivier Danvy",
+ title = "Functional Unparsing",
+ institution = "BRICS",
+ year = "1998",
+ number = "RS-98-12",
+ URL = "http://www.brics.dk/RS/98/12/",
+}
+
+@TechReport{danvy-nielsen-01,
+ author = "Olivier Danvy and Lasse R. Nielsen",
+ title = "Defunctionalization at Work",
+ year = "2001",
+ institution = "BRICS",
+ number = "RS-01-23",
+ URL = "http://www.brics.dk/RS/01/23/",
+}
+
+@Article{danvy-nielsen-03,
+ author = "Olivier Danvy and Lasse R. Nielsen",
+ title = "A first-order one-pass {CPS} transformation",
+ journal = tcs,
+ volume = "308",
+ number = "1--3",
+ pages = "239--257",
+ year = "2003",
+ URL = "http://dx.doi.org/10.1016/S0304-3975(02)00733-8",
+}
+
+@InProceedings{danvy-nielsen-ppdp-01,
+ author = "Olivier Danvy and Lasse R. Nielsen",
+ title = "Defunctionalization at Work",
+ pages = "162--174",
+ booktitle = ppdp,
+ year = "2001",
+ URL = "http://doi.acm.org/10.1145/773184.773202",
+}
+
+@Article{danvy-pearl-98,
+ author = "Olivier Danvy",
+ title = "Functional Unparsing",
+ journal = jfp,
+ year = "1998",
+ volume = "8",
+ number = "6",
+ pages = "621--625",
+ URL = "http://dx.doi.org/10.1017/S0956796898003104",
+}
+
+@PhdThesis{dao-00,
+ author = "Thi Bich Hanh Dao",
+ title = "{R}ésolution de contraintes du premier ordre dans la
+ théorie des arbres finis ou infinis",
+ school = "Université de la Méditerranée",
+ year = "2000",
+ URL = "http://www.univ-orleans.fr/SCIENCES/LIFO/Members/dao/papers/ts4dec.ps.gz",
+}
+
+@InProceedings{dargaye-leroy-cps-07,
+ author = "Zaynah Dargaye and Xavier Leroy",
+ title = "Mechanized verification of {CPS} transformations",
+ booktitle = lpar,
+ year = "2007",
+ series = lnai,
+ volume = "4790",
+ publisher = springer,
+ pages = "211--225",
+ URL = "http://gallium.inria.fr/~xleroy/publi/cps-dargaye-leroy.pdf",
+}
+
+@TechReport{davies-05,
+ author = "Rowan Davies",
+ title = "Practical Refinement-Type Checking",
+ institution = "School of Computer Science, Carnegie Mellon
+ University",
+ year = "2005",
+ number = "CMU-CS-05-110",
+ URL = "http://reports-archive.adm.cs.cmu.edu/anon/2005/CMU-CS-05-110.pdf",
+}
+
+@InProceedings{davies-pfenning-00,
+ author = "Rowan Davies and Frank Pfenning",
+ title = "Intersection types and computational effects",
+ booktitle = icfp,
+ year = "2000",
+ pages = "198--208",
+ URL = "http://www.cs.cmu.edu/~fp/papers/icfp00.pdf",
+}
+
+@Article{davis-logemann-loveland-62,
+ author = "Martin Davis and George Logemann and Donald Loveland",
+ title = "A machine program for theorem-proving",
+ journal = cacm,
+ volume = "5",
+ number = "7",
+ year = "1962",
+ pages = "394--397",
+ URL = "http://doi.acm.org/10.1145/368273.368557",
+}
+
+@Article{davis-putnam-60,
+ author = "Martin Davis and Hilary Putnam",
+ title = "A Computing Procedure for Quantification Theory",
+ journal = jacm,
+ volume = "7",
+ number = "3",
+ year = "1960",
+ pages = "201--215",
+ URL = "http://doi.acm.org/10.1145/321033.321034",
+}
+
+@Article{de-bruijn-72,
+ author = "Nicolaas G. de Bruijn",
+ title = "Lambda-Calculus Notation with Nameless Dummies: a Tool
+ for Automatic Formula Manipulation with Application to
+ the {Church-Rosser} Theorem",
+ journal = "Indag. Math.",
+ volume = "34",
+ number = "5",
+ year = "1972",
+ pages = "381--392",
+}
+
+@InProceedings{delaware-3mt-13,
+ author = "Benjamin Delaware and Steven Keuchel and Tom
+ Schrijvers and Bruno C. d. S. Oliveira",
+ title = "Modular monadic meta-theory",
+ booktitle = icfp,
+ year = "2013",
+ pages = "319--330",
+ URL = "http://ropas.snu.ac.kr/~bruno/papers/3MT.pdf",
+}
+
+@InProceedings{delaware-mtc-13,
+ author = "Benjamin Delaware and Bruno C. d. S. Oliveira and Tom
+ Schrijvers",
+ title = "Meta-theory à La Carte",
+ booktitle = popl,
+ year = "2013",
+ pages = "207--218",
+ URL = "http://people.csail.mit.edu/bendy/MTC/MTC.pdf",
+}
+
+@InProceedings{delbianco-nanevski-13,
+ author = "Germ{\'{a}}n Andr{\'{e}}s Delbianco and Aleksandar
+ Nanevski",
+ title = "{Hoare}-style reasoning with (algebraic)
+ continuations",
+ booktitle = icfp,
+ pages = "363--376",
+ year = "2013",
+ URL = "http://software.imdea.org/~aleks/papers/callcc/icfp2013.pdf",
+}
+
+@InProceedings{deline-faehndrich-01,
+ author = "Robert DeLine and Manuel Fähndrich",
+ title = "Enforcing High-Level Protocols in Low-Level Software",
+ booktitle = pldi,
+ pages = "59--69",
+ year = "2001",
+ URL = "http://research.microsoft.com/apps/pubs/default.aspx?id=67457",
+}
+
+@InProceedings{deline-faehndrich-04,
+ author = "Robert DeLine and Manuel Fähndrich",
+ title = "Typestates for objects",
+ booktitle = ecoop,
+ pages = "465--490",
+ year = "2004",
+ volume = "3086",
+ series = lncs,
+ publisher = springer,
+ URL = "http://research.microsoft.com/apps/pubs/default.aspx?id=67463",
+}
+
+@TechReport{deline-faehndrich-fugue-04,
+ author = "Robert DeLine and Manuel Fähndrich",
+ title = "The {Fugue} Protocol Checker: Is Your Software
+ Baroque?",
+ institution = "Microsoft Research",
+ year = "2004",
+ number = "MSR-TR-2004-07",
+ URL = "http://research.microsoft.com/apps/pubs/default.aspx?id=67458",
+}
+
+@InProceedings{delphin-08,
+ author = "Adam Poswolsky and Carsten Schürmann",
+ title = "Practical Programming with Higher-Order Encodings and
+ Dependent Types",
+ booktitle = esop,
+ pages = "93--107",
+ year = "2008",
+ volume = "4960",
+ series = lncs,
+ publisher = springer,
+ URL = "http://cs-www.cs.yale.edu/homes/delphin/files/delphinESOP08.pdf",
+}
+
+@Article{delphin-09,
+ author = "Adam Poswolsky and Carsten Schürmann",
+ title = "System Description: {Delphin} -- {A} Functional
+ Programming Language for Deductive Systems",
+ journal = entcs,
+ volume = "228",
+ year = "2009",
+ pages = "113--120",
+ URL = "http://www.itu.dk/~carsten/papers/lfmtp-08.pdf",
+}
+
+@Article{dencker-84,
+ author = "Peter Dencker and Karl Dürre and Johannes Heuft",
+ title = "Optimization of parser tables for portable compilers",
+ journal = toplas,
+ volume = "6",
+ number = "4",
+ year = "1984",
+ pages = "546--572",
+ URL = "http://doi.acm.org/10.1145/1780.1802",
+}
+
+@Article{denning-77,
+ author = "Dorothy E. Denning and Peter J. Denning",
+ title = "Certification of Programs for Secure Information
+ Flow",
+ journal = cacm,
+ volume = "20",
+ number = "7",
+ pages = "504--513",
+ year = "1977",
+}
+
+@Book{denning-82,
+ author = "Dorothy E. Denning",
+ title = "Cryptography and Data Security",
+ publisher = aw,
+ year = "1982",
+}
+
+@InProceedings{dennis-sat-06,
+ author = "Greg Dennis and Felix Change and Daniel Jackson",
+ title = "Modular Verification of Code with {SAT}",
+ booktitle = issta,
+ year = "2006",
+ URL = "http://sdg.csail.mit.edu/pubs/2006/dennis_modular.pdf",
+}
+
+@Article{denny-malloy-10,
+ author = "Joel E. Denny and Brian A. Malloy",
+ title = "The {IELR(1)} algorithm for generating minimal {LR(1)}
+ parser tables for non-{LR(1)} grammars with conflict
+ resolution",
+ journal = scp,
+ volume = "75",
+ number = "11",
+ pages = "943--979",
+ year = "2010",
+ URL = "http://dx.doi.org/10.1016/j.scico.2009.08.001",
+}
+
+@Article{deremer-pennello-82,
+ author = "Frank DeRemer and Thomas Pennello",
+ title = "Efficient Computation of ${LALR}(1)$ Look-Ahead Sets",
+ journal = toplas,
+ volume = "4",
+ number = "4",
+ year = "1982",
+ pages = "615--649",
+ URL = "http://doi.acm.org/10.1145/69622.357187",
+}
+
+@TechReport{deremer-phd-69,
+ author = "Franklin Lewis DeRemer",
+ title = "Practical Translators for {LR(k)} Languages",
+ institution = "Massachusetts Institute of Technology",
+ year = "1969",
+ type = "Technical Report",
+ number = "MIT-LCS-TR-065",
+ URL = "http://publications.csail.mit.edu/lcs/pubs/pdf/MIT-LCS-TR-065.pdf",
+}
+
+@Article{deremer-slr-71,
+ author = "Franklin L. DeRemer",
+ title = "Simple ${LR}(k)$ grammars",
+ journal = cacm,
+ year = "1971",
+ volume = "14",
+ number = "7",
+ pages = "453--460",
+ URL = "http://dx.doi.org/10.1145/362619.362625",
+}
+
+@Book{design-patterns,
+ author = "Erich Gamma and Richard Helm and Ralph Johnson and
+ John Vlissides",
+ title = "Design Patterns: Elements of Reusable Object-oriented
+ Software",
+ year = "1995",
+ publisher = aw,
+}
+
+@TechReport{detlefs-98,
+ author = "David L. Detlefs and K. Rustan M. Leino and Greg
+ Nelson and James B. Saxe",
+ title = "Extended static checking",
+ institution = "Compaq SRC",
+ year = "1998",
+ type = "Research Report",
+ number = "159",
+ URL = "ftp://gatekeeper.research.compaq.com/pub/DEC/SRC/research-reports/SRC-159.pdf",
+}
+
+@TechReport{detlefs-wrestling-98,
+ author = "David L. Detlefs and K. Rustan M. Leino and Greg
+ Nelson",
+ title = "Wrestling with rep exposure",
+ institution = "SRC",
+ year = "1998",
+ type = "Research Report",
+ number = "156",
+ URL = "http://www.hpl.hp.com/techreports/Compaq-DEC/SRC-RR-156.pdf",
+}
+
+@Book{dicosmo-95,
+ author = "Roberto {Di Cosmo}",
+ title = "Isomorphisms of types: from $\lambda$-calculus to
+ information retrieval and language design",
+ series = "Progress in Theoretical Computer Science",
+ publisher = "Birkhauser",
+ year = "1995",
+ URL = "http://www.pps.jussieu.fr/~dicosmo/Publications/ISObook.html",
+}
+
+@Article{dicosmo-jfp-93,
+ author = "Roberto {Di Cosmo}",
+ title = "Deciding Type isomorphisms in a type assignment
+ framework",
+ journal = jfp,
+ year = "1993",
+ volume = "3",
+ number = "3",
+ pages = "485--525",
+ URL = "http://www.dicosmo.org/Articles/JFP94.dvi",
+}
+
+@Article{dietl-drossopoulou-mueller-11,
+ author = "Werner Dietl and Sophia Drossopoulou and Peter
+ M{\"u}ller",
+ title = "Separating ownership topology and encapsulation with
+ generic universe types",
+ journal = toplas,
+ volume = "33",
+ number = "6",
+ year = "2011",
+ pages = "20",
+ URL = "http://pm.inf.ethz.ch/publications/getpdf.php?bibname=Own&id=DietlDrossopoulouMueller11.pdf",
+}
+
+@Article{dietl-mueller-05,
+ author = "Werner Dietl and Peter M{\"u}ller",
+ title = "Universes: Lightweight Ownership for {JML}",
+ journal = jot,
+ year = "2005",
+ volume = "4",
+ number = "8",
+ pages = "5--32",
+ URL = "http://www.jot.fm/issues/issue_2005_10/article1.pdf",
+}
+
+@Article{dijkstra-59,
+ author = "E. W. Dijkstra",
+ title = "A Note on Two Problems in Connection with Graphs",
+ journal = "Numerische Mathematik",
+ year = "1959",
+ volume = "1",
+ pages = "269--271",
+}
+
+@Article{dijkstra-75,
+ author = "Edsger W. Dijkstra",
+ title = "Guarded commands, nondeterminacy and formal derivation
+ of programs",
+ journal = "Communications of the ACM",
+ volume = "18",
+ number = "8",
+ year = "1975",
+ pages = "453--457",
+ URL = "http://doi.acm.org/10.1145/360933.360975",
+}
+
+@PhdThesis{dimock-02,
+ author = "Allyn Dimock",
+ title = "Type- and Flow-Directed Compilation for Specialized
+ Data Representations",
+ school = "Harvard University",
+ year = "2002",
+ URL = "http://www.cs.uml.edu/~dimock/thesis.ps.gz",
+}
+
+@InProceedings{dimock-al-01,
+ author = "Allyn Dimock and Ian Westmacott and Robert Muller and
+ Franklyn Turbak and J. B. Wells",
+ title = "Functioning without closure: type-safe customized
+ function representations for {Standard ML}",
+ booktitle = icfp,
+ year = "2001",
+ URL = "http://puma.wellesley.edu/~fturbak/pubs/icfp01.ps",
+}
+
+@InProceedings{dinsdale-young-views-13,
+ author = "Thomas Dinsdale-Young and Lars Birkedal and Philippa
+ Gardner and Matthew J. Parkinson and Hongseok Yang",
+ title = "Views: compositional reasoning for concurrent
+ programs",
+ booktitle = popl,
+ year = "2013",
+ pages = "287--300",
+ URL = "http://cs.au.dk/~birke/papers/views.pdf",
+}
+
+@InProceedings{dinsdaleyoung-cap-10,
+ author = "Thomas Dinsdale-Young and Mike Dodds and Philippa
+ Gardner and Matthew J. Parkinson and Viktor Vafeiadis",
+ booktitle = ecoop,
+ publisher = springer,
+ title = "Concurrent Abstract Predicates",
+ series = lncs,
+ volume = "6183",
+ year = "2010",
+ pages = "504--528",
+ URL = "http://www.cl.cam.ac.uk/~md466/publications/ECOOP.10.concurrent_abstract_predicates.pdf",
+}
+
+@TechReport{dinsdaleyoung-cap-tr-10,
+ author = "Thomas Dinsdale-Young and Mike Dodds and Philippa
+ Gardner and Matthew Parkinson and Viktor Vafeiadis",
+ title = "Concurrent Abstract Predicates",
+ institution = "University of Cambridge, Computer Laboratory",
+ year = "2010",
+ URL = "http://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-777.pdf",
+}
+
+@InProceedings{distefano-parkinson-08,
+ author = "Dino Distefano and Matthew J. Parkinson",
+ title = "{jStar}: towards practical verification for {Java}",
+ booktitle = oopsla,
+ year = "2008",
+ pages = "213--226",
+ URL = "http://www.eecs.qmul.ac.uk/~ddino/papers/oopsla2008.pdf",
+}
+
+@InProceedings{dockins-algebras-09,
+ author = "Robert Dockins and Aquinas Hobor and Andrew W. Appel",
+ title = "A Fresh Look at Separation Algebras and Share
+ Accounting",
+ booktitle = aplas,
+ year = "2009",
+ pages = "161--177",
+ publisher = springer,
+ series = lncs,
+ volume = "5904",
+ URL = "http://www.cs.princeton.edu/~appel/papers/fresh-sa.pdf",
+}
+
+@InProceedings{dodds-11,
+ author = "Mike Dodds and Suresh Jagannathan and Matthew J.
+ Parkinson",
+ title = "Modular reasoning for deterministic parallelism",
+ booktitle = popl,
+ year = "2011",
+ pages = "259--270",
+ URL = "http://www.cl.cam.ac.uk/~md466/publications/POPL.11.deterministic_parallelism.pdf",
+}
+
+@InProceedings{dodds-deny-guarantee-09,
+ author = "Mike Dodds and Xinyu Feng and Matthew J. Parkinson and
+ Viktor Vafeiadis",
+ title = "Deny-Guarantee Reasoning",
+ booktitle = esop,
+ year = "2009",
+ pages = "363--377",
+ publisher = springer,
+ series = lncs,
+ volume = "5502",
+ URL = "http://ttic.uchicago.edu/~feng/research/publications/DG.pdf",
+}
+
+@Article{dodds-sync-16,
+ author = "Mike Dodds and Suresh Jagannathan and Matthew J.
+ Parkinson and Kasper Svendsen and Lars Birkedal",
+ title = "Verifying custom synchronization constructs using
+ higher-order separation logic",
+ journal = toplas,
+ year = "2016",
+ volume = "28",
+ number = "2",
+ URL = "http://dx.doi.org/10.1145/2818638",
+}
+
+@InProceedings{donnelly-xi-05,
+ author = "Kevin Donnelly and Hongwei Xi",
+ title = "Combining higher-order abstract syntax with
+ first-order abstract syntax in {ATS}",
+ booktitle = merlin,
+ year = "2005",
+ pages = "58--63",
+ URL = "http://www.cs.bu.edu/~hwxi/academic/papers/merlin05.pdf",
+}
+
+@Article{dornic-jouvelot-gifford-92,
+ author = "Vincent Dornic and Pierre Jouvelot and David K.
+ Gifford",
+ title = "Polymorphic time systems for estimating program
+ complexity",
+ journal = loplas,
+ volume = "1",
+ number = "1",
+ year = "1992",
+ pages = "33--45",
+ URL = "http://ropas.snu.ac.kr/lib/dock/DoJoGi1992.pdf",
+}
+
+@InCollection{dowek-01,
+ author = "Gilles Dowek",
+ title = "Higher-order unification and matching",
+ booktitle = "Handbook of Automated Reasoning",
+ pages = "1009--1062",
+ publisher = elsevier,
+ year = "2001",
+ editor = "J. Alan Robinson and Andrei Voronkov",
+ URL = "http://www.lix.polytechnique.fr/~dowek/Publi/unification.ps",
+}
+
+@TechReport{dowek-al-95,
+ author = "Gilles Dowek and Thérèse Hardin and Claude
+ Kirchner",
+ title = "Higher Order Unification via Explicit Substitutions",
+ institution = "INRIA",
+ number = "2709",
+ year = "1995",
+ pages = "42",
+ type = "Research Report",
+ URL = "http://www.inria.fr/rrrt/rr-2709.html",
+}
+
+@TechReport{dowek-al-98,
+ author = "Gilles Dowek and Thérèse Hardin and Claude Kirchner
+ and Frank Pfenning",
+ title = "Unification via Explicit Substitutions: the Case of
+ Higher-Order Patterns",
+ institution = "INRIA",
+ number = "3591",
+ year = "1998",
+ pages = "33",
+ type = "Research Report",
+ URL = "http://www.inria.fr/rrrt/rr-3591.html",
+}
+
+@Article{dowling-gallier-84,
+ author = "William F. Dowling and Jean H. Gallier",
+ title = "Linear-Time Algorithms for Testing the Satisfiability
+ of Propositional {Horn} Formulae",
+ journal = jlp,
+ volume = "1",
+ number = "3",
+ year = "1984",
+ pages = "267--284",
+}
+
+@Article{downey-sethi-tarjan-80,
+ author = "Peter J. Downey and Ravi Sethi and Robert Endre
+ Tarjan",
+ title = "Variations on the Common Subexpression Problem",
+ journal = jacm,
+ year = "1980",
+ volume = "27",
+ number = "4",
+ pages = "758--771",
+ URL = "http://doi.acm.org/10.1145/322217.322228",
+}
+
+@InProceedings{dreyer-neis-birkedal-10,
+ author = "Derek Dreyer and Georg Neis and Lars Birkedal",
+ title = "The impact of higher-order state and control effects
+ on local relational reasoning",
+ booktitle = icfp,
+ pages = "143--156",
+ year = "2010",
+ URL = "https://www.mpi-sws.org/~dreyer/papers/stslr/icfp.pdf",
+}
+
+@InProceedings{dubois-menissier-97,
+ author = "Catherine Dubois and Valérie Ménissier-Morain",
+ title = "Typage de {ML}: Spécification et preuve en {Coq}",
+ booktitle = "Actes du GDR Programmation",
+ year = "1997",
+ URL = "http://www.irisa.fr/lande/ridoux/GDR_annexe/dubois.ps.gz",
+}
+
+@Article{dubois-menissier-99,
+ author = "Catherine Dubois and Valérie Ménissier-Morain",
+ title = "Certification of a Type Inference Tool for {ML}:
+ {Damas-Milner} within {Coq}",
+ journal = jar,
+ year = "1999",
+ volume = "23",
+ number = "3--4",
+ pages = "319--346",
+ URL = "http://www.ensiie.fr/~dubois/jar_final.pdf",
+}
+
+@Article{duggan-bent-96,
+ author = "Dominic Duggan and Frederick Bent",
+ title = "Explaining type inference",
+ journal = scp,
+ year = "1996",
+ volume = "27",
+ number = "1",
+}
+
+@InProceedings{dussart-henglein-mossin-95,
+ author = "Dirk Dussart and Fritz Henglein and Christian Mossin",
+ year = "1995",
+ title = "Polymorphic Recursion and Subtype Qualifications:
+ Polymorphic Binding-Time Analysis in Polynomial Time",
+ booktitle = sas,
+ publisher = springer,
+ series = lncs,
+ volume = "983",
+ pages = "118--135",
+ URL = "ftp://ftp.diku.dk/diku/semantics/papers/D-243.dvi.gz",
+}
+
+@Article{dybvig-93,
+ author = "Kent Dybvig and Robert Hieb and Carl Bruggeman",
+ title = "Syntactic abstraction in {Scheme}",
+ journal = lsc,
+ year = "1993",
+ volume = "5",
+ number = "4",
+ pages = "295--326",
+ URL = "http://www.cs.indiana.edu/~dyb/pubs/LaSC-5-4-pp295-326.pdf",
+}
+
+@Article{eberl-17,
+ author = "Manuel Eberl",
+ title = "Proving Divide and Conquer Complexities in
+ {Isabelle/HOL}",
+ journal = jar,
+ volume = "58",
+ number = "4",
+ pages = "483--508",
+ year = "2017",
+ URL = "https://www21.in.tum.de/~eberlm/divide_and_conquer_isabelle.pdf",
+}
+
+@InProceedings{eifrig-smith-trifonov-94,
+ author = "Jonathan Eifrig and Scott Smith and Valery Trifonov",
+ title = "Type Inference for Recursively Constrained Types and
+ its Application to {OOP}",
+ booktitle = mfps,
+ series = entcs,
+ publisher = elsevier,
+ volume = "1",
+ year = "1995",
+ URL = "http://www.cs.jhu.edu/~scott/ftp/ooinfer.ps.gz",
+}
+
+@Article{eifrig-smith-trifonov-95,
+ author = "Jonathan Eifrig and Scott Smith and Valery Trifonov",
+ title = "Sound polymorphic type inference for objects",
+ journal = notices,
+ volume = "30",
+ number = "10",
+ year = "1995",
+ pages = "169--184",
+ URL = "http://www.cs.jhu.edu/~scott/ftp/sptio.ps.gz",
+}
+
+@TechReport{elphin-04,
+ author = "Carsten Schürmann and Adam Poswolsky and Jeffrey
+ Sarnat",
+ title = "The $\nabla$-Calculus: Functional programming with
+ higher-order encodings",
+ institution = "Yale University",
+ number = "YALEU/DCS/TR-1272",
+ year = "2004",
+ URL = "http://www.cs.yale.edu/~delphin/files/nablaTR.pdf",
+}
+
+@InProceedings{elphin-05,
+ author = "Carsten Schürmann and Adam Poswolsky and Jeffrey
+ Sarnat",
+ title = "The $\nabla$-Calculus: Functional programming with
+ higher-order encodings",
+ booktitle = tlca,
+ pages = "339--353",
+ year = "2005",
+ volume = "3461",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.itu.dk/~carsten/papers/nabla.pdf",
+}
+
+@InProceedings{emerson-lei-86,
+ author = "E. Allen Emerson and Chin-Laung Lei",
+ title = "Efficient Model Checking in Fragments of the
+ Propositional Mu-Calculus",
+ booktitle = lics,
+ year = "1986",
+ pages = "267--278",
+}
+
+@TechReport{emms-leiss-96,
+ author = "Martin Emms and Hans Lei{\ss}",
+ title = "Extending the Type Checker for {SML} by Polymorphic
+ Recursion --- {A} Correctness Proof",
+ institution = "Centrum f{\"{u}}r Informations- und
+ Sprachverarbeitung, Universit{\"{a}}t M{\"{u}}nchen",
+ year = "1996",
+ number = "96-101",
+ URL = "http://www.cis.uni-muenchen.de/~leiss/polyrec/polyrec.cisbericht.96-101.ps.gz",
+}
+
+@Book{eopl,
+ author = "Daniel P. Friedman and Mitchell Wand",
+ title = "Essentials of Programming Languages, 3rd Edition",
+ publisher = mitp,
+ year = "2008",
+ URL = "http://www.eopl3.com/",
+}
+
+@Unpublished{epigram-05,
+ author = "Thorsten Altenkirch and Conor McBride and James
+ McKinna",
+ title = "Why Dependent Types Matter",
+ note = "Unpublished",
+ year = "2005",
+ URL = "http://www.e-pig.org/downloads/ydtm.pdf",
+}
+
+@Misc{ergo,
+ author = "Sylvain Conchon and Evelyne Contejean",
+ title = "The {Alt-Ergo} Automatic Theorem Prover",
+ note = "\url{http://alt-ergo.lri.fr/}",
+ year = "2011",
+ URL = "http://alt-ergo.lri.fr/",
+}
+
+@InProceedings{erlingsson-schneider-00,
+ author = "{\'U}lfar Erlingsson and Fred B. Schneider",
+ title = "{IRM} Enforcement of {Java} Stack Inspection",
+ booktitle = sp,
+ year = "2000",
+ pages = "246--255",
+ URL = "http://csdl.computer.org/comp/proceedings/sp/2000/0665/00/06650246abs.htm",
+}
+
+@InProceedings{erlingsson-schneider-99,
+ author = "{\'U}lfar Erlingsson and Fred B. Schneider",
+ title = "{SASI} Enforcement of Security Policies: a
+ Retrospective",
+ booktitle = nspw,
+ pages = "87--95",
+ year = "1999",
+ URL = "http://www.cs.cornell.edu/fbs/publications/sasiNSPW.ps",
+}
+
+@InProceedings{esparza-13,
+ author = "Javier Esparza and Peter Lammich and Ren{\'e} Neumann
+ and Tobias Nipkow and Alexander Schimpf and Jan-Georg
+ Smaus",
+ title = "A Fully Verified Executable {LTL} Model Checker",
+ booktitle = cav,
+ pages = "463--478",
+ year = "2013",
+ series = lncs,
+ volume = "8044",
+ publisher = springer,
+ URL = "https://www21.in.tum.de/~nipkow/pubs/cav13.pdf",
+}
+
+@InProceedings{esparza-efficient-00,
+ author = "Javier Esparza and David Hansel and Peter Rossmanith
+ and Stefan Schwoon",
+ title = "Efficient Algorithms for Model Checking Pushdown
+ Systems",
+ booktitle = cav,
+ pages = "232--247",
+ year = "2000",
+ series = lncs,
+ volume = "1855",
+ publisher = springer,
+ URL = "https://www7.in.tum.de/um/bibdb/esparza/cav00.pdf",
+}
+
+@Misc{f7,
+ author = "Karthik Bhargavan and Cédric Fournet and Andy Gordon
+ and Sergio Maffeis and Jesper Bengtson",
+ title = "The {F7} Typechecker",
+ note = "\url{http://research.microsoft.com/en-us/projects/f7/}",
+ year = "2011",
+ URL = "http://research.microsoft.com/en-us/projects/f7/",
+}
+
+@Misc{facebook-infer,
+ author = "Cristiano Calcagno and Dino Distefano and Peter
+ O'Hearn",
+ title = "Open-sourcing {Facebook Infer}: Identify bugs before
+ you ship",
+ howpublished = "\url{https://code.facebook.com/posts/1648953042007882/open-sourcing-facebook-infer-identify-bugs-before-you-ship/}",
+ year = "2015",
+}
+
+@InProceedings{faehndrich-al-00,
+ author = "Manuel Fähndrich and Jakob Rehof and Manuvir Das",
+ title = "Scalable Context-Sensitive Flow Analysis Using
+ Instantiation Constraints",
+ booktitle = pldi,
+ year = "2000",
+ URL = "http://research.microsoft.com/pubs/67468/pldi00.ps",
+}
+
+@InProceedings{faehndrich-cycles-98,
+ author = "Manuel Fähndrich and Jeffrey S. Foster and Zhendong
+ Su and Alexander S. Aiken",
+ title = "Partial Online Cycle Elimination in Inclusion
+ Constraint Graphs",
+ booktitle = pldi,
+ year = "1998",
+ pages = "85--96",
+ URL = "http://research.microsoft.com/pubs/67475/pldi98.pdf",
+}
+
+@InProceedings{faehndrich-deline-02,
+ author = "Manuel Fähndrich and Robert DeLine",
+ title = "Adoption and focus: practical linear types for
+ imperative programming",
+ booktitle = pldi,
+ year = "2002",
+ pages = "13--24",
+ URL = "http://research.microsoft.com/pubs/67459/pldi02.pdf",
+}
+
+@InProceedings{faehndrich-leino-03,
+ author = "Manuel Fähndrich and Rustan Leino",
+ title = "Heap Monotonic Typestates",
+ booktitle = "International Workshop on Alias Confinement and
+ Ownership (IWACO)",
+ year = "2003",
+ URL = "http://research.microsoft.com/en-us/um/people/leino/papers/krml123.pdf",
+}
+
+@PhdThesis{faehndrich-phd-99,
+ school = "University of California at Berkeley",
+ title = "Bane: {A} Library for Scalable Constraint-Based
+ Program Analysis",
+ year = "1999",
+ author = "Manuel Fähndrich",
+ URL = "http://research.microsoft.com/pubs/67479/thesis-compact.pdf",
+}
+
+@InProceedings{faehndrich-singularity-06,
+ author = "Manuel Fähndrich and Mark Aiken and Chris Hawblitzel
+ and Orion Hodson and Galen Hunt and James R. Larus and
+ Steven Levi",
+ title = "Language support for fast and reliable message-based
+ communication in {Singularity OS}",
+ booktitle = eurosys,
+ year = "2006",
+ pages = "177--190",
+ URL = "http://www.cs.kuleuven.ac.be/conference/EuroSys2006/papers/p177-fahndrich.pdf",
+}
+
+@Unpublished{fan,
+ author = "Hongbo Zhang and Steve Zdancewic",
+ title = "{Fan}: compile-time metaprogramming for {OCaml}",
+ note = "Unpublished",
+ year = "2013",
+ URL = "http://zhanghongbo.me/fan/_downloads/metaprogramming_for_ocaml.pdf",
+}
+
+@Article{faxen-02,
+ author = "Karl-Filip Fax\'{e}n",
+ title = "A Static Semantics for {Haskell}",
+ pages = "295--357",
+ year = "2002",
+ journal = jfp,
+ volume = "12",
+ number = "4--5",
+ URL = "http://www.it.kth.se/~kff/semantics.ps.gz",
+}
+
+@Article{fecht-seidl-99,
+ author = "Christian Fecht and Helmut Seidl",
+ title = "A Faster Solver for General Systems of Equations",
+ journal = scp,
+ year = "1999",
+ volume = "35",
+ number = "2--3",
+ pages = "137--162",
+ URL = "http://www2.in.tum.de/~seidl/papers/final-solver.ps.gz",
+}
+
+@InProceedings{felleisen-flanagan-componential-97,
+ author = "Cormac Flanagan and Matthias Felleisen",
+ title = "Componential Set-Based Analysis",
+ booktitle = pldi,
+ year = "1997",
+ pages = "235--248",
+ URL = "http://www.cs.rice.edu/CS/PLT/Publications/Scheme/pldi97-ff.ps.gz",
+}
+
+@TechReport{felleisen-flanagan-theory-practice-96,
+ number = "TR96-266",
+ institution = "Rice University",
+ title = "Modular and Polymorphic Set-Based Analysis: Theory and
+ Practice",
+ year = "1996",
+ pages = "48",
+ author = "Cormac Flanagan and Matthias Felleisen",
+ URL = "http://www.cs.rice.edu/CS/PLT/Publications/Scheme/tr96-266.ps.gz",
+}
+
+@PhdThesis{fenton-73,
+ school = "University of Cambridge",
+ title = "Information Protection Systems",
+ year = "1973",
+ author = "J. S. Fenton",
+}
+
+@Article{fenton-74,
+ author = "J. S. Fenton",
+ title = "Memoryless Subsystems",
+ journal = cj,
+ volume = "17",
+ number = "2",
+ pages = "143--147",
+ year = "1974",
+}
+
+@InProceedings{ferreira-pientka-17,
+ author = "Francisco Ferreira and Brigitte Pientka",
+ title = "Programs Using Syntax with First-Class Binders",
+ booktitle = esop,
+ year = "2017",
+ series = lncs,
+ volume = "10201",
+ publisher = springer,
+ URL = "http://www.cs.mcgill.ca/~bpientka/papers/esop17_ferreira.pdf",
+}
+
+@Article{fftw-05,
+ author = "Matteo Frigo and Steven G. Johnson",
+ title = "The Design and Implementation of {FFTW3}",
+ journal = pieee,
+ year = "2005",
+ volume = "93",
+ number = "2",
+ pages = "216--231",
+ URL = "http://www.fftw.org/fftw-paper-ieee.pdf",
+}
+
+@InProceedings{field-teitelbaum-90,
+ author = "John Field and Tim Teitelbaum",
+ title = "Incremental Reduction in the Lambda Calculus",
+ booktitle = lfp,
+ year = "1990",
+ pages = "307--322",
+}
+
+@InProceedings{filinski-99,
+ author = "Andrzej Filinski",
+ title = "Representing Layered Monads",
+ booktitle = popl,
+ year = "1999",
+ pages = "175--188",
+ URL = "http://www.diku.dk/~andrzej/papers/RLM.ps.gz",
+}
+
+@Article{filliatre-00,
+ author = "Jean-Christophe Filliâtre",
+ title = "Verification of Non-Functional Programs using
+ Interpretations in Type Theory",
+ journal = jfp,
+ volume = "13",
+ number = "4",
+ pages = "709--745",
+ year = "2003",
+ URL = "http://www.lri.fr/~filliatr/ftp/publis/jphd.ps.gz",
+}
+
+@InProceedings{filliatre-06,
+ author = "Jean-Christophe Filli\^atre",
+ title = "Backtracking iterators",
+ booktitle = ml,
+ year = "2006",
+ pages = "55--62",
+ URL = "http://www.lri.fr/~filliatr/publis/enum2.ps.gz",
+}
+
+@InProceedings{filliatre-conchon-06,
+ author = "Jean-Christophe Filli{\^a}tre and Sylvain Conchon",
+ title = "Type-safe modular hash-consing",
+ booktitle = ml,
+ pages = "12--19",
+ year = "2006",
+ URL = "https://www.lri.fr/~filliatr/ftp/publis/hash-consing2.pdf",
+}
+
+@Article{filliatre-find-06,
+ author = "Jean-Christophe Filliâtre",
+ title = "Formal Proof of a Program: {Find}",
+ journal = scp,
+ year = "2006",
+ volume = "64",
+ pages = "332--240",
+ URL = "http://www.lri.fr/~filliatr/ftp/publis/find.ps.gz",
+}
+
+@InProceedings{filliatre-ghost-14,
+ author = "Jean{-}Christophe Filli{\^{a}}tre and L{\'{e}}on
+ Gondelman and Andrei Paskevich",
+ title = "The Spirit of Ghost Code",
+ booktitle = cav,
+ pages = "1--16",
+ year = "2014",
+ series = lncs,
+ volume = "8559",
+ publisher = springer,
+ URL = "https://hal.archives-ouvertes.fr/hal-00873187/PDF/main.pdf",
+}
+
+@InProceedings{filliatre-letouzey-04,
+ author = "Jean-Christophe Filliâtre and Pierre Letouzey",
+ title = "Functors for Proofs and Programs",
+ booktitle = esop,
+ pages = "370--384",
+ year = "2004",
+ volume = "2986",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.lri.fr/~filliatr/ftp/publis/fpp.ps.gz",
+}
+
+@InProceedings{filliatre-marche-04,
+ author = "Jean-Christophe Filliâtre and Claude Marché",
+ title = "Multi-Prover Verification of {C} Programs",
+ booktitle = icfem,
+ year = "2004",
+ publisher = springer,
+ series = lncs,
+ volume = "3308",
+ pages = "15--29",
+ URL = "http://www.lri.fr/~filliatr/ftp/publis/caduceus.ps.gz",
+}
+
+@InProceedings{filliatre-pereira-16,
+ author = "Jean{-}Christophe Filli{\^{a}}tre and M{\'{a}}rio
+ Pereira",
+ title = "A Modular Way to Reason About Iteration",
+ booktitle = nfm,
+ pages = "322--336",
+ year = "2016",
+ series = lncs,
+ volume = "9690",
+ publisher = springer,
+ URL = "https://hal.inria.fr/hal-01281759",
+}
+
+@InProceedings{findler-felleisen-02,
+ author = "Robert Bruce Findler and Matthias Felleisen",
+ title = "Contracts for higher-order functions",
+ booktitle = icfp,
+ year = "2002",
+ pages = "48--59",
+ URL = "http://people.cs.uchicago.edu/~robby/pubs/papers/ho-contracts-icfp2002.pdf",
+}
+
+@Article{fischbach-hannan-02,
+ author = "Adam Fischbach and John Hannan",
+ title = "Specification and Correctness of Lambda Lifting",
+ journal = jfp,
+ year = "2003",
+ volume = "13",
+ number = "3",
+ pages = "509--543",
+ URL = "http://dx.doi.org/10.1017/S0956796802004604",
+}
+
+@Article{fisher-mitchell-98,
+ author = "Kathleen Fisher and John C. Mitchell",
+ title = "On the Relationship between Classes, Objects and Data
+ Abstraction",
+ journal = tapos,
+ year = "1998",
+ volume = "4",
+ number = "1",
+ pages = "3--25",
+ URL = "http://www.research.att.com/~kfisher/files/tapos98.ps",
+}
+
+@InProceedings{flanagan-abadi-99,
+ author = "Cormac Flanagan and Mart\'{\i}n Abadi",
+ title = "Types for Safe Locking",
+ booktitle = esop,
+ year = "1999",
+ pages = "91--108",
+ publisher = springer,
+ series = lncs,
+ volume = "1576",
+ URL = "http://users.soe.ucsc.edu/~cormac/papers/esop99.pdf",
+}
+
+@InProceedings{flanagan-al-93,
+ author = "Cormac Flanagan and Amr Sabry and Bruce F. Duba and
+ Matthias Felleisen",
+ title = "The Essence of Compiling with Continuations",
+ booktitle = pldi,
+ year = "1993",
+ pages = "237--247",
+ URL = "http://www.cs.rice.edu/CS/PLT/Publications/Scheme/pldi93-fsdf.ps.gz",
+}
+
+@InProceedings{flanagan-al-96,
+ author = "Cormac Flanagan and Matthew Flatt and Shriram
+ Krishnamurthi and Stephanie Weirich and Matthias
+ Felleisen",
+ year = "1996",
+ booktitle = pldi,
+ title = "Catching Bugs in the Web of Program Invariants",
+ URL = "http://www.cs.rice.edu/CS/PLT/Publications/Scheme/pldi96-ffkwf.ps.gz",
+}
+
+@PhdThesis{flanagan-effective-97,
+ school = "Rice University",
+ title = "Effective Static Debugging via Componential Set-Based
+ Analysis",
+ year = "1997",
+ pages = "164",
+ author = "Cormac Flanagan",
+ URL = "http://www.cs.rice.edu/CS/PLT/Publications/Scheme/thesis-flanagan.ps.gz",
+}
+
+@InProceedings{flanagan-esc-02,
+ author = "Cormac Flanagan and K. Rustan M. Leino and Mark
+ Lillibridge and Greg Nelson and James B. Saxe and
+ Raymie Stata",
+ title = "Extended Static Checking for {Java}",
+ booktitle = pldi,
+ pages = "234--245",
+ year = "2002",
+ URL = "http://www.soe.ucsc.edu/~cormac/papers/pldi02.ps",
+}
+
+@InProceedings{flanagan-saxe-01,
+ author = "Cormac Flanagan and James B. Saxe",
+ title = "Avoiding exponential explosion: generating compact
+ verification conditions",
+ booktitle = popl,
+ year = "2001",
+ pages = "193--205",
+ URL = "http://www.soe.ucsc.edu/~cormac/papers/popl01.ps",
+}
+
+@InProceedings{floyd-67,
+ author = "R. W. Floyd",
+ title = "Assigning meanings to programs",
+ booktitle = "Mathematical Aspects of Computer Science",
+ series = "Proceedings of Symposia in Applied Mathematics",
+ volume = "19",
+ year = "1967",
+ organization = ams,
+ pages = "19--32",
+ URL = "https://people.eecs.berkeley.edu/~necula/Papers/FloydMeaning.pdf",
+}
+
+@InProceedings{fluet-02,
+ author = "Matthew Fluet and Riccardo Pucella",
+ title = "Phantom types and subtyping",
+ booktitle = tcsconf,
+ pages = "448--460",
+ year = "2002",
+ URL = "http://arXiv.org/abs/cs.PL/0403034",
+}
+
+@InProceedings{fluet-al-06,
+ author = "Matthew Fluet and Greg Morrisett and Amal Ahmed",
+ title = "Linear Regions Are All You Need",
+ booktitle = esop,
+ pages = "7--21",
+ year = "2006",
+ volume = "3924",
+ series = lncs,
+ publisher = springer,
+ URL = "http://ttic.uchicago.edu/~fluet/research/substruct-regions/ESOP06/esop06.pdf",
+}
+
+@PhdThesis{fluet-phd-07,
+ author = "Matthew Fluet",
+ title = "Monadic and Substructural Type Systems for
+ Region-Based Memory Management",
+ school = "Cornell University",
+ year = "2007",
+ URL = "http://ttic.uchicago.edu/~fluet/research/thesis/fluet-thesis.single.pdf",
+}
+
+@InProceedings{fluet-pucella-02,
+ author = "Matthew Fluet and Riccardo Pucella",
+ title = "Phantom Types and Subtyping",
+ booktitle = ifiptcs,
+ pages = "448--460",
+ year = "2002",
+ volume = "223",
+ series = "IFIP Conference Proceedings",
+ publisher = kluwer,
+ URL = "http://www.cs.cornell.edu/people/fluet/phantom-subtyping/TCS02/tcs02.ps",
+}
+
+@InProceedings{fluet-pucella-05,
+ author = "Matthew Fluet and Riccardo Pucella",
+ title = "Practical Datatype Specializations with Phantom Types
+ and Recursion Schemes",
+ booktitle = ml,
+ year = "2005",
+ series = entcs,
+ URL = "http://www.cs.cornell.edu/people/fluet/specializations/MLWRK05/mlwrk05.pdf",
+}
+
+@Article{focardi-gorrieri-95,
+ author = "Riccardo Focardi and Roberto Gorrieri",
+ title = "A classification of security properties for process
+ algebras",
+ journal = "Journal of Computer Security",
+ volume = "3",
+ number = "1",
+ pages = "5--33",
+ year = "1995",
+ URL = "http://www.cs.unibo.it/~gorrieri/Papers/jcsfinal.ps.gz",
+}
+
+@InProceedings{ford-02,
+ author = "Bryan Ford",
+ title = "Packrat parsing: simple, powerful, lazy, linear time",
+ booktitle = icfp,
+ year = "2002",
+ pages = "36--47",
+ URL = "http://www.brynosaurus.com/pub/lang/packrat-icfp02.pdf",
+}
+
+@InProceedings{ford-04,
+ author = "Bryan Ford",
+ title = "Parsing expression grammars: a recognition-based
+ syntactic foundation",
+ booktitle = popl,
+ year = "2004",
+ pages = "111--122",
+ URL = "http://pdos.csail.mit.edu/~baford/packrat/popl04/peg-popl04.pdf",
+}
+
+@TechReport{foster-aiken-restrict-01,
+ author = "Jeffrey S. Foster and Alex Aiken",
+ institution = "University of California, Berkeley",
+ title = "Checking Programmer-Specified Non-Aliasing",
+ year = "2001",
+ number = "UCB//CSD-01-1160",
+ URL = "http://www.cs.umd.edu/~jfoster/papers/tr01-restrict.pdf",
+}
+
+@InProceedings{foster-flow-sensitive-qualifiers-02,
+ author = "Jeffrey S. Foster and Tachio Terauchi and Alex Aiken",
+ title = "Flow-Sensitive Type Qualifiers",
+ booktitle = pldi,
+ year = "2002",
+ pages = "1--12",
+ URL = "http://www.cs.umd.edu/~jfoster/papers/pldi02.pdf",
+}
+
+@Article{fournet-al-join-03,
+ author = "Cédric Fournet and Cosimo Laneve and Luc Maranget and
+ Didier Rémy",
+ journal = jlap,
+ title = "Inheritance in the Join Calculus",
+ volume = "57",
+ number = "2",
+ pages = "23--69",
+ year = "2003",
+ URL = "http://gallium.inria.fr/~remy/work/ojoin/jojoin.pdf",
+}
+
+@InProceedings{fournet-al-join-97,
+ author = "Cédric Fournet and Luc Maranget and Cosimo Laneve and
+ Didier Rémy",
+ title = "Implicit typing à la {ML} for the join-calculus",
+ booktitle = concur,
+ series = lncs,
+ publisher = springer,
+ volume = "1243",
+ pages = "196--212",
+ year = "1997",
+ URL = "http://gallium.inria.fr/~remy/ftp/typing-join.pdf",
+}
+
+@InProceedings{fournet-gonthier-96,
+ author = "Cédric Fournet and Georges Gonthier",
+ title = "The Reflexive Chemical Abstract Machine and the
+ Join-Calculus",
+ booktitle = popl,
+ pages = "372--385",
+ year = "1996",
+ URL = "https://doi.org/10.1145/237721.237805",
+}
+
+@InProceedings{fournet-gordon-02,
+ author = "Cédric Fournet and Andrew D. Gordon",
+ title = "Stack Inspection: Theory and Variants",
+ booktitle = popl,
+ pages = "307--318",
+ year = "2002",
+ URL = "http://research.microsoft.com/~fournet/papers/stack-inspection-theory-and-variants-popl-02.ps",
+}
+
+@Article{fournet-gordon-03,
+ author = "Cédric Fournet and Andrew D. Gordon",
+ title = "Stack Inspection: Theory and Variants",
+ journal = toplas,
+ year = "2003",
+ volume = "25",
+ number = "3",
+ pages = "360--399",
+ URL = "http://doi.acm.org/10.1145/641909.641912",
+}
+
+@Article{francalanza-rathke-sassone-2011,
+ author = "Adrian Francalanza and Julian Rathke and Vladimiro
+ Sassone",
+ title = "Permission-Based Separation Logic for Message-Passing
+ Concurrency",
+ journal = lmcs,
+ volume = "7",
+ number = "3",
+ year = "2011",
+ URL = "http://arxiv.org/abs/1106.5128",
+}
+
+@InProceedings{fredman-saks-89,
+ author = "Michael Fredman and Michael Saks",
+ title = "The Cell Probe Complexity of Dynamic Data Structures",
+ pages = "345--354",
+ booktitle = "Annual Symposium on Theory of Computing ({STOC})",
+ publisher = "ACM",
+ year = "1989",
+ URL = "http://dx.doi.org/10.1145/73007.73040",
+}
+
+@Article{fredman-tarjan-87,
+ author = "Michael L. Fredman and Robert Endre Tarjan",
+ title = "Fibonacci heaps and their uses in improved network
+ optimization algorithms",
+ journal = jacm,
+ volume = "34",
+ number = "3",
+ year = "1987",
+ pages = "596--615",
+ URL = "http://doi.acm.org/10.1145/28869.28874",
+}
+
+@InProceedings{freeman-91,
+ author = "Tim Freeman and Frank Pfenning",
+ title = "Refinement types for {ML}",
+ booktitle = pldi,
+ pages = "268--277",
+ year = "1991",
+ URL = "http://www.cs.cmu.edu/~fp/papers/pldi91.pdf",
+}
+
+@TechReport{fresh-ocaml,
+ author = "Mark R. Shinwell and Andrew M. Pitts",
+ year = "2005",
+ title = "{Fresh Objective Caml} user manual",
+ institution = "University of Cambridge",
+ number = "621",
+ URL = "http://www.cl.cam.ac.uk/TechReports/UCAM-CL-TR-621.pdf",
+}
+
+@PhdThesis{frey-04,
+ author = "Alexandre Frey",
+ title = "Approche algébrique du typage d'un langage à la {ML}
+ avec objets, sous-typage et multi-méthodes",
+ school = "École des Mines de Paris",
+ year = "2004",
+ URL = "http://gallium.inria.fr/~remy/students/alexandre.frey.pdf",
+}
+
+@InProceedings{frey-97,
+ author = "Alexandre Frey",
+ title = "Satisfying Subtype Inequalities in Polynomial Space",
+ booktitle = sas,
+ series = lncs,
+ number = "1302",
+ year = "1997",
+ pages = "265--277",
+ publisher = springer,
+ URL = "http://citeseer.ist.psu.edu/frey97satisfying.html",
+ alturl = "http://dx.doi.org/10.1016/S0304-3975(00)00314-5",
+}
+
+@InProceedings{frisch-castagna-benzaken-02,
+ author = "Alain Frisch and Giuseppe Castagna and V{\'e}ronique
+ Benzaken",
+ title = "Semantic Subtyping",
+ booktitle = lics,
+ year = "2002",
+ pages = "137--146",
+ URL = "http://www.cduce.org/papers/lics02.ps.gz",
+}
+
+@Article{frisch-castagna-benzaken-08,
+ author = "Alain Frisch and Giuseppe Castagna and V{\'e}ronique
+ Benzaken",
+ title = "Semantic subtyping: Dealing set-theoretically with
+ function, union, intersection, and negation types",
+ journal = jacm,
+ volume = "55",
+ number = "4",
+ year = "2008",
+ URL = "http://www.pps.univ-paris-diderot.fr/~gc/papers/semantic_subtyping.pdf",
+}
+
+@InProceedings{fstar,
+ author = "Nikhil Swamy and Juan Chen and C{\'e}dric Fournet and
+ Pierre-Yves Strub and Karthik Bhargavan and Jean Yang",
+ title = "Secure distributed programming with value-dependent
+ types",
+ booktitle = icfp,
+ year = "2011",
+ pages = "266--278",
+ URL = "http://research.microsoft.com/pubs/150012/icfp-camera-ready.pdf",
+}
+
+@InProceedings{fuh-mishra-88,
+ author = "You-Chin Fuh and Prateek Mishra",
+ title = "Type inference with subtypes",
+ booktitle = esop,
+ publisher = springer,
+ series = lncs,
+ volume = "300",
+ year = "1988",
+ pages = "94--114",
+ URL = "http://dx.doi.org/10.1007/3-540-19027-9_7",
+}
+
+@InProceedings{fuh-mishra-gap-89,
+ author = "You-Chin Fuh and Prateek Mishra",
+ title = "Polymorphic Subtype Inference: Closing the
+ Theory-Practice Gap",
+ pages = "167--183",
+ booktitle = tapsoft,
+ series = lncs,
+ volume = "352",
+ publisher = springer,
+ year = "1989",
+ URL = "http://dx.doi.org/10.1007/3-540-50940-2_35",
+}
+
+@InProceedings{furuse-03,
+ author = "Jun Furuse",
+ title = "Extensional Polymorphism by Flow Graph Dispatching",
+ booktitle = aplas,
+ publisher = springer,
+ series = lncs,
+ volume = "2895",
+ year = "2003",
+ URL = "http://gallium.inria.fr/~furuse/publications/flowgraph.ps.gz",
+}
+
+@PhdThesis{gabbay-01,
+ author = "Murdoch J. Gabbay",
+ title = "A Theory of Inductive Definitions with
+ $\alpha$-Equivalence",
+ school = "Cambridge University",
+ year = "2001",
+ URL = "http://www.macs.hw.ac.uk/~gabbay/papers/thesis.pdf",
+}
+
+@Unpublished{gabbay-04,
+ author = "Murdoch J. Gabbay",
+ title = "A General Mathematics of Names in Syntax",
+ year = "2004",
+ note = "Submitted for publication",
+ URL = "http://www.macs.hw.ac.uk/~gabbay/papers/genmns.pdf",
+}
+
+@Article{gabbay-pitts-02,
+ author = "Murdoch J. Gabbay and Andrew M. Pitts",
+ title = "A New Approach to Abstract Syntax with Variable
+ Binding",
+ journal = fac,
+ year = "2002",
+ volume = "13",
+ number = "3--5",
+ pages = "341--363",
+ URL = "http://www.cl.cam.ac.uk/~amp12/papers/newaas/newaas-jv.pdf",
+ alturl = "http://www.springerlink.com/link.asp?id=epn028x83rqw00qv",
+}
+
+@Article{galil-italiano-91,
+ author = "Zvi Galil and Giuseppe F. Italiano",
+ title = "Data Structures and Algorithms for Disjoint Set Union
+ Problems",
+ journal = surveys,
+ volume = "23",
+ number = "3",
+ pages = "319--344",
+ year = "1991",
+ URL = "http://doi.acm.org/10.1145/116873.116878",
+}
+
+@Article{galler-fischer-64,
+ author = "Bernard A. Galler and Michael J. Fischer",
+ title = "An improved equivalence algorithm",
+ journal = cacm,
+ volume = "7",
+ number = "5",
+ pages = "301--303",
+ year = "1964",
+ URL = "http://doi.acm.org/10.1145/364099.364331",
+}
+
+@Article{gapeyev-levin-pierce-00,
+ author = "Vladimir Gapeyev and Michael Levin and Benjamin
+ Pierce",
+ title = "Recursive Subtyping Revealed",
+ journal = jfp,
+ volume = "12",
+ number = "6",
+ pages = "511--548",
+ year = "2002",
+ URL = "http://dx.doi.org/10.1017/S0956796802004318",
+}
+
+@InProceedings{gardner-ntizk-wright-14,
+ author = "Philippa Gardner and Gian Ntzik and Adam Wright",
+ title = "Local Reasoning for the {POSIX} File System",
+ booktitle = esop,
+ pages = "169--188",
+ year = "2014",
+ series = lncs,
+ volume = "8410",
+ publisher = springer,
+ URL = "https://www.doc.ic.ac.uk/~gn408/POSIXFS/esop2014.pdf",
+}
+
+@Book{garey-johnson-79,
+ author = "Michael R. Garey and David S. Johnson",
+ title = "Computers and Intractability: {A} Guide to the Theory
+ of {NP}-Completeness",
+ year = "1979",
+ publisher = "W. H. Freeman and Company",
+}
+
+@InProceedings{garrigue-00,
+ author = "Jacques Garrigue",
+ title = "Code reuse through polymorphic variants",
+ booktitle = fse,
+ year = "2000",
+ URL = "http://www.math.nagoya-u.ac.jp/~garrigue/papers/variant-reuse.ps.gz",
+}
+
+@InProceedings{garrigue-02,
+ author = "Jacques Garrigue",
+ title = "Simple Type Inference for Structural Polymorphism",
+ booktitle = fool,
+ year = "2002",
+ URL = "http://www.math.nagoya-u.ac.jp/~garrigue/papers/structural-inf.ps.gz",
+}
+
+@InProceedings{garrigue-98,
+ author = "Jacques Garrigue",
+ title = "Programming with polymorphic variants",
+ booktitle = ml,
+ year = "1998",
+ URL = "http://www.math.nagoya-u.ac.jp/~garrigue/papers/variants.ps.gz",
+}
+
+@TechReport{garrigue-furuse-95,
+ author = "Jun P. Furuse and Jacques Garrigue",
+ title = "A label-selective lambda-calculus with optional
+ arguments and its compilation method",
+ institution = "Kyoto University",
+ year = "1995",
+ type = "RIMS Preprint",
+ number = "1041",
+ URL = "http://wwwfun.kurims.kyoto-u.ac.jp/~garrigue/papers/rims-1041.pdf",
+}
+
+@InProceedings{garrigue-relax-04,
+ author = "Jacques Garrigue",
+ title = "Relaxing the Value Restriction",
+ booktitle = flops,
+ pages = "196--213",
+ year = "2004",
+ volume = "2998",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.math.nagoya-u.ac.jp/~garrigue/papers/morepoly-long.pdf",
+}
+
+@Article{garrigue-remy-99,
+ author = "Jacques Garrigue and Didier R{\'e}my",
+ title = "Extending {ML} with Semi-Explicit Higher-Order
+ Polymorphism",
+ journal = ic,
+ year = "1999",
+ volume = "155",
+ number = "1",
+ pages = "134--169",
+ URL = "http://gallium.inria.fr/~remy/ftp/iandc.pdf",
+}
+
+@InProceedings{garrigue-remy-gadts-13,
+ author = "Jacques Garrigue and Didier R{\'e}my",
+ title = "Ambivalent types for principal type inference with
+ {GADT}s",
+ booktitle = aplas,
+ year = "2013",
+ URL = "http://gallium.inria.fr/~remy/gadts/Garrigue-Remy:gadts@aplas2013.pdf",
+}
+
+@PhdThesis{gaster-98,
+ author = "Benedict R. Gaster",
+ title = "Records, variants and qualified types",
+ school = "University of Nottingham",
+ year = "1998",
+ URL = "http://www.cs.nott.ac.uk/Research/fop/gaster-thesis.ps",
+}
+
+@TechReport{gaster-jones-96,
+ author = "Benedict R. Gaster and Mark P. Jones",
+ title = "A Polymorphic Type System for Extensible Records and
+ Variants",
+ institution = "Department of Computer Science, University of
+ Nottingham",
+ year = "1996",
+ number = "NOTTCS-TR-96-3",
+ URL = "http://web.cecs.pdx.edu/~mpj/pubs/polyrec.html",
+}
+
+@InProceedings{gauthier-pottier-04,
+ author = "Nadji Gauthier and François Pottier",
+ title = "Numbering Matters: First-Order Canonical Forms for
+ Second-Order Recursive Types",
+ booktitle = icfp,
+ URL = "http://gallium.inria.fr/~fpottier/publis/gauthier-fpottier-icfp04.pdf",
+ year = "2004",
+ pages = "150--161",
+}
+
+@InProceedings{gay-modular-session-types-10,
+ author = "Simon J. Gay and Vasco Thudichum Vasconcelos and
+ Ant{\'o}nio Ravara and Nils Gesbert and Alexandre Z.
+ Caldeira",
+ title = "Modular session types for distributed object-oriented
+ programming",
+ booktitle = popl,
+ year = "2010",
+ pages = "299--312",
+ URL = "http://www.dcs.gla.ac.uk/~simon/publications/ModularSessionTypes.pdf",
+}
+
+@InProceedings{german-clarke-halpern-83,
+ author = "Steven German and Edmund Clarke and Joseph Halpern",
+ title = "Reasoning About Procedures as Parameters",
+ booktitle = "Logic of Programs",
+ pages = "206--220",
+ year = "1983",
+ volume = "164",
+ series = lncs,
+ publisher = springer,
+ URL = "http://dx.doi.org/10.1007/3-540-12896-4_365",
+}
+
+@TechReport{geser-chaotic-94,
+ author = "Alfons Geser and Jens Knoop and Gerald Lüttgen and
+ Oliver Rüthing and Bernhard Steffen",
+ title = "Chaotic fixed point iterations",
+ institution = "Fakultät für Mathematik und Informatik, Universität
+ Passau",
+ year = "1994",
+ type = "MIP-Bericht",
+ number = "9403",
+ URL = "http://citeseer.ist.psu.edu/190778.html",
+}
+
+@Manual{ghc,
+ author = "The GHC team",
+ title = "The {Glasgow Haskell} compiler",
+ year = "2005",
+ URL = "http://www.haskell.org/ghc/",
+}
+
+@Article{ghelli-divergence-95,
+ title = "Divergence of {$F_\leq$} type checking",
+ author = "Giorgio Ghelli",
+ journal = tcs,
+ pages = "131--162",
+ year = "1995",
+ volume = "139",
+ number = "1--2",
+ URL = "ftp://ftp.di.unipi.it/pub/Papers/ghelli/DivergenceFsubTCS95.ps.gz",
+}
+
+@InProceedings{gherghina-structured-11,
+ author = "Cristian Gherghina and Cristina David and Shengchao
+ Qin and Wei-Ngan Chin",
+ title = "Structured Specifications for Better Verification of
+ Heap-Manipulating Programs",
+ year = "2011",
+ pages = "386--401",
+ booktitle = fm,
+ publisher = springer,
+ series = lncs,
+ volume = "6664",
+ URL = "http://loris-7.ddns.comp.nus.edu.sg/~project/hip/publications/FM_2011_Case.pdf",
+}
+
+@InProceedings{gibbons-dgp-06,
+ author = "Jeremy Gibbons",
+ title = "Datatype-generic programming",
+ booktitle = "International Spring School on Datatype-Generic
+ Programming",
+ pages = "1--71",
+ year = "2006",
+ series = lncs,
+ publisher = springer,
+ volume = "4719",
+ URL = "http://www.cs.ox.ac.uk/jeremy.gibbons/publications/dgp.pdf",
+}
+
+@TechReport{gifford-fx-87,
+ author = "David K. Gifford and Pierre Jouvelot and John M.
+ Lucassen and Mark A. Sheldon",
+ title = "{FX-87} Reference Manual",
+ institution = "Massachusetts Institute of Technology",
+ year = "1987",
+ number = "MIT/LCS/TR-407",
+}
+
+@TechReport{gifford-fx-91,
+ author = "David K. Gifford and Pierre Jouvelot and Mark A.
+ Sheldon and James W. O'Toole",
+ title = "Report on the {FX-91} Programming Language",
+ institution = "Massachusetts Institute of Technology",
+ year = "1992",
+ number = "MIT/LCS/TR-531",
+ URL = "http://www.psrg.lcs.mit.edu/history/publications.html#fxps",
+}
+
+@PhdThesis{girard-72,
+ author = "Jean-Yves Girard",
+ title = "Interprétation fonctionnelle et élimination des
+ coupures de l'arith\-mé\-ti\-que d'ordre supérieur",
+ school = "Universit{\'e} Paris 7",
+ type = "Th\`ese d'\'Etat",
+ year = "1972",
+}
+
+@Article{girard-87,
+ author = "Jean-Yves Girard",
+ title = "Linear logic",
+ journal = tcs,
+ year = "1987",
+ volume = "50",
+ number = "1",
+ pages = "1--102",
+ URL = "http://iml.univ-mrs.fr/~girard/linear.pdf",
+}
+
+@InProceedings{glew-00,
+ author = "Neal Glew",
+ title = "An Efficient Class and Object Encoding",
+ booktitle = oopsla,
+ pages = "311--324",
+ year = "2000",
+ URL = "http://glew.org/nglew/papers/oce-oopsla.ps.gz",
+}
+
+@InProceedings{glew-02,
+ author = "Neal Glew",
+ title = "A Theory of Second-Order Trees",
+ booktitle = esop,
+ pages = "147--161",
+ year = "2002",
+ volume = "2305",
+ series = lncs,
+ publisher = springer,
+ URL = "http://glew.org/nglew/papers/tsot-esop.pdf",
+}
+
+@InProceedings{glew-99,
+ author = "Neal Glew",
+ title = "Object Closure Conversion",
+ booktitle = hoots,
+ year = "1999",
+ series = entcs,
+ volume = "26",
+ pages = "52--68",
+ URL = "http://glew.org/nglew/papers/occ-hoots.ps.gz",
+}
+
+@InProceedings{gmeta-12,
+ author = "Gyesik Lee and Bruno C. d. S. Oliveira and Sungkeun
+ Cho and Kwangkeun Yi",
+ title = "{GMeta}: {A} Generic Formal Metatheory Framework for
+ First-Order Representations",
+ booktitle = esop,
+ pages = "436--455",
+ year = "2012",
+ series = lncs,
+ volume = "7211",
+ publisher = springer,
+ URL = "http://ropas.snu.ac.kr/gmeta/gmeta.pdf",
+}
+
+@InProceedings{goerdt-85,
+ author = "Andreas Goerdt",
+ title = "A {Hoare} Calculus for Functions Defined by Recursion
+ on Higher Types",
+ booktitle = "Logic of Programs",
+ year = "1985",
+ pages = "106--117",
+ publisher = springer,
+ series = lncs,
+ volume = "193",
+ URL = "http://dx.doi.org/10.1007/3-540-15648-8_9",
+}
+
+@InProceedings{goguen-meseguer-82,
+ author = "Joseph Goguen and José Meseguer",
+ title = "Security policies and security models",
+ booktitle = sp,
+ year = "1982",
+ pages = "11--20",
+}
+
+@InProceedings{gong-97,
+ author = "Li Gong and Marianne Mueller and Hemma Prafullchandra
+ and Roland Schemers",
+ title = "Going Beyond the Sandbox: An Overview of the New
+ Security Architecture in the {Java Development Kit
+ 1.2}",
+ booktitle = "{USENIX} Symposium on Internet Technologies and
+ Systems",
+ year = "1997",
+ pages = "103--112",
+ URL = "http://secinf.net/uplarticle/10/jdk12arch.ps",
+}
+
+@InProceedings{gong-schemers-98,
+ author = "Li Gong and Roland Schemers",
+ title = "Implementing Protection Domains in the {Java}
+ Development Kit 1.2",
+ booktitle = ndss,
+ year = "1998",
+ URL = "http://www.isoc.org/isoc/conferences/ndss/98/gong.pdf",
+}
+
+@InProceedings{gordon-12,
+ author = "Colin S. Gordon and Matthew J. Parkinson and Jared
+ Parsons and Aleks Bromfield and Joe Duffy",
+ title = "Uniqueness and reference immutability for safe
+ parallelism",
+ booktitle = oopsla,
+ year = "2012",
+ pages = "21--40",
+ URL = "http://homes.cs.washington.edu/~csgordon/papers/oopsla12.pdf",
+}
+
+@InProceedings{gordon-melham-96,
+ author = "Andrew D. Gordon and Tom Melham",
+ title = "Five Axioms of Alpha-Conversion",
+ booktitle = tphol,
+ pages = "173--191",
+ year = "1996",
+ volume = "1125",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.ftp.cl.cam.ac.uk/ftp/papers/adg/hug96.ps.gz",
+}
+
+@InProceedings{gordon-noble-07,
+ author = "Donald Gordon and James Noble",
+ title = "Dynamic ownership in a dynamic language",
+ booktitle = dls,
+ year = "2007",
+ pages = "41--52",
+ URL = "http://doi.acm.org/10.1145/1297081.1297090",
+}
+
+@InProceedings{gotsman-aplas-07,
+ author = "Alexey Gotsman and Josh Berdine and Byron Cook and
+ Noam Rinetzky and Mooly Sagiv",
+ title = "Local Reasoning for Storable Locks and Threads",
+ booktitle = aplas,
+ pages = "19--37",
+ year = "2007",
+ series = lncs,
+ volume = "4807",
+ publisher = springer,
+ URL = "http://dx.doi.org/10.1007/978-3-540-76637-7_3",
+}
+
+@TechReport{gotsman-storable-07,
+ author = "Alexey Gotsman and Josh Berdine and Byron Cook and
+ Noam Rinetzky and Mooly Sagiv",
+ title = "Local Reasoning for Storable Locks and Threads",
+ institution = "Microsoft Research",
+ year = "2007",
+ number = "MSR-TR-2007-39",
+ URL = "http://research.microsoft.com/pubs/70427/tr-2007-39.pdf",
+}
+
+@InProceedings{goubault-dim-94,
+ author = "Jean Goubault",
+ title = "Inférence d'unités physiques en {ML}",
+ booktitle = jfla,
+ pages = "3--20",
+ year = "1994",
+}
+
+@Article{gries-73,
+ author = "David Gries",
+ title = "Describing an Algorithm by {Hopcroft}",
+ journal = acta,
+ volume = "2",
+ pages = "97--109",
+ year = "1973",
+ URL = "http://dx.doi.org/10.1007/BF00264025",
+}
+
+@Article{grosch-90,
+ author = "Josef Grosch",
+ title = "Efficient and Comfortable Error Recovery in Recursive
+ Descent Parsers",
+ journal = "Structured Programming",
+ volume = "11",
+ number = "3",
+ pages = "129--140",
+ year = "1990",
+ URL = "http://www.cocolab.com/products/cocktail/doc.pdf/ell.pdf",
+}
+
+@Article{grossman-06,
+ author = "Dan Grossman",
+ title = "Quantified Types in an Imperative Language",
+ journal = toplas,
+ year = "2006",
+ volume = "28",
+ number = "3",
+ pages = "429--475",
+ URL = "http://www.cs.washington.edu/homes/djg/papers/qtil.pdf",
+}
+
+@Book{grune-jacobs-08,
+ author = "Dick Grune and Ceriel J. H. Jacobs",
+ title = "Parsing techniques: a practical guide, second
+ edition",
+ year = "2008",
+ publisher = springer,
+ series = "Monographs in computer science",
+ URL = "http://www.cs.vu.nl/~dick/PT2Ed.html",
+}
+
+@Book{grune-jacobs-90,
+ author = "Dick Grune and Ceriel J. H. Jacobs",
+ title = "Parsing techniques: a practical guide",
+ year = "1990",
+ publisher = ellis,
+ URL = "http://www.cs.vu.nl/~dick/PTAPG.html",
+}
+
+@Unpublished{gueneau-cakeml-16,
+ author = "Arma{\"e}l Gu{\'e}neau and Magnus O. Myreen and Ramana
+ Kumar and Michael Norrish",
+ title = "Verified Characteristic Formulae for {CakeML}",
+ note = "Submitted",
+ year = "2016",
+}
+
+@Misc{gueneau-pottier-protzenko-13,
+ author = "Armaël Guéneau and François Pottier and Jonathan
+ Protzenko",
+ title = "The ins and outs of iteration in {Mezzo}",
+ note = "\url{http://goo.gl/NrgKc4}",
+ year = "2013",
+ howpublished = "Higher-Order Programming and Effects (HOPE)",
+}
+
+@InProceedings{guillemette-monnier-07,
+ author = "Louis-Julien Guillemette and Stefan Monnier",
+ title = "A Type-Preserving Closure Conversion in {Haskell}",
+ booktitle = hw,
+ pages = "83--92",
+ year = "2007",
+ URL = "http://www.iro.umontreal.ca/~monnier/tcm.pdf",
+}
+
+@InProceedings{guillemette-monnier-08,
+ author = "Louis-Julien Guillemette and Stefan Monnier",
+ title = "A Type-Preserving Compiler in {Haskell}",
+ booktitle = icfp,
+ year = "2008",
+ pages = "75--86",
+ URL = "http://www-etud.iro.umontreal.ca/~guillelj/icfp08.pdf",
+}
+
+@InProceedings{guillemette-vote-08,
+ author = "Louis-Julien Guillemette and Stefan Monnier",
+ title = "One Vote for Type Families in {Haskell}!",
+ booktitle = tfp,
+ year = "2008",
+ URL = "http://www-etud.iro.umontreal.ca/~guillelj/tfp08.pdf",
+}
+
+@InProceedings{gundry-10,
+ author = "Adam Gundry and Conor McBride and James McKinna",
+ title = "Type inference in context",
+ booktitle = msfp,
+ pages = "43--54",
+ year = "2010",
+ URL = "https://personal.cis.strath.ac.uk/adam.gundry/type-inference/type-inference-final.pdf",
+}
+
+@PhdThesis{gundry-13,
+ author = "Adam Gundry",
+ title = "Type Inference, {Haskell} and Dependent Types",
+ school = "University of Strathclyde",
+ year = "2013",
+ URL = "https://personal.cis.strath.ac.uk/adam.gundry/thesis/thesis-2013-12-03.pdf",
+}
+
+@Article{gupta-nandivada-15,
+ author = "Kartik Gupta and V. Krishna Nandivada",
+ title = "Lexical state analyzer for {JavaCC} grammars",
+ journal = spe,
+ URL = "http://dx.doi.org/10.1002/spe.2322",
+ year = "2015",
+}
+
+@InProceedings{gustavsson-svenningsson-01,
+ author = "Jörgen Gustavsson and Josef Svenningsson",
+ title = "Constraint Abstractions",
+ booktitle = "Symposium on Programs as Data Objects",
+ year = "2001",
+ volume = "2053",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.cse.chalmers.se/~josefs/publications/ca.pdf",
+}
+
+@InProceedings{guzman-suarez-94,
+ author = "Juan Carlos Guzm{\'a}n and Asc{\'a}nder Su{\'a}rez",
+ title = "An Extended Type System for Exceptions",
+ booktitle = mlapp,
+ series = "INRIA Research Reports",
+ publisher = "INRIA",
+ number = "2265",
+ year = "1994",
+ pages = "127--135",
+}
+
+@InProceedings{haack-huisman-hurlin-08,
+ author = "Christian Haack and Marieke Huisman and Cl{\'{e}}ment
+ Hurlin",
+ title = "Reasoning about {Java's} Reentrant Locks",
+ booktitle = aplas,
+ pages = "171--187",
+ year = "2008",
+ series = lncs,
+ volume = "5356",
+ publisher = springer,
+ URL = "http://www.cs.ru.nl/~chaack/papers/papers/reentrant.pdf",
+}
+
+@Article{haack-hurlin-09,
+ author = "Christian Haack and Cl{\'{e}}ment Hurlin",
+ title = "Resource Usage Protocols for Iterators",
+ journal = jot,
+ volume = "8",
+ number = "4",
+ pages = "55--83",
+ year = "2009",
+ URL = "http://www.jot.fm/issues/issue_2009_06/article3.pdf",
+}
+
+@InProceedings{haack-wells-03,
+ author = "Christian Haack and J. B. Wells",
+ title = "Type error slicing in implicitly typed, higher-order
+ languages",
+ booktitle = esop,
+ year = "2003",
+ series = lncs,
+ publisher = springer,
+ volume = "2618",
+ URL = "http://www.macs.hw.ac.uk/~jbw/papers/Haack+Wells:Type-Error-Slicing-in-Implicitly-Typed-Higher-Order-Languages:ESOP-2003.pdf",
+}
+
+@InProceedings{hall-94,
+ author = "Cordelia Hall and Kevin Hammond and Simon {Peyton
+ Jones} and Philip Wadler",
+ title = "Type classes in {Haskell}",
+ booktitle = esop,
+ pages = "241--256",
+ year = "1994",
+ volume = "788",
+ series = lncs,
+ publisher = springer,
+ URL = "http://research.microsoft.com/Users/simonpj/Papers/classhask.ps.gz",
+}
+
+@Article{hall-96,
+ author = "Cordelia Hall and Kevin Hammond and Simon {Peyton
+ Jones} and Philip Wadler",
+ title = "Type classes in {Haskell}",
+ journal = toplas,
+ year = "1996",
+ volume = "18",
+ number = "2",
+ pages = "109--138",
+ URL = "http://doi.acm.org/10.1145/227699.227700",
+}
+
+@InProceedings{haller-odersky-10,
+ author = "Philipp Haller and Martin Odersky",
+ title = "Capabilities for Uniqueness and Borrowing",
+ booktitle = ecoop,
+ year = "2010",
+ pages = "354--378",
+ publisher = springer,
+ series = lncs,
+ volume = "6183",
+ URL = "http://lampwww.epfl.ch/~phaller/doc/haller-odersky10-Capabilities_for_uniqueness_and_borrowing.pdf",
+}
+
+@TechReport{hallett-kfoury-04,
+ author = "Joseph J. Hallett and Assaf J. Kfoury",
+ title = "Programming Examples Needing Polymorphic Recursion",
+ institution = "Department of Computer Science, Boston University",
+ year = "2004",
+ number = "BUCS-TR-2004-004",
+ URL = "http://www.church-project.org/reports/electronic/Hal+Kfo:BUCS-TR-2004-004.pdf",
+}
+
+@PhdThesis{hanus-88,
+ author = "Michael Hanus",
+ title = "Horn Clause Specifications with Polymorphic Types",
+ year = "1988",
+ school = "Fachbereich Informatik, Universität Dortmund",
+ URL = "http://www.informatik.uni-kiel.de/~mh/publications/various/Dissertation.dvi.Z",
+}
+
+@InProceedings{hanus-89,
+ author = "Michael Hanus",
+ title = "Horn Clause Programs with Polymorphic Types: Semantics
+ and Resolution",
+ booktitle = tapsoft,
+ publisher = springer,
+ series = lncs,
+ volume = "352",
+ pages = "225--240",
+ year = "1989",
+ URL = "http://www.informatik.uni-kiel.de/~mh/publications/papers/TAPSOFT89.ps",
+}
+
+@Manual{happy,
+ author = "Simon Marlow and Andy Gill",
+ title = "Happy: the parser generator for {Haskell}",
+ year = "2004",
+ URL = "http://www.haskell.org/happy/",
+}
+
+@Article{hardy-88,
+ author = "Norm Hardy",
+ title = "The Confused Deputy (or why capabilities might have
+ been invented)",
+ journal = sigops,
+ year = "1988",
+ volume = "22",
+ number = "4",
+ pages = "36--38",
+ URL = "http://www.cis.upenn.edu/~KeyKOS/ConfusedDeputy.html",
+}
+
+@Article{harfst-reingold-00,
+ author = "Gregory C. Harfst and Edward M. Reingold",
+ title = "A potential-based amortized analysis of the union-find
+ data structure",
+ journal = "{SIGACT} News",
+ volume = "31",
+ number = "3",
+ pages = "86--95",
+ year = "2000",
+ URL = "http://doi.acm.org/10.1145/356458.356463",
+}
+
+@Article{harper-94,
+ author = "Robert Harper",
+ title = "A simplified account of polymorphic references",
+ journal = ipl,
+ volume = "51",
+ number = "4",
+ year = "1994",
+ pages = "201--206",
+ URL = "http://www.cs.cmu.edu/~rwh/papers/refs/ipl94.pdf",
+}
+
+@Article{harper-99,
+ author = "Robert Harper",
+ title = "Proof-Directed Debugging",
+ journal = jfp,
+ volume = "9",
+ number = "4",
+ year = "1999",
+ pages = "463--469",
+ URL = "http://dx.doi.org/10.1017/S0956796808007119",
+}
+
+@Article{harper-honsell-plotkin-93,
+ author = "Robert Harper and Furio Honsell and Gordon D.
+ Plotkin",
+ title = "A Framework for Defining Logics",
+ journal = jacm,
+ volume = "40",
+ number = "1",
+ pages = "143--184",
+ year = "1993",
+ URL = "http://homepages.inf.ed.ac.uk/gdp/publications/Framework_Def_Log.pdf",
+}
+
+@Article{harper-licata-07,
+ author = "Robert Harper and Daniel R. Licata",
+ title = "Mechanizing metatheory in a logical framework",
+ journal = jfp,
+ volume = "17",
+ number = "4--5",
+ year = "2007",
+ pages = "613--673",
+ URL = "http://www.cs.cmu.edu/~rwh/papers/mech/jfp07.pdf",
+}
+
+@Misc{harper-lillibridge-91,
+ author = "Bob Harper and Mark Lillibridge",
+ title = "{ML} with callcc is unsound",
+ howpublished = "Message to the {TYPES} mailing list",
+ year = "1991",
+ URL = "http://www.cis.upenn.edu/~bcpierce/types/archives/1991/msg00034.html",
+}
+
+@InProceedings{harper-pierce-91,
+ author = "Robert Harper and Benjamin Pierce",
+ title = "A Record Calculus Based on symmetric Concatenation",
+ pages = "131--142",
+ booktitle = popl,
+ year = "1991",
+ URL = "http://www.cis.upenn.edu/~bcpierce/papers/merge.ps",
+}
+
+@InCollection{harper-pierce-attapl,
+ author = "Robert Harper and Benjamin C. Pierce",
+ title = "Design Considerations for {ML}-Style Module Systems",
+ booktitle = "Advanced Topics in Types and Programming Languages",
+ pages = "293--345",
+ publisher = mitp,
+ year = "2005",
+ editor = "Benjamin C. Pierce",
+ chapter = "8",
+}
+
+@Book{harrison-09,
+ author = "John Harrison",
+ title = "Handbook of Practical Logic and Automated Reasoning",
+ publisher = cup,
+ year = "2009",
+ URL = "http://www.cl.cam.ac.uk/~jrh13/atp/",
+}
+
+@Book{haskell-98,
+ editor = "Simon {Peyton Jones}",
+ title = "{Haskell} 98 Language and Libraries: The Revised
+ Report",
+ publisher = cup,
+ year = "2003",
+ URL = "http://www.haskell.org/onlinereport/",
+}
+
+@InProceedings{haskell-history-07,
+ author = "Paul Hudak and John Hughes and Simon {Peyton Jones}
+ and Philip Wadler",
+ title = "A History of {Haskell}: being lazy with class",
+ booktitle = hopl,
+ year = "2007",
+ URL = "https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/history.pdf",
+}
+
+@TechReport{hawblitzel-05,
+ author = "Chris Hawblitzel",
+ title = "Linear Types for Aliased Resources",
+ institution = "Microsoft Research",
+ year = "2005",
+ number = "MSR-TR-2005-141",
+ URL = "http://research.microsoft.com/pubs/70228/tr-2005-141.pdf",
+}
+
+@InProceedings{hecht-ullman-73,
+ author = "Matthew S. Hecht and Jeffrey D. Ullman",
+ title = "Analysis of a simple algorithm for global data flow
+ problems",
+ booktitle = popl,
+ pages = "207--217",
+ year = "1973",
+ URL = "http://doi.acm.org/10.1145/512927.512946",
+}
+
+@TechReport{heeren-improving-02,
+ title = "Improving type-error messages in functional
+ languages",
+ author = "Bastiaan Heeren and Johan Jeuring and Doaitse
+ Swierstra and Pablo Azero Alcocer",
+ year = "2002",
+ institution = "University of Utrecht, Institute of Information and
+ Computing Science",
+ number = "UU-CS-2002-009",
+ URL = "http://archive.cs.uu.nl/pub/RUU/CS/techreps/CS-2002/2002-009.pdf",
+}
+
+@TechReport{heeren2002generalizing,
+ title = "Generalizing {Hindley-Milner} Type Inference
+ Algorithms",
+ author = "Bastiaan Heeren and Jurriaan Hage and Doaitse
+ Swierstra",
+ year = "2002",
+ institution = "University of Utrecht, Institute of Information and
+ Computing Science",
+ number = "UU-CS-2002-031",
+ URL = "http://archive.cs.uu.nl/pub/RUU/CS/techreps/CS-2002/2002-031.pdf",
+}
+
+@TechReport{heeren2002parametric,
+ title = "Parametric Type Inferencing for {Helium}",
+ author = "Bastiaan Heeren and Jurriaan Hage",
+ year = "2002",
+ institution = "University of Utrecht, Institute of Information and
+ Computing Science",
+ number = "UU-CS-2002-035",
+ URL = "http://archive.cs.uu.nl/pub/RUU/CS/techreps/CS-2002/2002-035.pdf",
+}
+
+@InBook{hehner-96,
+ author = "Eric C. R. Hehner",
+ booktitle = "A classical mind",
+ title = "Abstractions of Time",
+ publisher = prentice,
+ year = "1994",
+ pages = "191--210",
+ URL = "http://www.cs.toronto.edu/~hehner/AoT.pdf",
+}
+
+@Article{hehner-98,
+ author = "Eric C. R. Hehner",
+ title = "Formalization of Time and Space",
+ journal = fac,
+ year = "1998",
+ volume = "10",
+ pages = "290--206",
+ URL = "http://www.cs.toronto.edu/~hehner/FTS.pdf",
+}
+
+@TechReport{heintze-93,
+ author = "Nevin Heintze",
+ institution = "Carnegie Mellon University, School of Computer
+ Science",
+ title = "Set Based Analysis of {ML} Programs",
+ year = "1993",
+ number = "CMU-CS-93-193",
+ URL = "http://reports-archive.adm.cs.cmu.edu/anon/1993/CMU-CS-93-193.ps",
+}
+
+@InProceedings{heintze-mcallester-97,
+ author = "Nevin Heintze and David McAllester",
+ title = "Linear-Time Subtransitive Control Flow Analysis",
+ pages = "261--272",
+ booktitle = pldi,
+ year = "1997",
+ URL = "http://www.autoreason.com/PLDI97.ps",
+}
+
+@InProceedings{heintze-riecke-slam-98,
+ author = "Nevin Heintze and Jon G. Riecke",
+ title = "The {SL}am Calculus: Programming with Secrecy and
+ Integrity",
+ booktitle = popl,
+ year = "1998",
+ pages = "365--377",
+ URL = "http://cm.bell-labs.com/cm/cs/who/nch/slam.ps",
+}
+
+@InProceedings{heintze-tardieu-01,
+ author = "Nevin Heintze and Olivier Tardieu",
+ title = "Ultra-fast Aliasing Analysis using {CLA}: {A} Million
+ Lines of {C} Code in a Second",
+ pages = "254--263",
+ booktitle = pldi,
+ year = "2001",
+ URL = "http://cm.bell-labs.com/cm/cs/who/nch/pldi01-1m.ps",
+}
+
+@InProceedings{helsen-thiemann-00,
+ author = "Simon Helsen and Peter Thiemann",
+ title = "Syntactic Type Soundness for the Region Calculus",
+ booktitle = hoots,
+ pages = "1--19",
+ year = "2000",
+ volume = "41",
+ number = "3",
+ series = entcs,
+ URL = "http://www.swen.uwaterloo.ca/~shelsen/papers/helsen-thiemann-hoots-00.pdf",
+}
+
+@TechReport{henderson-modes-92,
+ author = "Fergus Henderson",
+ title = "Strong modes can change the world!",
+ institution = "Department of Computer Science, University of
+ Melbourne",
+ year = "1992",
+ number = "96/11",
+ URL = "http://www.cs.mu.oz.au/~fjh/papers/hons_thesis.ps.gz",
+}
+
+@InProceedings{hendriks-oostrom-03,
+ author = "Dimitri Hendriks and Vincent van Oostrom",
+ title = "Adbmal",
+ booktitle = cade,
+ pages = "136--150",
+ year = "2003",
+ volume = "2741",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.phil.uu.nl/~oostrom/publication/ps/adbmal_jfpsv.ps",
+}
+
+@InProceedings{henglein-91,
+ author = "Fritz Henglein",
+ booktitle = fpca,
+ title = "Efficient Type Inference for Higher-Order Binding-Time
+ Analysis",
+ year = "1991",
+ pages = "448--472",
+ series = lncs,
+ volume = "523",
+ publisher = springer,
+ URL = "ftp://ftp.diku.dk/pub/diku/users/henglein/binding-time-analysis.dvi.gz",
+}
+
+@Article{henglein-93,
+ author = "Fritz Henglein",
+ title = "Type Inference with Polymorphic Recursion",
+ journal = toplas,
+ year = "1993",
+ volume = "15",
+ number = "2",
+ pages = "253--289",
+ URL = "http://doi.acm.org/10.1145/169701.169692",
+}
+
+@InProceedings{henglein-breaking-97,
+ author = "Fritz Henglein",
+ title = "Breaking through the $n^3$ barrier: Faster object type
+ inference",
+ booktitle = fool,
+ year = "1997",
+}
+
+@Article{henglein-breaking-99,
+ author = "Fritz Henglein",
+ title = "Breaking through the $n^3$ barrier: Faster Object Type
+ Inference",
+ journal = "Theory and Practice of Object Systems",
+ year = "1999",
+ volume = "5",
+ number = "1",
+ pages = "57--72",
+ URL = "ftp://ftp.diku.dk/diku/semantics/papers/D-396.ps.gz",
+}
+
+@Article{henglein-paige-87,
+ author = "Robert Paige and Fritz Henglein",
+ title = "Mechanical translation of set theoretic problem
+ specifications into efficient {RAM} code -- {A} case
+ study",
+ journal = jsc,
+ volume = "4",
+ number = "2",
+ year = "1987",
+ pages = "207--232",
+ URL = "http://dx.doi.org/10.1016/S0747-7171(87)80066-4",
+}
+
+@PhdThesis{henglein-phd-89,
+ author = "Fritz Henglein",
+ school = "Rutgers University",
+ title = "Polymorphic Type Inference and Semi-Unification",
+ year = "1989",
+ URL = "ftp://ftp.diku.dk/diku/users/henglein/poly-typ-inf-and-semi-unif.ps.gz",
+}
+
+@InProceedings{henglein-rehof-97,
+ author = "Fritz Henglein and Jakob Rehof",
+ title = "The Complexity of Subtype Entailment for Simple
+ Types",
+ pages = "352--361",
+ booktitle = lics,
+ year = "1997",
+ URL = "http://research.microsoft.com/~rehof/lics97.ps",
+}
+
+@InProceedings{henglein-rehof-98,
+ author = "Fritz Henglein and Jakob Rehof",
+ title = "Constraint Automata and the Complexity of Recursive
+ Subtype Entailment",
+ booktitle = icalp,
+ year = "1998",
+ URL = "http://research.microsoft.com/~rehof/icalp98.ps",
+}
+
+@TechReport{hennessy-2000,
+ author = "Matthew Hennessy",
+ title = "The security picalculus and non-interference",
+ year = "2000",
+ institution = "University of Sussex",
+ number = "2000:05",
+ URL = "ftp://ftp.cogs.susx.ac.uk/pub/reports/compsci/cs052000.ps.Z",
+}
+
+@InProceedings{hennessy-riely-00,
+ author = "Matthew Hennessy and James Riely",
+ title = "Information Flow vs. Resource Access in the
+ Asynchronous Pi-Calculus",
+ booktitle = icalp,
+ series = lncs,
+ publisher = springer,
+ year = "2000",
+ URL = "http://www.depaul.edu/~jriely/papers/00icalp.ps.gz",
+}
+
+@InProceedings{hepburn-wright-01,
+ author = "Mark Hepburn and David Wright",
+ title = "Trust in the Pi-Calculus",
+ booktitle = ppdp,
+ year = "2001",
+}
+
+@Article{herlihy-schachte-sondergaard-07,
+ author = "Brian Herlihy and Peter Schachte and Harald
+ Søndergaard",
+ title = "Un-{Kleene} {Boolean} Equation Solving",
+ journal = ijfcs,
+ year = "2007",
+ volume = "18",
+ number = "2",
+ pages = "227--250",
+ URL = "http://dx.doi.org/10.1142/S0129054107004668",
+}
+
+@InProceedings{heule-13,
+ author = "Stefan Heule and K. Rustan M. Leino and Peter
+ M{\"u}ller and Alexander J. Summers",
+ title = "Abstract Read Permissions: Fractional Permissions
+ without the Fractions",
+ booktitle = vmcai,
+ year = "2013",
+ pages = "315--334",
+ publisher = springer,
+ series = lncs,
+ volume = "7737",
+ URL = "http://research.microsoft.com/en-us/um/people/leino/papers/krml225.pdf",
+}
+
+@InProceedings{higuchi-ohori-03,
+ author = "Tomoyuki Higuchi and Atsushi Ohori",
+ title = "A Static Type System for {JVM} Access Control",
+ booktitle = icfp,
+ pages = "227--237",
+ year = "2003",
+ URL = "http://doi.acm.org/10.1145/944726",
+}
+
+@InProceedings{hillerstrom-lindley-16,
+ author = "Daniel Hillerstr{\"{o}}m and Sam Lindley",
+ title = "Liberating effects with rows and handlers",
+ booktitle = "International Workshop on Type-Driven Development
+ (TyDe@ICFP)",
+ pages = "15--27",
+ year = "2016",
+ URL = "http://homepages.inf.ed.ac.uk/slindley/papers/links-effect.pdf",
+}
+
+@Article{hindley-69,
+ author = "J. Roger Hindley",
+ title = "The Principal Type-scheme of an Object in Combinatory
+ Logic",
+ journal = tams,
+ volume = "146",
+ pages = "29--60",
+ year = "1969",
+ URL = "http://dx.doi.org/10.2307/1995158",
+}
+
+@InCollection{hinze-03,
+ author = "Ralf Hinze",
+ editor = "Jeremy Gibbons and Oege de Moor",
+ booktitle = "The Fun of Programming",
+ title = "Fun with Phantom Types",
+ publisher = palgrave,
+ year = "2003",
+ pages = "245--262",
+ URL = "http://www.informatik.uni-bonn.de/~ralf/publications/With.pdf",
+}
+
+@TechReport{hinze-comparing-generic-06,
+ author = "Ralf Hinze and Johan Jeuring and Andres Löh",
+ year = "2006",
+ title = "Comparing approaches to generic programming in
+ {Haskell}",
+ number = "UU-CS-2006-022",
+ institution = "Department of Information and Computing Sciences,
+ Utrecht University",
+ URL = "http://www.cs.uu.nl/research/techreps/repo/CS-2006/2006-022.pdf",
+}
+
+@InProceedings{hinze-derivable-00,
+ author = "Ralf Hinze and Simon {Peyton Jones}",
+ title = "Derivable type classes",
+ booktitle = hw,
+ year = "2000",
+ URL = "https://www.microsoft.com/en-us/research/wp-content/uploads/2000/09/derive.pdf",
+}
+
+@Unpublished{hinze-paterson-05,
+ author = "Ralf Hinze and Ross Paterson",
+ title = "Derivation of a Typed Functional {LR} Parser",
+ note = "Unpublished",
+ year = "2005",
+ URL = "http://www.cs.ox.ac.uk/ralf.hinze/publications/TypedLR.pdf",
+}
+
+@Article{hinze-paterson-06,
+ title = "Finger trees: a simple general-purpose data
+ structure",
+ author = "Ralf Hinze and Ross Paterson",
+ journal = jfp,
+ year = "2006",
+ number = "2",
+ volume = "16",
+ pages = "197--217",
+ URL = "http://www.cs.ox.ac.uk/ralf.hinze/publications/FingerTrees.pdf",
+}
+
+@InProceedings{hirschowitz-cbv-04,
+ author = "Tom Hirschowitz and Xavier Leroy and J. B. Wells",
+ title = "Call-by-value mixin modules: Reduction semantics, side
+ effects, types",
+ booktitle = esop,
+ pages = "64--78",
+ year = "2004",
+ volume = "2986",
+ series = lncs,
+ publisher = springer,
+ URL = "http://gallium.inria.fr/~xleroy/publi/mixins-mm-esop2004.ps.gz",
+}
+
+@Article{hirschowitz-leroy-04,
+ author = "Tom Hirschowitz and Xavier Leroy",
+ title = "Mixin Modules in a Call-by-Value Setting",
+ journal = toplas,
+ year = "2004",
+ note = "To appear",
+ URL = "http://gallium.inria.fr/~hirschow/papers/toplas-cmsv.ps.gz",
+}
+
+@InProceedings{hoang-mitchell-lower-95,
+ author = "My Hoang and John C. Mitchell",
+ title = "Lower Bounds on Type Inference with Subtypes",
+ pages = "176--185",
+ booktitle = popl,
+ year = "1995",
+ URL = "http://doi.acm.org/10.1145/199448.199481",
+}
+
+@Article{hoare-61,
+ author = "C. A. R. Hoare",
+ title = "Algorithm 65: find",
+ journal = cacm,
+ volume = "4",
+ number = "7",
+ year = "1961",
+ pages = "321--322",
+ URL = "http://doi.acm.org/10.1145/366622.366647",
+}
+
+@Article{hoare-69,
+ author = "C. A. R. Hoare",
+ title = "An axiomatic basis for computer programming",
+ journal = cacm,
+ volume = "12",
+ number = "10",
+ year = "1969",
+ pages = "576--580",
+ URL = "http://doi.acm.org/10.1145/363235.363259",
+}
+
+@Article{hoare-71,
+ author = "C. A. R. Hoare",
+ title = "Proof of a program: {FIND}",
+ journal = cacm,
+ year = "1971",
+ volume = "14",
+ number = "1",
+ pages = "39--45",
+ URL = "http://doi.acm.org/10.1145/362452.362489",
+}
+
+@Article{hoare-data-72,
+ author = "C. A. R. Hoare",
+ title = "Proof of correctness of data representations",
+ journal = acta,
+ year = "1972",
+ volume = "4",
+ pages = "271--281",
+ URL = "http://dx.doi.org/10.1007/BF00289507",
+}
+
+@InProceedings{hobor-gherghina-11,
+ author = "Aquinas Hobor and Cristian Gherghina",
+ title = "Barriers in Concurrent Separation Logic",
+ booktitle = esop,
+ year = "2011",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.comp.nus.edu.sg/~hobor/Publications/barrier.pdf",
+}
+
+@InProceedings{hobor-indirection-10,
+ author = "Aquinas Hobor and Robert Dockins and Andrew W. Appel",
+ title = "A Theory of Indirection via Approximation",
+ booktitle = popl,
+ year = "2010",
+ URL = "http://www.comp.nus.edu.sg/~hobor/Publications/indirection.pdf",
+}
+
+@InProceedings{hobor-oracle-08,
+ author = "Aquinas Hobor and Andrew W. Appel and Francesco {Zappa
+ Nardelli}",
+ title = "Oracle Semantics for Concurrent Separation Logic",
+ booktitle = esop,
+ pages = "353--367",
+ year = "2008",
+ volume = "4960",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.cs.princeton.edu/~appel/papers/concurrent.pdf",
+}
+
+@Article{hoffmann-aehlig-hofmann-multivariate-12,
+ author = "Jan Hoffmann and Klaus Aehlig and Martin Hofmann",
+ title = "Multivariate amortized resource analysis",
+ journal = toplas,
+ volume = "34",
+ number = "3",
+ pages = "14:1--14:62",
+ year = "2012",
+ URL = "http://doi.acm.org/10.1145/2362389.2362393",
+}
+
+@InProceedings{hoffmann-aehlig-hofmann-raml-12,
+ author = "Jan Hoffmann and Klaus Aehlig and Martin Hofmann",
+ title = "Resource Aware {ML}",
+ booktitle = cav,
+ pages = "781--786",
+ year = "2012",
+ URL = "http://dx.doi.org/10.1007/978-3-642-31424-7_64",
+ series = lncs,
+ volume = "7358",
+ publisher = springer,
+}
+
+@InProceedings{hoffmann-das-weng-17,
+ author = "Jan Hoffmann and Ankush Das and Shu{-}Chun Weng",
+ title = "Towards automatic resource bound analysis for
+ {OCaml}",
+ booktitle = popl,
+ pages = "359--373",
+ year = "2017",
+ URL = "http://www.cs.cmu.edu/~janh/papers/HoffmannDW17.pdf",
+}
+
+@InProceedings{hoffmann-hofmann-10,
+ author = "Jan Hoffmann and Martin Hofmann",
+ title = "Amortized Resource Analysis with Polynomial
+ Potential",
+ booktitle = esop,
+ pages = "287--306",
+ year = "2010",
+ volume = "6012",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.cs.yale.edu/homes/hoffmann/papers/aapoly_conference.pdf",
+}
+
+@InProceedings{hoffmann-marmar-shao-13,
+ author = "Jan Hoffmann and Michael Marmar and Zhong Shao",
+ title = "Quantitative Reasoning for Proving Lock-Freedom",
+ booktitle = lics,
+ year = "2013",
+ pages = "124--133",
+ URL = "http://www.cs.cmu.edu/~janh/papers/lockfree2013.pdf",
+}
+
+@Article{hofmann-00,
+ author = "Martin Hofmann",
+ title = "A type system for bounded space and functional
+ in-place update",
+ journal = njc,
+ year = "2000",
+ volume = "7",
+ number = "4",
+ pages = "258--289",
+ URL = "http://www.tcs.informatik.uni-muenchen.de/~mhofmann/nordic.ps.gz",
+}
+
+@InProceedings{hofmann-jost-03,
+ author = "Martin Hofmann and Steffen Jost",
+ title = "Static prediction of heap space usage for first-order
+ functional programs",
+ booktitle = popl,
+ year = "2003",
+ pages = "185--197",
+ URL = "http://www2.tcs.ifi.lmu.de/~jost/research/POPL_2003_Jost_Hofmann.pdf",
+}
+
+@InProceedings{hofmann-moser-14,
+ author = "Martin Hofmann and Georg Moser",
+ title = "Amortised Resource Analysis and Typed Polynomial
+ Interpretations",
+ booktitle = tlca,
+ pages = "272--286",
+ year = "2014",
+ volume = "8560",
+ series = lncs,
+ publisher = springer,
+ URL = "http://arxiv.org/pdf/1402.1922.pdf",
+}
+
+@InProceedings{hofmann-pavlova-08,
+ author = "Martin Hofmann and Mariela Pavlova",
+ title = "Elimination of ghost variables in program logics",
+ booktitle = "Trustworthy Global Computing",
+ pages = "1--20",
+ year = "2008",
+ volume = "4912",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www-sop.inria.fr/everest/personnel/Mariela.Pavlova/ghost.pdf",
+}
+
+@Article{hofmann-pierce-94,
+ author = "Martin Hofmann and Benjamin Pierce",
+ title = "A Unifying Type-Theoretic Framework for Objects",
+ journal = jfp,
+ volume = "5",
+ number = "4",
+ pages = "593--635",
+ note = "Previous versions appeared in the Symposium on
+ Theoretical Aspects of Computer Science, 1994, (pages
+ 251--262) and, under the title ``An Abstract View of
+ Objects and Subtyping (Preliminary Report),'' as
+ University of Edinburgh, LFCS technical report
+ ECS-LFCS-92-226, 1992",
+ year = "1995",
+ URL = "http://www.cis.upenn.edu/~bcpierce/papers/abstroop.ps",
+}
+
+@InProceedings{hogg-91,
+ author = "John Hogg",
+ title = "Islands: Aliasing Protection in Object-Oriented
+ Languages",
+ booktitle = oopsla,
+ year = "1991",
+ pages = "271--285",
+ URL = "http://dx.doi.org/10.1145/118014.117975",
+}
+
+@InProceedings{honda-al-00,
+ author = "Kohei Honda and Vasco Vasconcelos and Nobuko Yoshida",
+ title = "Secure information flow as typed process behaviour",
+ booktitle = esop,
+ publisher = springer,
+ series = lncs,
+ volume = "1782",
+ pages = "180--199",
+ year = "2000",
+ URL = "ftp://ftp.dcs.qmw.ac.uk/lfp/kohei/siftp-esop00.ps.gz",
+}
+
+@TechReport{honda-al-00-long,
+ author = "Kohei Honda and Vasco Vasconcelos and Nobuko Yoshida",
+ title = "Secure information flow as typed process behaviour",
+ institution = "Queen Mary and Westfield College, University of
+ London",
+ year = "1999",
+ number = "QMW-DCS-1999-767",
+ URL = "ftp://ftp.dcs.qmw.ac.uk/lfp/kohei/siftp-qmwrep.ps.gz",
+}
+
+@InProceedings{honda-yoshida-02,
+ author = "Kohei Honda and Nobuko Yoshida",
+ title = "A Uniform Type Structure for Secure Information Flow",
+ booktitle = popl,
+ year = "2002",
+ pages = "81--92",
+ URL = "http://www.mcs.le.ac.uk/~nyoshida/paper/ifa_long.ps.gz",
+}
+
+@InProceedings{honda-yoshida-04,
+ author = "Kohei Honda and Nobuko Yoshida",
+ title = "A compositional logic for polymorphic higher-order
+ functions",
+ booktitle = ppdp,
+ year = "2004",
+ pages = "191--202",
+ URL = "http://www.dcs.qmul.ac.uk/~kohei/logics/polyrec.pdf.gz",
+}
+
+@InProceedings{honsell-01,
+ author = "Furio Honsell and Marino Miculan and Ivan Scagnetto",
+ title = "An axiomatic approach to metareasoning on nominal
+ algebras in {HOAS}",
+ booktitle = icalp,
+ pages = "963--978",
+ year = "2001",
+ volume = "2076",
+ series = lncs,
+ publisher = springer,
+ URL = "https://users.dimi.uniud.it/~marino.miculan/Papers/ICALP01.pdf",
+}
+
+@InCollection{hopcroft-minimizing-71,
+ author = "John~E. Hopcroft",
+ title = "An $n\log n$ algorithm for minimizing states in a
+ finite automaton",
+ booktitle = "Theory of Machines and Computations",
+ editor = "Z. Kohavi",
+ publisher = ap,
+ year = "1971",
+ pages = "189--196",
+}
+
+@Book{hopcroft-motwani-ullman-00,
+ author = "John E. Hopcroft and Rajeev Motwani and Jeffrey D.
+ Ullman",
+ title = "Introduction to Automata Theory, Languages, and
+ Computation",
+ publisher = aw,
+ year = "2000",
+ URL = "http://www-db.stanford.edu/~ullman/ialc.html",
+}
+
+@Article{hopcroft-ullman-73,
+ author = "John E. Hopcroft and Jeffrey D. Ullman",
+ title = "Set Merging Algorithms",
+ journal = siamjc,
+ volume = "2",
+ number = "4",
+ pages = "294--303",
+ year = "1973",
+ URL = "http://dx.doi.org/10.1137/0202024",
+}
+
+@InProceedings{horning-74,
+ author = "James J. Horning",
+ title = "What the Compiler Should Tell the User",
+ booktitle = cc,
+ year = "1974",
+ pages = "525--548",
+ volume = "21",
+ series = lncs,
+ publisher = springer,
+ URL = "http://dx.doi.org/10.1007/3540069585_64",
+}
+
+@Article{horspool-faster-90,
+ author = "R. Nigel Horspool and Michael Whitney",
+ title = "Even Faster {LR} Parsing",
+ journal = spe,
+ year = "1990",
+ volume = "20",
+ number = "6",
+ pages = "515--535",
+ URL = "http://www.cs.uvic.ca/~nigelh/Publications/fastparse.pdf",
+}
+
+@InProceedings{horwitz-95,
+ author = "Susan Horwitz and Thomas Reps and Mooly Sagiv",
+ title = "Demand interprocedural dataflow analysis",
+ booktitle = "ACM Symposium on the Foundations of Software
+ Engineering (FSE)",
+ year = "1995",
+ URL = "http://www.cs.wisc.edu/wpis/papers/fse95a.ps",
+}
+
+@Article{horwitz-demers-teitelbaum-87,
+ author = "Alan Demers and Susan Horwitz and Tim Teitelbaum",
+ title = "An efficient general algorithm for dataflow analysis",
+ journal = acta,
+ year = "1987",
+ volume = "24",
+ number = "6",
+ pages = "679--694",
+ URL = "http://dx.doi.org/10.1007/BF00282621",
+}
+
+@Article{hosoya-pierce-02,
+ author = "Haruo Hosoya and Benjamin C. Pierce",
+ title = "Regular expression pattern matching for {XML}",
+ journal = jfp,
+ volume = "13",
+ number = "6",
+ year = "2003",
+ pages = "961--1004",
+ URL = "http://dx.doi.org/10.1017/S0956796802004410",
+}
+
+@TechReport{howell-08,
+ author = "Rodney R. Howell",
+ title = "On Asymptotic Notation with Multiple Variables",
+ institution = "Kansas State University",
+ year = "2008",
+ number = "2007-4",
+ URL = "http://people.cs.ksu.edu/~rhowell/asymptotic.pdf",
+}
+
+@Misc{howell-book,
+ author = "Rodney R. Howell",
+ title = "Algorithms: {A} Top-Down Approach",
+ year = "2012",
+ note = "Draft",
+ URL = "http://people.cs.ksu.edu/~rhowell/algorithms-text/text/",
+}
+
+@Article{hru-76,
+ author = "Michael A. Harrison and Walter L. Ruzzo and Jeffrey D.
+ Ullman",
+ title = "Protection in Operating Systems",
+ journal = cacm,
+ year = "1976",
+ volume = "19",
+ number = "8",
+ pages = "461--471",
+ URL = "http://doi.acm.org/10.1145/360303.360333",
+}
+
+@InProceedings{hubert-marche-07,
+ author = "Thierry Hubert and Claude Marché",
+ title = "Separation Analysis for Deductive Verification",
+ booktitle = hav,
+ year = "2007",
+ URL = "http://www.lri.fr/~marche/hubert07hav.pdf",
+}
+
+@PhdThesis{huet-76,
+ author = "G{\'e}rard Huet",
+ title = "{R}{\'e}solution d'{\'e}quations dans des langages
+ d'ordre $1$, $2$, $\ldots$, $\omega$",
+ school = "Universit{\'e} Paris 7",
+ year = "1976",
+}
+
+@Article{huet-98,
+ author = "Gérard Huet",
+ title = "Regular {Böhm} Trees",
+ journal = mscs,
+ year = "1998",
+ volume = "8",
+ pages = "671--680",
+ URL = "http://yquem.inria.fr/~huet/PUBLIC/RBT2.pdf",
+}
+
+@Article{huet-zipper-97,
+ author = "G{\'e}rard Huet",
+ title = "The Zipper",
+ journal = jfp,
+ volume = "7",
+ number = "5",
+ year = "1997",
+ pages = "549--554",
+ URL = "http://yquem.inria.fr/~huet/PUBLIC/zip.pdf",
+}
+
+@InProceedings{huffman-urban-10,
+ author = "Brian Huffman and Christian Urban",
+ title = "A New Foundation for {Nominal Isabelle}",
+ booktitle = itp,
+ pages = "35--50",
+ year = "2010",
+ series = lncs,
+ volume = "6172",
+ publisher = springer,
+ URL = "http://nms.kcl.ac.uk/christian.urban/Publications/nominal-atoms.pdf",
+}
+
+@Article{hughes-arrows-00,
+ author = "John Hughes",
+ title = "Generalising monads to arrows",
+ journal = scp,
+ volume = "37",
+ number = "1--3",
+ year = "2000",
+ pages = "67--111",
+ URL = "http://www.cse.chalmers.se/~rjmh/Papers/arrows.pdf",
+}
+
+@Article{hughes-matters-89,
+ author = "John Hughes",
+ title = "Why Functional Programming Matters",
+ journal = cj,
+ volume = "32",
+ number = "2",
+ pages = "98--107",
+ year = "1989",
+ URL = "http://www.cse.chalmers.se/~rjmh/Papers/whyfp.pdf",
+}
+
+@InProceedings{hughes-pareto-sabry-96,
+ author = "John Hughes and Lars Pareto and Amr Sabry",
+ title = "Proving the correctness of reactive systems using
+ sized types",
+ booktitle = popl,
+ year = "1996",
+ pages = "410--423",
+ URL = "http://doi.acm.org/10.1145/237721.240882",
+}
+
+@Article{hutton-fold-99,
+ author = "Graham Hutton",
+ title = "A Tutorial on the Universality and Expressiveness of
+ Fold",
+ journal = jfp,
+ volume = "9",
+ number = "4",
+ pages = "355--372",
+ year = "1999",
+ URL = "http://www.cs.nott.ac.uk/~pszgmh/fold.pdf",
+}
+
+@Article{igarashi-kobayashi-00,
+ author = "Atsushi Igarashi and Naoki Kobayashi",
+ title = "Type Reconstruction for Linear $\pi$-Calculus with
+ {I}/{O} Subtyping",
+ journal = ic,
+ volume = "161",
+ pages = "1--44",
+ year = "2000",
+ URL = "http://www.sato.kuis.kyoto-u.ac.jp/~igarashi/papers/psgz/linear-pi.IC.ps.gz",
+}
+
+@InProceedings{ishtiaq-ohearn-01,
+ author = "Samin S. Ishtiaq and Peter W. O'Hearn",
+ title = "{BI} as an assertion language for mutable data
+ structures",
+ booktitle = popl,
+ year = "2001",
+ pages = "14--26",
+ URL = "http://www.cs.ucl.ac.uk/staff/p.ohearn/papers/bi-assertion-lan.pdf",
+}
+
+@InCollection{iwaco-03,
+ author = "Dave Clarke and Sophia Drossopoulou and James Noble",
+ title = "Aliasing, Confinement, and Ownership in
+ Object-Oriented Programming",
+ booktitle = "Object-Oriented Technology. {ECOOP 2003} Workshop
+ Reader",
+ year = "2004",
+ publisher = springer,
+ series = lncs,
+ volume = "3013",
+ pages = "197--207",
+ URL = "http://dx.doi.org/10.1007/978-3-540-25934-3_19",
+}
+
+@Manual{jacc,
+ title = "jacc: Just Another Compiler Compiler for {Java}",
+ author = "Mark P. Jones",
+ year = "2004",
+ URL = "http://web.cecs.pdx.edu/~mpj/jacc/jacc.pdf",
+}
+
+@InProceedings{jackson-vaziri-00,
+ author = "Daniel Jackson and Mandana Vaziri",
+ title = "Finding Bugs with a Constraint Solver",
+ booktitle = issta,
+ year = "2000",
+ URL = "http://sdg.csail.mit.edu/pubs/2000/issta00.pdf",
+}
+
+@InProceedings{jacobs-termination-15,
+ author = "Bart Jacobs and Dragan Bosnacki and Ruurd Kuipe",
+ title = "Modular Termination Verification",
+ booktitle = ecoop,
+ pages = "99--1023",
+ year = "2015",
+ series = lipics,
+ URL = "http://people.cs.kuleuven.be/~bart.jacobs/ecoop2015.pdf",
+}
+
+@InProceedings{jagannathan-wright-95,
+ author = "Suresh Jagannathan and Andrew Wright",
+ title = "Effective Flow Analysis for Avoiding Run-Time Checks",
+ year = "1995",
+ booktitle = sas,
+ publisher = springer,
+ series = lncs,
+ volume = "983",
+ URL = "http://www.cs.purdue.edu/homes/suresh/papers/sas95.ps.gz",
+}
+
+@PhdThesis{jansson-00,
+ author = "Patrik Jansson",
+ title = "Functional Polytypic Programming",
+ school = "Chalmers University of Technology",
+ year = "2000",
+ URL = "http://www.cse.chalmers.se/~patrikj/poly/polythesis/Jansson2000_PhD_thesis.pdf",
+}
+
+@Book{java,
+ author = "James Gosling and Bill Joy and Guy Steele and Gilad
+ Bracha",
+ title = "The {Java} Language Specification, Second Edition",
+ publisher = aw,
+ year = "2000",
+ URL = "http://java.sun.com/docs/books/jls/",
+}
+
+@Book{javasec,
+ author = "Li Gong and Gary Ellison and Mary Dageforde",
+ title = "Inside {Java 2} Platform Security, Second Edition",
+ publisher = aw,
+ year = "2003",
+ URL = "http://java.sun.com/docs/books/security/",
+}
+
+@Article{jay-04,
+ author = "C. Barry Jay",
+ title = "The Pattern Calculus",
+ journal = toplas,
+ volume = "26",
+ number = "6",
+ pages = "911--937",
+ year = "2004",
+ URL = "http://www-staff.it.uts.edu.au/~cbj/Publications/pattern_calculus.pdf",
+ alturl = "http://doi.acm.org/10.1145/1034774.1034775",
+}
+
+@Article{jeffery-03,
+ author = "Clinton L. Jeffery",
+ title = "Generating {LR} syntax error messages from examples",
+ journal = toplas,
+ volume = "25",
+ number = "5",
+ year = "2003",
+ pages = "631--640",
+ URL = "http://doi.acm.org/10.1145/937563.937566",
+}
+
+@InProceedings{jensen-13,
+ author = "Jonas Braband Jensen and Nick Benton and Andrew
+ Kennedy",
+ title = "High-level separation logic for low-level code",
+ booktitle = popl,
+ pages = "301--314",
+ year = "2013",
+ URL = "http://research.microsoft.com/en-us/um/people/nick/hlsl.pdf",
+}
+
+@InProceedings{jensen-98,
+ author = "Thomas Jensen",
+ title = "Inference of polymorphic and conditional strictness
+ properties",
+ booktitle = popl,
+ year = "1998",
+ pages = "209--221",
+ publisher = acmp,
+ URL = "http://www.irisa.fr/lande/jensen/papers/popl98.ps",
+}
+
+@InProceedings{jensen-al-99,
+ author = "Thomas Jensen and Daniel {Le Métayer} and Tommy
+ Thorn",
+ title = "Verifying security properties of control-flow graphs",
+ booktitle = sp,
+ pages = "89--105",
+ year = "1999",
+ URL = "http://www.irisa.fr/lande/jensen/papers/SP99.ps",
+}
+
+@InProceedings{jensen-birkedal-fictional-12,
+ author = "Jonas Braband Jensen and Lars Birkedal",
+ title = "Fictional Separation Logic",
+ booktitle = esop,
+ year = "2012",
+ pages = "377--396",
+ publisher = springer,
+ series = lncs,
+ volume = "7211",
+ URL = "http://cs.au.dk/~birke/papers/sharing-conf.pdf",
+}
+
+@InProceedings{jensen-ployette-ridoux-02,
+ title = "Iteration schemes for fixed point computation",
+ author = "Thomas Jensen and Florimond Ployette and Olivier
+ Ridoux",
+ year = "2002",
+ booktitle = fics,
+ pages = "69--76",
+ URL = "http://www.irisa.fr/lande/REQS/fics02.ps",
+}
+
+@InProceedings{jha-al-02,
+ author = "Somesh Jha and Jens Palsberg and Tian Zhao",
+ title = "Efficient Type Matching",
+ booktitle = fossacs,
+ pages = "187--204",
+ year = "2002",
+ publisher = springer,
+ series = lncs,
+ volume = "2303",
+ URL = "http://www.cs.ucla.edu/~palsberg/paper/fossacs02.pdf",
+}
+
+@InProceedings{jia-05,
+ author = "Limin Jia and Frances Spalding and David Walker and
+ Neal Glew",
+ title = "Certifying Compilation for a Language with Stack
+ Allocation",
+ booktitle = lics,
+ year = "2005",
+ URL = "http://www.cs.princeton.edu/~dpw/papers/stackcert-lics05.pdf",
+ pages = "407--416",
+}
+
+@InProceedings{jia-walker-06,
+ author = "Limin Jia and David Walker",
+ title = "{ILC}: {A} Foundation for Automated Reasoning About
+ Pointer Programs",
+ booktitle = esop,
+ year = "2006",
+ pages = "131--145",
+ publisher = springer,
+ series = lncs,
+ volume = "3924",
+ URL = "http://sip.cs.princeton.edu/pub/ilc-esop06.pdf",
+}
+
+@InProceedings{jim-00,
+ author = "Trevor Jim",
+ title = "A Polar Type System",
+ booktitle = itrs,
+ year = "2000",
+ volume = "8",
+ series = pi,
+ publisher = carleton,
+ URL = "http://www.cee.hw.ac.uk/~jbw/itrs/itrs00/papers/Jim:ITRS-2000.ps.gz",
+}
+
+@TechReport{jim-95,
+ author = "Trevor Jim",
+ title = "What are principal typings and what are they good
+ for?",
+ institution = "Massachusetts Institute of Technology",
+ year = "1995",
+ number = "MIT/LCS TM-532",
+ URL = "http://www.research.att.com/~trevor/papers/principal-typings.ps.gz",
+}
+
+@Unpublished{jim-palsberg-99,
+ author = "Trevor Jim and Jens Palsberg",
+ title = "Type inference in systems of recursive types with
+ subtyping",
+ year = "1999",
+ note = "Manuscript",
+ URL = "http://www.cs.ucla.edu/~palsberg/draft/jim-palsberg99.pdf",
+}
+
+@Manual{jml,
+ title = "{JML} Reference Manual",
+ author = "Gary T. Leavens and Erik Poll and Curtis Clifton and
+ Yoonsik Cheon and Clyde Ruby and David Cok and Peter
+ Müller and Joseph Kiniry and Patrice Chalin and Daniel
+ M. Zimmerman",
+ year = "2008",
+ URL = "http://www.jmlspecs.org/OldReleases/jmlrefman.pdf",
+}
+
+@Article{jml-05,
+ author = "Lilian Burdy and Yoonsik Cheon and David Cok and
+ Michael Ernst and Joe Kiniry and Gary T. Leavens and K.
+ Rustan M. Leino and Erik Poll",
+ title = "An overview of {JML} tools and applications",
+ journal = sttt,
+ year = "2005",
+ volume = "7",
+ number = "3",
+ pages = "212--232",
+ URL = "http://research.microsoft.com/en-us/um/people/leino/papers/jml-sttt.pdf",
+}
+
+@TechReport{johnson-75,
+ author = "Stephen C. Johnson",
+ title = "Yacc: Yet Another Compiler-Compiler",
+ institution = "Bell Laboratories",
+ year = "1975",
+ type = "Computing Science Technical Report",
+ number = "32",
+ URL = "http://dinosaur.compilertools.net/yacc/yacc.ps",
+}
+
+@InProceedings{johnson-walz-86,
+ author = "Gregory F. Johnson and Janet A. Walz",
+ title = "A maximum-flow approach to anomaly isolation in
+ unification-based incremental type inference",
+ booktitle = popl,
+ pages = "44--57",
+ year = "1986",
+}
+
+@InCollection{johnson-yacc-79,
+ author = "Steven C. Johnson",
+ title = "{Yacc}: Yet Another Compiler Compiler",
+ booktitle = "{UNIX} Programmer's Manual",
+ volume = "2",
+ publisher = "Holt, Rinehart, and Winston",
+ pages = "353--387",
+ year = "1979",
+ URL = "http://dinosaur.compilertools.net/",
+}
+
+@InCollection{johnsson-85,
+ author = "Thomas Johnsson",
+ editor = "Jean-Pierre Jouannaud",
+ title = "Lambda Lifting: Transforming Programs to Recursive
+ Equations",
+ booktitle = fpca,
+ series = lncs,
+ volume = "201",
+ pages = "190--203",
+ publisher = springer,
+ year = "1985",
+ URL = "http://dx.doi.org/10.1007/3-540-15975-4_37",
+}
+
+@InProceedings{jones-92,
+ author = "Mark P. Jones",
+ title = "A theory of qualified types",
+ booktitle = esop,
+ year = "1992",
+ volume = "582",
+ series = lncs,
+ publisher = springer,
+ URL = "http://web.cecs.pdx.edu/~mpj/pubs/esop92.html",
+}
+
+@Book{jones-94,
+ author = "Mark P. Jones",
+ title = "Qualified Types: Theory and Practice",
+ publisher = cup,
+ year = "1994",
+}
+
+@TechReport{jones-95,
+ author = "Mark P. Jones",
+ title = "From {Hindley-Milner} Types to First-Class
+ Structures",
+ institution = "Yale University",
+ year = "1995",
+ type = "Research Report",
+ number = "YALEU/DCS/RR-1075",
+ URL = "http://web.cecs.pdx.edu/~mpj/pubs/haskwork95.html",
+}
+
+@InProceedings{jones-96,
+ author = "Mark P. Jones",
+ title = "Using Parameterized Signatures to Express Modular
+ Structure",
+ booktitle = popl,
+ year = "1996",
+ URL = "http://web.cecs.pdx.edu/~mpj/pubs/paramsig.html",
+}
+
+@InProceedings{jones-dictionary-94,
+ author = "Mark P. Jones",
+ title = "Dictionary-free Overloading by Partial Evaluation",
+ booktitle = pepm,
+ year = "1994",
+ URL = "http://web.cecs.pdx.edu/~mpj/pubs/pepm94.ps",
+}
+
+@InProceedings{jones-peyton-jones-99,
+ author = "Mark P. Jones and Simon {Peyton Jones}",
+ title = "Lightweight Extensible Records for {Haskell}",
+ booktitle = hw,
+ year = "1999",
+ URL = "http://web.cecs.pdx.edu/~mpj/pubs/recpro.ps.gz",
+}
+
+@TechReport{jones-qualified-94,
+ author = "Mark P. Jones",
+ institution = "Yale University",
+ title = "Simplifying and Improving Qualified Types",
+ year = "1994",
+ number = "YALEU/DCS/RR-1040",
+ URL = "ftp://nebula.cs.yale.edu/pub/yale-fp/reports/RR-1040.ps.Z",
+}
+
+@InProceedings{jones-thih-99,
+ author = "Mark P. Jones",
+ title = "Typing {Haskell} in {Haskell}",
+ booktitle = hw,
+ year = "1999",
+ URL = "http://web.cecs.pdx.edu/~mpj/thih/",
+}
+
+@InProceedings{jorgensen-93,
+ author = "Niels Jørgensen",
+ title = "Chaotic Fixpoint Iteration Guided by Dynamic
+ Dependency",
+ booktitle = wsa,
+ year = "1993",
+ pages = "27--44",
+ series = lncs,
+ volume = "724",
+ publisher = springer,
+ URL = "http://webhotel2.ruc.dk/nielsj/research/publications/wsa93.ps",
+}
+
+@InProceedings{jost-hammond-loidl-hofmann-10,
+ author = "Steffen Jost and Kevin Hammond and Hans{-}Wolfgang
+ Loidl and Martin Hofmann",
+ title = "Static determination of quantitative resource usage
+ for higher-order programs",
+ booktitle = popl,
+ pages = "223--236",
+ year = "2010",
+ URL = "http://www2.tcs.ifi.lmu.de/~jost/research/POPL_2010__Higher-Order_AA__Jost_etAl.pdf",
+}
+
+@InProceedings{jost-loidl-hammond-scaife-hofmann-09,
+ author = "Steffen Jost and Hans{-}Wolfgang Loidl and Kevin
+ Hammond and Norman Scaife and Martin Hofmann",
+ title = "{"}Carbon Credits{"} for Resource-Bounded Computations
+ Using Amortised Analysis",
+ booktitle = fm,
+ pages = "354--369",
+ year = "2009",
+ series = lncs,
+ volume = "5850",
+ publisher = springer,
+ URL = "http://www2.tcs.ifi.lmu.de/~jost/research/FM09_AmortisedAnalysis__Jost_etAl.pdf",
+}
+
+@TechReport{jouannaud-kirchner-90,
+ author = "Jean-Pierre Jouannaud and Claude Kirchner",
+ title = "Solving equations in abstract algebras: a rule-based
+ survey of unification",
+ institution = "Université Paris-Sud",
+ number = "561",
+ year = "1990",
+}
+
+@InCollection{jouannaud-kirchner-91,
+ author = "Jean-Pierre Jouannaud and Claude Kirchner",
+ title = "Solving equations in abstract algebras: a rule-based
+ survey of unification",
+ booktitle = "Computational Logic. Essays in honor of Alan
+ Robinson",
+ publisher = mitp,
+ year = "1991",
+ editor = "Jean-Louis Lassez and Gordon Plotkin",
+ chapter = "8",
+ pages = "257--321",
+}
+
+@InProceedings{jourdan-leroy-pottier-12,
+ author = "Jacques-Henri Jourdan and François Pottier and Xavier
+ Leroy",
+ title = "Validating ${LR}(1)$ Parsers",
+ year = "2012",
+ booktitle = esop,
+ publisher = springer,
+ series = lncs,
+ volume = "7211",
+ pages = "397--416",
+ URL = "http://gallium.inria.fr/~fpottier/publis/jourdan-leroy-pottier-validating-parsers.pdf",
+}
+
+@InProceedings{jourdan-verasco-15,
+ author = "Jacques{-}Henri Jourdan and Vincent Laporte and
+ Sandrine Blazy and Xavier Leroy and David Pichardie",
+ title = "A Formally-Verified {C} Static Analyzer",
+ booktitle = popl,
+ pages = "247--259",
+ year = "2015",
+ URL = "http://gallium.inria.fr/~xleroy/publi/verasco-popl2015.pdf",
+}
+
+@InProceedings{jung-15,
+ author = "Ralf Jung and David Swasey and Filip Sieczkowski and
+ Kasper Svendsen and Aaron Turon and Lars Birkedal and
+ Derek Dreyer",
+ title = "Iris: Monoids and Invariants as an Orthogonal Basis
+ for Concurrent Reasoning",
+ booktitle = popl,
+ pages = "637--650",
+ year = "2015",
+ URL = "http://plv.mpi-sws.org/iris/paper.pdf",
+}
+
+@Article{kam-ullman-76,
+ author = "John B. Kam and Jeffrey D. Ullman",
+ title = "Global Data Flow Analysis and Iterative Algorithms",
+ journal = jacm,
+ year = "1976",
+ volume = "23",
+ number = "1",
+ pages = "158--171",
+ URL = "http://doi.acm.org/10.1145/321921.321938",
+}
+
+@Article{kam-ullman-77,
+ author = "John B. Kam and Jeffrey D. Ullman",
+ title = "Monotone Data Flow Analysis Frameworks",
+ journal = acta,
+ year = "1977",
+ volume = "7",
+ number = "3",
+ pages = "305--317",
+ URL = "http://dx.doi.org/10.1007/BF00290339",
+}
+
+@InProceedings{kammar-lindley-oury-13,
+ author = "Ohad Kammar and Sam Lindley and Nicolas Oury",
+ title = "Handlers in action",
+ booktitle = icfp,
+ pages = "145--158",
+ year = "2013",
+ URL = "http://homepages.inf.ed.ac.uk/slindley/papers/handlers.pdf",
+}
+
+@PhdThesis{kanig-10,
+ author = "Johannes Kanig",
+ title = "Specification and Proof of Higher-Order Programs",
+ school = "Université Paris-Sud",
+ year = "2010",
+ URL = "http://www.lri.fr/~kanig/files/thesis-kanig-15112010.pdf",
+}
+
+@Article{kantorowitz-laor-86,
+ author = "E. Kantorowitz and H. Laor",
+ title = "Automatic generation of useful syntax error messages",
+ journal = spe,
+ volume = "16",
+ number = "7",
+ publisher = "John Wiley \& Sons",
+ URL = "http://dx.doi.org/10.1002/spe.4380160703",
+ pages = "627--640",
+ year = "1986",
+}
+
+@InProceedings{kaplan-shafrir-tarjan-02,
+ author = "Haim Kaplan and Nira Shafrir and Robert E. Tarjan",
+ title = "Union-find with deletions",
+ booktitle = soda,
+ pages = "19--28",
+ year = "2002",
+ URL = "http://dl.acm.org/citation.cfm?id=545381.545384",
+}
+
+@Article{kaplan-tarjan-99,
+ author = "Haim Kaplan and Robert E. Tarjan",
+ title = "Purely functional, real-time deques with catenation",
+ journal = jacm,
+ volume = "46",
+ number = "5",
+ year = "1999",
+ pages = "577--603",
+ URL = "http://www.math.tau.ac.il/~haimk/bob.ps",
+}
+
+@Article{kapur-zhang-rrl,
+ author = "Deepak Kapur and Hantao Zhang",
+ title = "An overview of {Rewrite Rule Laboratory (RRL)}",
+ journal = "J. Comput. Appl. Math.",
+ year = "1995",
+ volume = "29",
+ number = "2",
+ pages = "91--114",
+ URL = "ftp://ftp.cs.albany.edu/pub/ipl/papers/overview.rrl.ps.gz",
+}
+
+@TechReport{kashiwagi-wise-91,
+ author = "Yugo Kashiwagi and David S. Wise",
+ title = "Graph Algorithms in a Lazy Functional Programming
+ Language",
+ institution = "Indiana University",
+ year = "1991",
+ type = "Technical Report",
+ number = "330",
+ URL = "http://www.cs.indiana.edu/pub/techreports/TR330.pdf",
+}
+
+@InProceedings{kassios-06,
+ author = "Ioannis T. Kassios",
+ title = "Dynamic Frames: Support for Framing, Dependencies and
+ Sharing Without Restrictions",
+ booktitle = fm,
+ year = "2006",
+ pages = "268--283",
+ publisher = springer,
+ series = lncs,
+ volume = "4085",
+ URL = "http://n.ethz.ch/~kassiosi/papers/fm06.pdf",
+}
+
+@PhdThesis{keinanen-06,
+ author = "Misa Keinänen",
+ title = "Techniques For Solving {Boolean} Equation Systems",
+ school = "Helsinki University of Technology",
+ year = "2006",
+ note = "Research Report HUT-TCS-A105",
+ URL = "http://www.tcs.hut.fi/Publications/bibdb/HUT-TCS-A105.pdf",
+}
+
+@Article{keisu-94,
+ author = "Torbjörn Keisu",
+ title = "Finite and Rational Tree Constraints",
+ journal = "Bulletin of the {IGPL}",
+ year = "1994",
+ volume = "2",
+ number = "2",
+ pages = "167--204",
+ URL = "http://www.dcs.kcl.ac.uk/journals/igpl/IGPL/V2-2/Keisu.ps.gz",
+}
+
+@PhdThesis{keisu-phd-94,
+ author = "Torbjörn Keisu",
+ title = "Tree Constraints",
+ school = "The Royal Institute of Technology (KTH)",
+ year = "1994",
+ URL = "ftp://ftp.sics.se/pub/ps/papers/torbjorn-keisu-thesis.ps.gz",
+}
+
+@InProceedings{kennedy-07,
+ author = "Andrew Kennedy",
+ title = "Compiling with continuations, continued",
+ booktitle = icfp,
+ year = "2007",
+ pages = "177--190",
+ URL = "http://research.microsoft.com/~akenn/sml/CompilingWithContinuationsContinued.pdf",
+}
+
+@InProceedings{kennedy-75,
+ author = "Ken W. Kennedy",
+ title = "Node listings applied to data flow analysis",
+ booktitle = popl,
+ year = "1975",
+ pages = "10--21",
+ URL = "http://doi.acm.org/10.1145/512976.512978",
+}
+
+@InProceedings{kennedy-94,
+ author = "Andrew Kennedy",
+ title = "Dimension Types",
+ booktitle = esop,
+ year = "1994",
+ volume = "788",
+ series = lncs,
+ publisher = springer,
+ URL = "http://research.microsoft.com/~akenn/units/DimensionTypes.pdf",
+}
+
+@TechReport{kennedy-96,
+ author = "Andrew Kennedy",
+ title = "Type Inference and Equational Theories",
+ institution = "École Polytechnique",
+ year = "1996",
+ number = "LIX/RR/96/09",
+}
+
+@InProceedings{kerber-91,
+ author = "Manfred Kerber",
+ title = "How to Prove Higher Order Theorems in First Order
+ Logic",
+ booktitle = ijcai,
+ year = "1991",
+ pages = "137--142",
+ URL = "ftp://ftp.cs.bham.ac.uk/pub/authors/M.Kerber/91-IJCAI.pdf",
+}
+
+@Book{kernighan-ritchie-88,
+ author = "Brian W. Kernighan and Dennis Ritchie",
+ title = "The {C} Programming Language, Second Edition",
+ publisher = prentice,
+ year = "1988",
+}
+
+@Unpublished{keuchel-schrijvers-inbound-15,
+ author = "Steven Keuchel and Tom Schrijvers",
+ title = "\textsc{InBound}: simple yet powerful specification of
+ syntax with binders",
+ note = "Unpublished",
+ year = "2015",
+ URL = "http://users.ugent.be/~skeuchel/publications/inbound.pdf",
+}
+
+@InProceedings{kfoury-ml-90,
+ author = "Assaf J. Kfoury and Jerzy Tiuryn and Pawel Urzyczyn",
+ title = "{ML} Typability is {DEXPTIME}-Complete",
+ booktitle = "Colloquium on Trees in Algebra and Programming",
+ publisher = springer,
+ series = lncs,
+ volume = "431",
+ pages = "206--220",
+ year = "1990",
+ URL = "http://dx.doi.org/10.1007/3-540-52590-4_50",
+}
+
+@Article{kfoury-recursion-93,
+ author = "A. J. Kfoury and J. Tiuryn and P. Urzyczyn",
+ title = "Type reconstruction in the presence of polymorphic
+ recursion",
+ journal = toplas,
+ volume = "15",
+ number = "2",
+ year = "1993",
+ pages = "290--311",
+ URL = "http://doi.acm.org/10.1145/169701.169687",
+}
+
+@Article{kfoury-wells-2004,
+ author = "Assaf J. Kfoury and J. B. Wells",
+ title = "Principality and Type Inference for Intersection Types
+ Using Expansion Variables",
+ journal = tcs,
+ volume = "311",
+ number = "1--3",
+ pages = "1--70",
+ year = "2004",
+ URL = "http://www.church-project.org/reports/Kfo+Wel:TCSB-2004-v311n1-3.html",
+}
+
+@Unpublished{kieburtz-02,
+ author = "Richard B. Kieburtz",
+ title = "${P}$-logic: Property verification for {Haskell}
+ programs",
+ note = "Draft",
+ year = "2002",
+ URL = "http://www.cse.ogi.edu/PacSoft/projects/programatica/plogic.pdf",
+}
+
+@InProceedings{kieburtz-98,
+ author = "Richard B. Kieburtz",
+ title = "Taming effects with monadic typing",
+ booktitle = icfp,
+ year = "1998",
+ pages = "51--62",
+ URL = "http://doi.acm.org/10.1145/289423.289428",
+}
+
+@InProceedings{kildall-73,
+ author = "Gary A. Kildall",
+ title = "A unified approach to global program optimization",
+ booktitle = popl,
+ year = "1973",
+ pages = "194--206",
+ URL = "http://doi.acm.org/10.1145/512927.512945",
+}
+
+@InProceedings{kim-yi-calcagno-06,
+ author = "Ik-Soon Kim and Kwangkeun Yi and Cristiano Calcagno",
+ title = "A polymorphic modal type system for {Lisp}-like
+ multi-staged languages",
+ booktitle = popl,
+ year = "2006",
+ pages = "257--268",
+ URL = "http://www.doc.ic.ac.uk/~ccris/ftp/06-popl-kiyicr.pdf",
+}
+
+@InProceedings{king-wadler-92,
+ author = "David King and Philip Wadler",
+ title = "Combining Monads",
+ booktitle = "Workshop on Functional Programming",
+ publisher = springer,
+ year = "1992",
+ URL = "http://homepages.inf.ed.ac.uk/wadler/papers/monadscomb/monadscomb.ps.gz",
+}
+
+@InProceedings{kiselyov-shan-07,
+ author = "Oleg Kiselyov and Chung{-}chieh Shan",
+ title = "A Substructural Type System for Delimited
+ Continuations",
+ booktitle = tlca,
+ pages = "223--239",
+ year = "2007",
+ series = lncs,
+ volume = "4583",
+ publisher = springer,
+ URL = "http://homes.soic.indiana.edu/ccshan/binding/context.pdf",
+}
+
+@Article{klein-seL4-2010,
+ author = "Gerwin Klein and June Andronick and Kevin Elphinstone
+ and Gernot Heiser and David Cock and Philip Derrin and
+ Dhammika Elkaduwe and Kai Engelhardt and Rafal Kolanski
+ and Michael Norrish and Thomas Sewell and Harvey Tuch
+ and Simon Winwood",
+ title = "{seL4}: formal verification of an operating-system
+ kernel",
+ journal = cacm,
+ volume = "53",
+ number = "6",
+ year = "2010",
+ pages = "107--115",
+ URL = "http://ertos.nicta.com.au/publications/papers/Klein_EHACDEEKNSTW_10.pdf",
+}
+
+@Article{klint-laemmel-verhoef-05,
+ author = "Paul Klint and Ralf L{\"a}mmel and Chris Verhoef",
+ title = "{Toward an engineering discipline for grammarware}",
+ journal = tosem,
+ volume = "14",
+ number = "3",
+ year = "2005",
+ pages = "331--380",
+ URL = "http://www.few.vu.nl/~x/gw/gw.pdf",
+}
+
+@InProceedings{kloos-majumdar-vafeiadis-15,
+ author = "Johannes Kloos and Rupak Majumdar and Viktor
+ Vafeiadis",
+ title = "Asynchronous Liquid Separation Types",
+ booktitle = ecoop,
+ pages = "396--420",
+ year = "2015",
+ URL = "https://www.mpi-sws.org/~viktor/papers/ecoop2015-alstypes.pdf",
+}
+
+@Article{kmp-77,
+ author = "James H. Morris and Donald E. Knuth and Vaughan R.
+ Pratt",
+ title = "Fast Pattern Matching in Strings",
+ journal = siamjc,
+ year = "1977",
+ volume = "6",
+ number = "2",
+ pages = "323--350",
+ URL = "http://locus.siam.org/fulltext/SICOMP/volume-06/0206024.pdf",
+}
+
+@Article{knight-89,
+ author = "Kevin Knight",
+ title = "Unification: a multidisciplinary survey",
+ journal = surveys,
+ year = "1989",
+ volume = "21",
+ number = "1",
+ pages = "93--124",
+ URL = "http://doi.acm.org/10.1145/62029.62030",
+}
+
+@Article{knuth-77,
+ author = "Donald E. Knuth",
+ title = "A Generalization of {Dijkstra}'s Algorithm",
+ journal = ipl,
+ year = "1977",
+ volume = "6",
+ number = "1",
+ pages = "1--5",
+}
+
+@Article{knuth-lr-65,
+ author = "Donald E. Knuth",
+ title = "On the translation of languages from left to right",
+ journal = "Information \& Control",
+ year = "1965",
+ volume = "8",
+ number = "6",
+ pages = "607--639",
+ URL = "http://www.sciencedirect.com/science/article/pii/S0019995865904262",
+}
+
+@InProceedings{kobayashi-implicit-00,
+ author = "Naoki Kobayashi and Shin Saito and Eijiro Sumii",
+ title = "An Implicitly-Typed Deadlock-Free Process Calculus",
+ booktitle = concur,
+ publisher = springer,
+ series = lncs,
+ volume = "1877",
+ year = "2000",
+ pages = "489--503",
+ URL = "http://www.yl.is.s.u-tokyo.ac.jp/members/koba/papers/deadlock-inference-concur.ps.gz",
+}
+
+@Article{kobayashi-linearity-99,
+ author = "Naoki Kobayashi and Benjamin C. Pierce and David N.
+ Turner",
+ title = "Linearity and the {Pi-Calculus}",
+ journal = toplas,
+ volume = "21",
+ number = "5",
+ pages = "914--947",
+ year = "1999",
+ URL = "http://doi.acm.org/10.1145/330249.330251",
+}
+
+@Article{kobayashi-partial-98,
+ author = "Naoki Kobayashi",
+ title = "A Partially Deadlock-Free Typed Process Calculus",
+ journal = toplas,
+ volume = "20",
+ number = "2",
+ pages = "436--482",
+ year = "1998",
+ URL = "http://doi.acm.org/10.1145/276393.278524",
+}
+
+@InProceedings{kobayashi-sumii-98,
+ author = "Eijiro Sumii and Naoki Kobayashi",
+ title = "A Generalized Deadlock-Free Process Calculus",
+ booktitle = hlcl,
+ year = "1998",
+ volume = "16",
+ series = entcs,
+ publisher = elsevier,
+ pages = "55--77",
+ URL = "http://www1.elsevier.com/gej-ng/31/29/23/40/26/39/tcs16.3.006.ps",
+}
+
+@InProceedings{kobayashi-useless-00,
+ author = "Naoki Kobayashi",
+ title = "Type-based useless variable elimination",
+ pages = "84--93",
+ booktitle = pepm,
+ year = "2000",
+ URL = "http://www.yl.is.s.u-tokyo.ac.jp/members/koba/papers/PEPM00.ps.gz",
+}
+
+@Article{koda-ruskey-93,
+ author = "Yasunori Koda and Frank Ruskey",
+ title = "A {Gray} Code for the Ideals of a Forest Poset",
+ journal = "Journal of Algorithms",
+ volume = "15",
+ number = "2",
+ year = "1993",
+ pages = "324--340",
+ URL = "http://www.cs.uvic.ca/~ruskey/Publications/ForestIdeals.ps",
+}
+
+@InProceedings{kohlbecker-hygienic-86,
+ author = "Eugene Kohlbecker and Daniel P. Friedman and Matthias
+ Felleisen and Bruce Duba",
+ title = "Hygienic macro expansion",
+ booktitle = lfp,
+ year = "1986",
+ pages = "151--161",
+ URL = "http://doi.acm.org/10.1145/319838.319859",
+}
+
+@InProceedings{kohlbecker-wand-87,
+ author = "Eugene E. Kohlbecker and Mitchell Wand",
+ title = "Macro-by-example: Deriving syntactic transformations
+ from their specifications",
+ booktitle = popl,
+ year = "1987",
+ pages = "77--84",
+ URL = "http://doi.acm.org/10.1145/41625.41632",
+}
+
+@InProceedings{konat-13,
+ author = "Gabri{\"e}l Konat and Lennart Kats and Guido Wachsmuth
+ and Eelco Visser",
+ title = "Declarative Name Binding and Scope Rules",
+ booktitle = sle,
+ year = "2013",
+ publisher = springer,
+ volume = "7745",
+ series = lncs,
+ pages = "311--331",
+ URL = "http://swerl.tudelft.nl/twiki/pub/Main/TechnicalReports/TUD-SERG-2012-015.pdf",
+}
+
+@InProceedings{koprowski-binsztok-10,
+ author = "Adam Koprowski and Henri Binsztok",
+ title = "{TRX}: {A} Formally Verified Parser Interpreter",
+ booktitle = esop,
+ year = "2010",
+ pages = "345--365",
+ publisher = "Springer",
+ series = lncs,
+ volume = "6012",
+ URL = "http://adam-koprowski.net/papers/trx-ESOP-10.pdf",
+}
+
+@Article{koprowski-binsztok-11,
+ author = "Adam Koprowski and Henri Binsztok",
+ title = "{TRX}: {A} Formally Verified Parser Interpreter",
+ journal = lmcs,
+ year = "2011",
+ volume = "7",
+ number = "2",
+ URL = "http://arxiv.org/pdf/1105.2576",
+}
+
+@InProceedings{koved-al-02,
+ author = "Larry Koved and Marco Pistoia and Aaron Kershenbaum",
+ title = "Access rights analysis for {Java}",
+ pages = "359--372",
+ booktitle = oopsla,
+ year = "2002",
+ URL = "http://www.research.ibm.com/javasec/OOPSLA2002preprint.pdf",
+}
+
+@Book{kozen-91,
+ author = "Dexter C. Kozen",
+ title = "The design and analysis of algorithms",
+ year = "1992",
+ series = "Texts and Monographs in Computer Science",
+ publisher = springer,
+ URL = "http://www.cs.cornell.edu/~kozen/papers/daa.pdf",
+}
+
+@Article{kozen-palsberg-schwartzbach-95,
+ author = "Dexter Kozen and Jens Palsberg and Michael I.
+ Schwartzbach",
+ title = "Efficient Recursive Subtyping",
+ journal = mscs,
+ volume = "5",
+ number = "1",
+ pages = "113--125",
+ year = "1995",
+ URL = "http://www.cs.ucla.edu/~palsberg/paper/mscs95-kps.pdf",
+}
+
+@InProceedings{krebbers-17,
+ author = "Robert Krebbers and Amin Timany and Lars Birkedal",
+ title = "Interactive proofs in higher-order concurrent
+ separation logic",
+ booktitle = popl,
+ year = "2017",
+ URL = "http://cs.au.dk/~birke/papers/ipm-conf.pdf",
+}
+
+@InProceedings{krishnamurthi-99,
+ author = "Shriram Krishnamurthi and Matthias Felleisen and Bruce
+ F. Duba",
+ title = "From Macros to Reusable Generative Programming",
+ booktitle = gcse,
+ pages = "105--120",
+ year = "1999",
+ volume = "1799",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.cs.brown.edu/~sk/Publications/Papers/Published/kfd-macro-to-gen-prog/paper.ps",
+}
+
+@PhdThesis{krishnaswami-12,
+ author = "Neelakantan R. Krishnaswami",
+ title = "Verifying Higher-Order Imperative Programs with
+ Higher-Order Separation Logic",
+ school = "School of Computer Science, Carnegie Mellon
+ University",
+ year = "2012",
+ URL = "http://www.cs.cmu.edu/~neelk/thesis.pdf",
+}
+
+@InProceedings{krishnaswami-design-patterns-09,
+ author = "Neelakantan R. Krishnaswami and Jonathan Aldrich and
+ Lars {Bir\-ke\-dal} and Kasper Svendsen and Alexandre
+ Buisse",
+ title = "Design Patterns in Separation Logic",
+ booktitle = tldi,
+ pages = "105--116",
+ year = "2009",
+ URL = "http://www.cs.cmu.edu/~neelk/design-patterns-tldi09.pdf",
+}
+
+@InProceedings{krishnaswami-sharing-12,
+ author = "Neelakantan R. Krishnaswami and Aaron Turon and Derek
+ Dreyer and Deepak Garg",
+ title = "Superficially substructural types",
+ booktitle = icfp,
+ year = "2012",
+ pages = "41--54",
+ URL = "http://www.mpi-sws.org/~neelk/icfp12-superficial-krishnaswami-turon-dreyer-garg.pdf",
+}
+
+@Book{kroening-strichman-08,
+ author = "Daniel Kroening and Ofer Strichman",
+ title = "Decision procedures -- An algorithmic point of view",
+ publisher = springer,
+ year = "2008",
+ URL = "http://www.decision-procedures.org/",
+}
+
+@InProceedings{kuan-07,
+ author = "George Kuan and David MacQueen",
+ title = "Efficient type inference using ranked type variables",
+ booktitle = ml,
+ year = "2007",
+ pages = "3--14",
+ URL = "http://people.cs.uchicago.edu/~gkuan/pubs/ml07-km.pdf",
+}
+
+@InProceedings{kuncak-rinard-03,
+ author = "Viktor Kuncak and Martin Rinard",
+ title = "Structural Subtyping of Non-Recursive Types is
+ Decidable",
+ booktitle = lics,
+ year = "2003",
+ URL = "http://www.cag.lcs.mit.edu/~rinard/paper/lics03.pdf",
+}
+
+@TechReport{kuncak-rinard-tr-03,
+ author = "Viktor Kuncak and Martin Rinard",
+ title = "On the Theory of Structural Subtyping",
+ institution = "MIT Laboratory for Computer Science",
+ year = "2003",
+ number = "879",
+ URL = "http://www.mit.edu/people/vkuncak/papers/TheoryStructuralSubtyping.ps",
+}
+
+@InProceedings{laemmel-00,
+ author = "Ralf Lämmel and Joost Visser and Jan Kort",
+ title = "Dealing with Large Bananas",
+ pages = "46--59",
+ booktitle = wgp,
+ year = "2000",
+ URL = "http://homepages.cwi.nl/~ralf/wgp00.ps",
+}
+
+@Unpublished{laemmel-scrap-05,
+ author = "Ralf Lämmel and Simon {Peyton Jones}",
+ title = "Scrap your boilerplate with class: extensible generic
+ functions",
+ note = "Submitted",
+ year = "2005",
+ URL = "http://research.microsoft.com/Users/simonpj/papers/hmap/gmap3.ps",
+}
+
+@InProceedings{lai-user-99,
+ author = "Charlie Lai and Li Gong and Larry Koved and Anthony J.
+ Nadalin and Roland Schemers",
+ title = "User Authentication and Authorization in the {Java}
+ Platform",
+ booktitle = acsac,
+ pages = "285--290",
+ year = "1999",
+ URL = "http://www.acsac.org/1999/papers/thu-b-1500-lai.pdf",
+}
+
+@InProceedings{lammich-13,
+ author = "Peter Lammich",
+ title = "Automatic Data Refinement",
+ booktitle = itp,
+ pages = "84--99",
+ year = "2013",
+ volume = "7998",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www21.in.tum.de/~lammich/pub/autoref.pdf",
+}
+
+@InProceedings{lammich-14,
+ author = "Peter Lammich",
+ title = "Verified Efficient Implementation of {Gabow}'s
+ Strongly Connected Component Algorithm",
+ booktitle = itp,
+ year = "2014",
+ pages = "325--340",
+ publisher = springer,
+ series = lncs,
+ volume = "8558",
+ URL = "http://www21.in.tum.de/~lammich/pub/gabow_scc.pdf",
+}
+
+@InProceedings{lammich-15,
+ author = "Peter Lammich",
+ title = "Refinement to {Imperative/HOL}",
+ booktitle = itp,
+ pages = "253--269",
+ year = "2015",
+ series = lncs,
+ volume = "9236",
+ publisher = springer,
+ URL = "https://www21.in.tum.de/~lammich/pub/itp15_sepref.pdf",
+}
+
+@InProceedings{lammich-16,
+ author = "Peter Lammich",
+ title = "Refinement Based Verification of Imperative Data
+ Structures",
+ booktitle = cpp,
+ year = "2016",
+ pages = "27--36",
+ URL = "https://www21.in.tum.de/~lammich/pub/cpp2016_impds.pdf",
+}
+
+@InProceedings{lammich-lochbihler-10,
+ author = "Peter Lammich and Andreas Lochbihler",
+ title = "The {Isabelle} Collections Framework",
+ booktitle = itp,
+ pages = "339--354",
+ year = "2010",
+ series = lncs,
+ volume = "6172",
+ publisher = springer,
+ URL = "http://cs.uni-muenster.de/sev/publications/itp10.pdf",
+}
+
+@Article{lammich-meis-12,
+ author = "Peter Lammich and Rene Meis",
+ title = "A Separation Logic Framework for {Imperative HOL}",
+ journal = "Archive of Formal Proofs",
+ year = "2012",
+ URL = "http://afp.sourceforge.net/entries/Separation_Logic_Imperative_HOL.shtml",
+}
+
+@Article{lampson-73,
+ author = "Butler W. Lampson",
+ title = "A Note on the Confinement Problem",
+ journal = cacm,
+ volume = "16",
+ number = "10",
+ pages = "613--615",
+ year = "1973",
+ URL = "http://research.microsoft.com/lampson/11-Confinement/WebPage.html",
+}
+
+@Article{landin-64,
+ author = "Peter J. Landin",
+ title = "The Mechanical Evaluation of Expressions",
+ journal = cj,
+ volume = "6",
+ number = "4",
+ year = "1964",
+ pages = "308--320",
+}
+
+@Article{landin-65,
+ author = "Peter J. Landin",
+ title = "Correspondence between {ALGOL} 60 and {Church's}
+ Lambda-notation: part {I}",
+ journal = cacm,
+ volume = "8",
+ number = "2",
+ year = "1965",
+ pages = "89--101",
+ URL = "http://doi.acm.org/10.1145/363744.363749",
+}
+
+@PhdThesis{larus-89,
+ author = "James Richard Larus",
+ title = "Restructuring Symbolic Programs for Concurrent
+ Execution on Multiprocessors",
+ school = "EECS Department, University of California, Berkeley",
+ year = "1989",
+ note = "Technical Report UCB/CSD-89-502",
+ URL = "http://www.eecs.berkeley.edu/Pubs/TechRpts/1989/CSD-89-502.pdf",
+}
+
+@InProceedings{lassen-06,
+ author = "Soren B. Lassen",
+ title = "Head Normal Form Bisimulation for Pairs and the
+ $\lambda\mu$-Calculus",
+ booktitle = lics,
+ year = "2006",
+ pages = "297--306",
+ URL = "http://www.blassen.dk/soren/papers/2006lics.pdf",
+}
+
+@InProceedings{lassen-99,
+ author = "Soren B. Lassen",
+ title = "Bisimulation in untyped lambda calculus: {Böhm} trees
+ and bisimulation up to context",
+ booktitle = mfps,
+ pages = "346--374",
+ year = "1999",
+ volume = "20",
+ series = entcs,
+ publisher = elsevier,
+ URL = "http://www.blassen.dk/soren/papers/1999mfps15.ps",
+}
+
+@InCollection{lassez-al-88,
+ author = "Jean-Louis Lassez and Michael J. Maher and Kim G.
+ Marriott",
+ editor = "Jack Minker",
+ booktitle = "Foundations of Deductive Databases and Logic
+ Programming",
+ title = "Unification Revisited",
+ chapter = "15",
+ publisher = "Morgan Kaufmann",
+ year = "1988",
+ pages = "587--625",
+}
+
+@Article{lassez-nguyen-sonenberg-82,
+ author = "Jean-Louis Lassez and V. L. Nguyen and Liz Sonenberg",
+ title = "Fixed point theorems and semantics: a folk tale",
+ journal = ipl,
+ year = "1982",
+ volume = "14",
+ number = "3",
+ pages = "112--116",
+ URL = "http://dx.doi.org/10.1016/0020-0190(82)90065-5",
+}
+
+@InProceedings{laufer-odersky-92,
+ author = "Martin Odersky and Konstantin Läufer",
+ title = "An Extension of {ML} with First-Class Abstract Types",
+ year = "1992",
+ booktitle = mlapp,
+ pages = "78--91",
+ URL = "http://www.cs.luc.edu/laufer/papers/ml92.pdf",
+}
+
+@Article{laufer-odersky-94,
+ author = "Konstantin L{\"a}ufer and Martin Odersky",
+ title = "Polymorphic Type Inference and Abstract Data Types",
+ journal = toplas,
+ year = "1994",
+ pages = "1411--1430",
+ volume = "16",
+ number = "5",
+ URL = "http://www.cs.luc.edu/laufer/papers/toplas94.pdf",
+}
+
+@Article{launchbury-peyton-jones-95,
+ author = "John Launchbury and Simon {Peyton Jones}",
+ title = "State in {Haskell}",
+ journal = "{LISP} and Symbolic Computation",
+ publisher = springer,
+ pages = "293--341",
+ year = "1995",
+ volume = "8",
+ number = "4",
+ URL = "http://dx.doi.org/10.1007/BF01018827",
+}
+
+@InProceedings{laviron-chang-rival-10,
+ author = "Vincent Laviron and Bor-Yuh Evan Chang and Xavier
+ Rival",
+ title = "Separating Shape Graphs",
+ booktitle = esop,
+ year = "2010",
+ pages = "387--406",
+ publisher = springer,
+ series = lncs,
+ volume = "6012",
+ URL = "http://xisa.cs.colorado.edu/papers/esop10-sepshapegraph.pdf",
+}
+
+@TechReport{le-charlier-van-hentenryck-92,
+ author = "Baudouin {Le Charlier} and Pascal {Van Hentenryck}",
+ title = "A Universal Top-Down Fixpoint Algorithm",
+ institution = "Brown University",
+ year = "1992",
+ type = "Technical Report",
+ number = "CS-92-25",
+ URL = "ftp://ftp.cs.brown.edu/pub/techreports/92/cs92-25.ps.gz",
+}
+
+@Article{le-metayer-88,
+ author = "Daniel {Le Métayer}",
+ title = "{ACE:} An Automatic Complexity Evaluator",
+ journal = toplas,
+ volume = "10",
+ number = "2",
+ pages = "248--266",
+ year = "1988",
+ URL = "http://doi.acm.org/10.1145/42190.42347",
+}
+
+@Article{league-02,
+ author = "Christopher League and Zhong Shao and Valery
+ Trifonov",
+ title = "Type-Preserving Compilation of {Featherweight}
+ {Java}",
+ journal = toplas,
+ year = "2002",
+ volume = "24",
+ number = "2",
+ pages = "112--152",
+ URL = "http://flint.cs.yale.edu/flint/publications/fj-toplas.html",
+}
+
+@InProceedings{league-03,
+ author = "Christopher League and Zhong Shao and Valery
+ Trifonov",
+ title = "Precision in Practice: a Type-Preserving {Java}
+ Compiler",
+ booktitle = cc,
+ pages = "106--120",
+ year = "2003",
+ volume = "2622",
+ series = lncs,
+ publisher = springer,
+ URL = "http://flint.cs.yale.edu/flint/publications/piptr.html",
+}
+
+@InProceedings{league-99,
+ author = "Christopher League and Zhong Shao and Valery
+ Trifonov",
+ title = "Representing {Java} Classes in a Typed Intermediate
+ Language",
+ booktitle = icfp,
+ pages = "183--196",
+ year = "1999",
+ URL = "http://flint.cs.yale.edu/flint/publications/javaflint2.html",
+}
+
+@InProceedings{leavens-baker-99,
+ author = "Gary T. Leavens and Albert L. Baker",
+ title = "Enhancing the Pre- and Postcondition Technique for
+ More Expressive Specifications",
+ booktitle = fm,
+ volume = "1709",
+ series = lncs,
+ year = "1999",
+ pages = "1087--1106",
+ publisher = springer,
+ URL = "http://dx.doi.org/10.1007/3-540-48118-4_8",
+}
+
+@InProceedings{lebotlan-remy-03,
+ author = "Didier {Le Botlan} and Didier R{\'e}my",
+ title = "{MLF}: Raising {ML} to the power of System ${F}$",
+ booktitle = icfp,
+ pages = "27--38",
+ year = "2003",
+ URL = "http://gallium.inria.fr/~remy/work/mlf/icfp.pdf",
+}
+
+@InProceedings{lebresne-08,
+ author = "Sylvain Lebresne",
+ title = "A System ${F}$ with Call-by-Name Exceptions",
+ booktitle = icalp,
+ year = "2008",
+ pages = "323--335",
+ publisher = springer,
+ series = lncs,
+ volume = "5126",
+ URL = "http://www.pps.jussieu.fr/~lebresne/papers/SystemFWithExceptions.pdf",
+}
+
+@Article{lee-yi-98,
+ author = "Oukseh Lee and Kwangkeun Yi",
+ title = "Proofs about a folklore let-polymorphic type inference
+ algorithm",
+ journal = toplas,
+ volume = "20",
+ number = "4",
+ year = "1998",
+ pages = "707--723",
+ URL = "http://doi.acm.org/10.1145/291891.291892",
+}
+
+@InProceedings{lefessant-maranget-01,
+ author = "Fabrice {Le Fessant} and Luc Maranget",
+ title = "Optimizing Pattern Matching",
+ booktitle = icfp,
+ year = "2001",
+ URL = "http://gallium.inria.fr/~maranget/papers/opt-pat.ps.gz",
+}
+
+@TechReport{leijen-algebraic-effects-16,
+ author = "Daan Leijen",
+ title = "Algebraic Effects for Functional Programming",
+ institution = "Microsoft Research",
+ number = "MSR-TR-2016-29",
+ year = "2016",
+ URL = "https://www.microsoft.com/en-us/research/publication/algebraic-effects-for-functional-programming/",
+}
+
+@Article{leino-05,
+ author = "K. Rustan M. Leino",
+ title = "Efficient Weakest Preconditions",
+ journal = ipl,
+ year = "2005",
+ volume = "93",
+ number = "6",
+ pages = "281--288",
+ URL = "http://research.microsoft.com/pubs/70052/tr-2004-34.pdf",
+}
+
+@InProceedings{leino-mueller-chalice-09,
+ author = "K. Rustan M. Leino and Peter M{\"u}ller",
+ title = "A Basis for Verifying Multi-threaded Programs",
+ booktitle = esop,
+ year = "2009",
+ pages = "378--393",
+ series = lncs,
+ volume = "5502",
+ publisher = springer,
+ URL = "http://research.microsoft.com/en-us/um/people/leino/papers/krml191.pdf",
+}
+
+@InProceedings{leino-mueller-smans-09,
+ author = "K. Rustan M. Leino and Peter Müller and Jan Smans",
+ title = "Verification of Concurrent Programs with {Chalice}",
+ booktitle = fosad,
+ year = "2009",
+ pages = "195--222",
+ publisher = springer,
+ series = lncs,
+ volume = "5705",
+ URL = "http://research.microsoft.com/en-us/um/people/leino/papers/krml197.pdf",
+}
+
+@InProceedings{leino-mueller-smans-10,
+ author = "K. Rustan M. Leino and Peter Müller and Jan Smans",
+ title = "Deadlock-Free Channels and Locks",
+ booktitle = esop,
+ year = "2010",
+ pages = "407--426",
+ publisher = springer,
+ series = lncs,
+ volume = "6012",
+ URL = "http://research.microsoft.com/en-us/um/people/leino/papers/krml200ext.pdf",
+}
+
+@Article{leino-nelson-02,
+ author = "K. Rustan M. Leino and Greg Nelson",
+ title = "Data abstraction and information hiding",
+ journal = toplas,
+ volume = "24",
+ number = "5",
+ year = "2002",
+ pages = "491--553",
+ URL = "http://research.microsoft.com/~leino/papers/krml71.pdf",
+}
+
+@InProceedings{leino-schulte-07,
+ author = "K. Rustan M. Leino and Wolfram Schulte",
+ title = "Using History Invariants to Verify Observers",
+ booktitle = esop,
+ year = "2007",
+ pages = "80--94",
+ publisher = springer,
+ series = lncs,
+ volume = "4421",
+ URL = "http://research.microsoft.com/en-us/um/people/leino/papers/krml166.pdf",
+}
+
+@PhdThesis{leroy-92,
+ author = "Xavier Leroy",
+ title = "Typage polymorphe d'un langage algorithmique",
+ school = "Université Paris 7",
+ year = "1992",
+ pages = "196",
+ URL = "http://gallium.inria.fr/~xleroy/publi/these-doctorat.ps.gz",
+}
+
+@InProceedings{leroy-compcert-06,
+ author = "Xavier Leroy",
+ title = "Formal certification of a compiler back-end or:
+ programming a compiler with a proof assistant",
+ booktitle = popl,
+ year = "2006",
+ pages = "42--54",
+ URL = "http://gallium.inria.fr/~xleroy/publi/compiler-certif.pdf",
+}
+
+@TechReport{leroy-phd-92,
+ author = "Xavier Leroy",
+ title = "Polymorphic typing of an algorithmic language",
+ institution = "INRIA",
+ year = "1992",
+ type = "Research Report",
+ number = "1778",
+ URL = "http://gallium.inria.fr/~xleroy/publi/phd-thesis.ps.gz",
+}
+
+@MastersThesis{lescuyer-06,
+ author = "Stéphane Lescuyer",
+ title = "Codage de la logique du premier ordre polymorphe
+ multi-sortée dans la logique sans sortes",
+ school = "Master Parisien de Recherche en Informatique",
+ year = "2006",
+ URL = "http://www.seas.upenn.edu/~lescuyer/pdf/RapportDEA.pdf",
+}
+
+@Article{lescuyer-11,
+ author = "St{\'{e}}phane Lescuyer",
+ title = "First-Class Containers in {Coq}",
+ journal = "Studia Informatica Universalis",
+ volume = "9",
+ number = "1",
+ pages = "87--127",
+ year = "2011",
+ URL = "http://studia.complexica.net/Art/RI090103.pdf",
+}
+
+@PhdThesis{letouzey-04,
+ author = "Pierre Letouzey",
+ title = "Programmation fonctionnelle certifiée -- l'extraction
+ de programmes dans l'assistant {Coq}",
+ school = "Université Paris 11",
+ year = "2004",
+ URL = "http://www.lri.fr/~letouzey/download/these_letouzey.ps.gz",
+}
+
+@InProceedings{levy-02,
+ author = "Paul Blain Levy",
+ title = "Possible World Semantics for General Storage in
+ Call-By-Value",
+ booktitle = csl,
+ series = lncs,
+ volume = "2471",
+ publisher = springer,
+ year = "2002",
+ URL = "http://www.cs.bham.ac.uk/~pbl/papers/storagecbv.ps",
+}
+
+@InProceedings{lewis-al-00,
+ author = "Jeffrey Lewis and Mark Shields and Erik Meijer and
+ John Launchbury",
+ title = "Implicit Parameters: Dynamic Scoping with Static
+ Types",
+ booktitle = popl,
+ year = "2000",
+ pages = "108--118",
+ URL = "http://www.cse.ogi.edu/~mbs/pub/implicit_parameters/implicit.ps",
+}
+
+@InProceedings{ley-wild-nanevski-subjective-13,
+ author = "Ruy Ley-Wild and Aleksandar Nanevski",
+ title = "Subjective auxiliary state for coarse-grained
+ concurrency",
+ booktitle = popl,
+ year = "2013",
+ pages = "561--574",
+ URL = "http://software.imdea.org/~aleks/papers/concur/scsl4.pdf",
+}
+
+@InProceedings{lgph-08,
+ author = "Johan Jeuring and Sean Leather and Jos{\'{e}} Pedro
+ Magalh{\~{a}}es and Alexey Rodriguez Yakushev",
+ title = "Libraries for Generic Programming in {Haskell}",
+ booktitle = afp,
+ pages = "165--229",
+ year = "2008",
+ series = lncs,
+ volume = "5832",
+ publisher = springer,
+ URL = "http://dreixel.net/research/pdf/lgph.pdf",
+}
+
+@InProceedings{licata-harper-09,
+ author = "Daniel R. Licata and Robert Harper",
+ title = "A universe of binding and computation",
+ booktitle = icfp,
+ year = "2009",
+ pages = "123--134",
+ URL = "http://www.cs.cmu.edu/~drl/pubs/lh09unibind/lh09unibind.pdf",
+}
+
+@InProceedings{licata-zeilberger-harper-08,
+ author = "Daniel R. Licata and Noam Zeilberger and Robert
+ Harper",
+ title = "Focusing on Binding and Computation",
+ booktitle = lics,
+ year = "2008",
+ pages = "241--252",
+ URL = "http://www.cs.cmu.edu/~rwh/papers/focusing/paper.pdf",
+}
+
+@TechReport{licata-zeilberger-harper-08-tr,
+ author = "Daniel R. Licata and Noam Zeilberger and Robert
+ Harper",
+ title = "Focusing on Binding and Computation",
+ institution = "Carnegie Mellon University",
+ year = "2008",
+ number = "CMU-CS-08-101",
+ URL = "http://www.cs.cmu.edu/~noam/research/lzh08focbind-tr.pdf",
+}
+
+@InProceedings{lindley-mcbride-mclaughlin-17,
+ author = "Sam Lindley and Conor McBride and Craig McLaughlin",
+ title = "Do Be Do Be Do",
+ booktitle = popl,
+ year = "2017",
+ URL = "http://homepages.inf.ed.ac.uk/slindley/papers/frankly-draft-july2016.pdf",
+}
+
+@Book{liskov-guttag-01,
+ author = "Barbara Liskov and John V. Guttag",
+ title = "Program Development in {Java} -- Abstraction,
+ Specification, and Object-Oriented Design",
+ year = "2001",
+ publisher = aw,
+ URL = "http://dl.acm.org/citation.cfm?id=556707",
+}
+
+@Article{liskov-wing-94,
+ author = "Barbara Liskov and Jeannette M. Wing",
+ title = "A Behavioral Notion of Subtyping",
+ journal = toplas,
+ volume = "16",
+ number = "6",
+ year = "1994",
+ pages = "1811--1841",
+ URL = "http://www.cs.cmu.edu/~wing/publications/LiskovWing94.pdf",
+}
+
+@InProceedings{liu-smolka-98,
+ author = "Xinxin Liu and Scott A. Smolka",
+ title = "Simple Linear-Time Algorithms for Minimal Fixed
+ Points",
+ booktitle = icalp,
+ year = "1998",
+ pages = "53--66",
+ series = lncs,
+ volume = "1443",
+ publisher = springer,
+ URL = "http://dx.doi.org/10.1007/BFb0055040",
+}
+
+@TechReport{lngen-10,
+ author = "Brian Aydemir and Stephanie Weirich",
+ title = "{LNgen}: Tool Support for Locally Nameless
+ Representations",
+ institution = "University of Pennsylvania Department of Computer and
+ Information Science",
+ year = "2010",
+ type = "Technical Report",
+ number = "MS-CIS-10-24",
+ URL = "http://repository.upenn.edu/cis_reports/933/",
+}
+
+@InProceedings{lochbihler-13,
+ author = "Andreas Lochbihler",
+ title = "Light-weight containers for {Isabelle}: efficient,
+ extensible, nestable",
+ booktitle = itp,
+ pages = "116--132",
+ year = "2013",
+ series = lncs,
+ volume = "7998",
+ publisher = springer,
+ URL = "https://pp.ipd.kit.edu/uploads/publikationen/lochbihler13itp.pdf",
+}
+
+@InProceedings{longley-99,
+ author = "John Longley",
+ title = "When is a Functional Program Not a Functional
+ Program?",
+ booktitle = icfp,
+ year = "1999",
+ pages = "1--7",
+ URL = "http://doi.acm.org/10.1145/317636.317775",
+}
+
+@InProceedings{longley-pollack-04,
+ author = "John Longley and Randy Pollack",
+ title = "Reasoning About {CBV} Functional Programs in
+ {Isabelle/HOL}",
+ booktitle = tphol,
+ year = "2004",
+ pages = "201--216",
+ URL = "http://homepages.inf.ed.ac.uk/rpollack/export/LongleyPollack04.pdf",
+ publisher = springer,
+ series = lncs,
+ volume = "3223",
+}
+
+@InProceedings{lucassen-gifford-88,
+ author = "John M. Lucassen and David K. Gifford",
+ title = "Polymorphic effect systems",
+ booktitle = popl,
+ year = "1988",
+ pages = "47--57",
+ URL = "http://pag.lcs.mit.edu/reading-group/lucassen88effects.pdf",
+}
+
+@InProceedings{mackenzie-wolverson-03,
+ author = "Kenneth MacKenzie and Nicholas Wolverson",
+ title = "{Camelot} and {Grail}: resource-aware functional
+ programming for the {JVM}",
+ booktitle = tfp,
+ pages = "29--46",
+ year = "2003",
+ volume = "4",
+ URL = "http://groups.inf.ed.ac.uk/mrg/publications/mrg/camelot.ps",
+}
+
+@Article{macqueen-plotkin-sethi-86,
+ author = "David B. MacQueen and Gordon D. Plotkin and Ravi
+ Sethi",
+ title = "An Ideal Model for Recursive Polymorphic Types",
+ journal = "Information and Control",
+ volume = "71",
+ number = "1--2",
+ year = "1986",
+ pages = "95--130",
+}
+
+@PhdThesis{mader-97,
+ school = "Technische Universität München",
+ author = "Angelika Mader",
+ title = "Verification of Modal Properties Using {Boolean}
+ Equation Systems",
+ year = "1997",
+ URL = "http://eprints.eemcs.utwente.nl/1078/02/diss.pdf",
+}
+
+@InProceedings{madhavan-kulal-kuncak-17,
+ author = "Ravichandhran Madhavan and Sumith Kulal and Viktor
+ Kuncak",
+ title = "Contract-based resource verification for higher-order
+ functions with memoization",
+ booktitle = popl,
+ pages = "330--343",
+ year = "2017",
+ URL = "http://lara.epfl.ch/~kandhada/orb-popl17.pdf",
+}
+
+@InProceedings{maeda-11,
+ author = "Toshiyuki Maeda and Haruki Sato and Akinori Yonezawa",
+ title = "Extended Alias Type System using Separating
+ Implication",
+ booktitle = tldi,
+ year = "2011",
+ pages = "29--42",
+ URL = "http://dx.doi.org/10.1145/1929553.1929559",
+}
+
+@InProceedings{maher-88,
+ author = "Michael J. Maher",
+ title = "Complete Axiomatizations of the Algebras of Finite,
+ Rational and Infinite Trees",
+ booktitle = lics,
+ pages = "348--357",
+ year = "1988",
+}
+
+@InProceedings{mairson-90,
+ author = "Harry G. Mairson",
+ title = "Deciding {ML} typability is complete for deterministic
+ exponential time",
+ booktitle = popl,
+ year = "1990",
+ pages = "382--401",
+ URL = "http://doi.acm.org/10.1145/96709.96748",
+}
+
+@InCollection{mairson-kanellakis-mitchell-91,
+ author = "Harry G. Mairson and Paris C. Kanellakis and John C.
+ Mitchell",
+ title = "Unification and {ML} type reconstruction",
+ booktitle = "Computational Logic: Essays in Honor of Alan
+ Robinson",
+ publisher = mitp,
+ year = "1991",
+ editor = "J.-L. Lassez and G. Plotkin",
+ pages = "444--478",
+}
+
+@Article{marche-krakatoa-04,
+ author = "Claude Marché and Christine Paulin-Mohring and Xavier
+ Urbain",
+ title = "The {Krakatoa} tool for certification of
+ {Java}/{JavaCard} programs annotated in {JML}",
+ journal = jlap,
+ year = "2004",
+ volume = "58",
+ number = "1--2",
+ pages = "89--106",
+ URL = "http://www3.ensiie.fr/~urbain/textes/jlap.ps.gz",
+}
+
+@Article{maric-09,
+ author = "Filip Mari\'c",
+ title = "Formalization and Implementation of Modern {SAT}
+ Solvers",
+ journal = jar,
+ year = "2009",
+ volume = "43",
+ pages = "81--119",
+ URL = "http://poincare.matf.bg.ac.rs/~filip//phd/sat-tutorial.pdf",
+}
+
+@Unpublished{maric-10,
+ author = "Filip Mari\'c",
+ title = "Formal Verification of a Modern {SAT} Solver",
+ note = "Unpublished",
+ year = "2010",
+ URL = "http://poincare.matf.bg.ac.rs/~filip//phd/sat-verification-shallow.pdf",
+}
+
+@InProceedings{marlow-wadler-erlang-97,
+ title = "A Practical Subtyping System for {Erlang}",
+ author = "Simon Marlow and Philip Wadler",
+ pages = "136--149",
+ booktitle = icfp,
+ year = "1997",
+}
+
+@TechReport{marriott-odersky-boolean-94,
+ author = "Kim Marriott and Martin Odersky",
+ title = "Negative {Boolean} Constraints",
+ institution = "Monash University",
+ year = "1994",
+ number = "94/203",
+ URL = "http://lampwww.epfl.ch/~odersky/papers/negative-tr.ps.gz",
+}
+
+@Article{martelli-montanari-82,
+ author = "Alberto Martelli and Ugo Montanari",
+ title = "An Efficient Unification Algorithm",
+ journal = toplas,
+ volume = "4",
+ number = "2",
+ pages = "258--282",
+ year = "1982",
+ URL = "http://doi.acm.org/10.1145/357162.357169",
+}
+
+@Article{mateescu-sighireanu-03,
+ author = "Radu Mateescu and Mihaela Sighireanu",
+ title = "Efficient on-the-fly model-checking for regular
+ alternation-free mu-calculus",
+ journal = scp,
+ volume = "46",
+ number = "3",
+ year = "2003",
+ pages = "255--281",
+ URL = "ftp://ftp.inrialpes.fr/pub/vasy/publications/cadp/Mateescu-Sighireanu-03.pdf",
+}
+
+@TechReport{mauny-pottier-93,
+ author = "Michel Mauny and François Pottier",
+ title = "An implementation of {Caml Light} with existential
+ types",
+ number = "2183",
+ institution = "INRIA",
+ year = "1993",
+ URL = "http://gallium.inria.fr/~fpottier/publis/rapport-maitrise.ps.gz",
+}
+
+@InProceedings{mazurak-10,
+ author = "Karl Mazurak and Jianzhou Zhao and Steve Zdancewic",
+ title = "Lightweight linear types in system ${F}^\circ$",
+ booktitle = tldi,
+ year = "2010",
+ pages = "77--88",
+ URL = "http://www.cis.upenn.edu/~stevez/papers/MZZ10.pdf",
+}
+
+@InProceedings{mcadam-98,
+ title = "{On the Unification of Substitutions in Type
+ Inference}",
+ author = "Bruce J. McAdam",
+ publisher = springer,
+ booktitle = ifl,
+ series = lncs,
+ volume = "1595",
+ year = "1998",
+ pages = "139--154",
+ URL = "http://www.scms.rgu.ac.uk/staff/bjm/doc/IFL_98.ps",
+}
+
+@Article{mcallester-02,
+ author = "David McAllester",
+ title = "On the Complexity Analysis of Static Analyses",
+ year = "2002",
+ pages = "512--537",
+ journal = jacm,
+ volume = "49",
+ number = "4",
+ URL = "http://doi.acm.org/10.1145/581771.581774",
+}
+
+@InProceedings{mcallester-03,
+ author = "David McAllester",
+ title = "A Logical Algorithm for {ML} Type Inference",
+ booktitle = rta,
+ year = "2003",
+ pages = "436--451",
+ series = lncs,
+ publisher = springer,
+ volume = "2706",
+ URL = "http://ttic.uchicago.edu/~dmcallester/rta03.ps",
+}
+
+@Unpublished{mcbride-derivative,
+ author = "Conor McBride",
+ title = "The Derivative of a Regular Type is its Type of
+ One-Hole Contexts",
+ note = "Unpublished",
+ URL = "http://strictlypositive.org/diff.pdf",
+}
+
+@InProceedings{mcbride-mckinna-04,
+ author = "Conor McBride and James McKinna",
+ title = "{I} am not a number: {I} am a free variable",
+ booktitle = hw,
+ year = "2004",
+ URL = "http://www.cs.ru.nl/~james/RESEARCH/haskell2004.pdf",
+}
+
+@Article{mcbride-paterson-08,
+ author = "Conor McBride and Ross Paterson",
+ title = "Applicative Programming with Effects",
+ journal = jfp,
+ year = "2008",
+ volume = "18",
+ number = "1",
+ pages = "1--13",
+ URL = "http://www.soi.city.ac.uk/~ross/papers/Applicative.pdf",
+}
+
+@Article{mcbride-unif-03,
+ author = "Conor McBride",
+ title = "First-order unification by structural recursion",
+ journal = jfp,
+ volume = "13",
+ number = "6",
+ year = "2003",
+ pages = "1061--1075",
+ URL = "http://strictlypositive.org/unify.ps.gz",
+}
+
+@InProceedings{mccarthy-16,
+ author = "Jay A. McCarthy and Burke Fetscher and Max S. New and
+ Daniel Feltey and Robert Bruce Findler",
+ title = "A {Coq} Library for Internal Verification of
+ Running-Times",
+ booktitle = flops,
+ pages = "144--162",
+ year = "2016",
+ series = lncs,
+ volume = "9613",
+ publisher = springer,
+ URL = "https://www.eecs.northwestern.edu/~robby/pubs/papers/flops2016-mfnff.pdf",
+}
+
+@InProceedings{mckinna-pollack-93,
+ author = "James McKinna and Randy Pollack",
+ title = "Pure Type Systems Formalized",
+ booktitle = tlca,
+ year = "1993",
+ pages = "289--305",
+ publisher = springer,
+ series = lncs,
+ number = "664",
+ URL = "http://www.dcs.ed.ac.uk/home/rap/export/formalPTS.ps.gz",
+}
+
+@Article{mckinna-pollack-99,
+ author = "James McKinna and Randy Pollack",
+ title = "Some Lambda Calculus and Type Theory Formalized",
+ journal = jar,
+ year = "1999",
+ volume = "23",
+ number = "3--4",
+ pages = "373--409",
+}
+
+@InCollection{mclean-94,
+ author = "John {McLean}",
+ title = "Security Models",
+ year = "1994",
+ booktitle = "Encyclopedia of Software Engineering",
+ editor = "John Marciniak",
+ publisher = "John Wiley \& Sons",
+ URL = "http://chacs.nrl.navy.mil/publications/CHACS/1994/1994mclean-ency.ps",
+}
+
+@InProceedings{mclean-composition-94,
+ author = "John {McLean}",
+ title = "A General Theory of Composition for Trace Sets Closed
+ Under Selective Interleaving Functions",
+ year = "1994",
+ booktitle = sp,
+ URL = "http://chacs.nrl.navy.mil/publications/CHACS/1994/1994mclean-sp.ps",
+}
+
+@InProceedings{meadows-94,
+ author = "Catherine Meadows",
+ title = "Formal Verification of Cryptographic Protocols: {A}
+ Survey",
+ booktitle = "Advances in Cryptology -- {ASIA\-CRYPT}'94",
+ year = "1995",
+ publisher = springer,
+ series = lncs,
+ volume = "917",
+ pages = "133--150",
+ URL = "http://chacs.nrl.navy.mil/publications/CHACS/1995/1995meadows-asiacrypt94.ps",
+}
+
+@Article{mehta-nipkow-05,
+ author = "Farhad Mehta and Tobias Nipkow",
+ title = "Proving pointer programs in higher-order logic",
+ journal = ic,
+ volume = "199",
+ number = "1--2",
+ year = "2005",
+ pages = "200--227",
+ URL = "http://www4.informatik.tu-muenchen.de/~nipkow/pubs/ic05.ps.gz",
+}
+
+@Article{melham-hol-93,
+ author = "Thomas F. Melham",
+ title = "The {HOL} Logic Extended with Quantification over Type
+ Variables",
+ journal = fmsd,
+ year = "1993",
+ volume = "3",
+ number = "1--2",
+ pages = "7--24",
+ URL = "http://web.comlab.ox.ac.uk/oucl/work/tom.melham/pub/Melham-1994-HLE.pdf",
+}
+
+}
+
+@Article{melski-reps-00,
+ author = "David Melski and Thomas Reps",
+ title = "Interconvertibility of a class of set constraints and
+ context-free language reachability",
+ journal = tcs,
+ year = "2000",
+ volume = "248",
+ number = "1--2",
+ URL = "http://www.cs.wisc.edu/wpis/papers/tcs_submission98r2.ps",
+}
+
+@Misc{menhir,
+ author = "François Pottier and Yann Régis-Gianas",
+ title = "The {Menhir} parser generator",
+ note = "\url{http://gallium.inria.fr/~fpottier/menhir/}",
+}
+
+@Manual{merr,
+ title = "{Merr} User's Guide",
+ author = "Clinton L. Jeffery",
+ year = "2002",
+ URL = "http://unicon.sourceforge.net/merr/merrguid.pdf",
+}
+
+@InProceedings{merz-00,
+ author = "Stephan Merz",
+ title = "Model Checking: {A} Tutorial Overview",
+ booktitle = "Fourth Summer School on Modeling and Verification of
+ Parallel Processes",
+ pages = "3--38",
+ publisher = springer,
+ series = lncs,
+ volume = "2067",
+ year = "2001",
+ URL = "http://www.loria.fr/~merz/papers/mc-tutorial.pdf",
+}
+
+@InProceedings{merz-08,
+ author = "Stephan Merz",
+ editor = "N. Navet and S. Merz",
+ booktitle = "Modeling and Verification of Real-Time Systems:
+ Formalisms and Software Tools",
+ title = "An Introduction to Model Checking",
+ publisher = "ISTE Publishing",
+ year = "2008",
+ pages = "77--109",
+ URL = "http://www.loria.fr/~merz/papers/mc-iste2008.pdf",
+}
+
+@InProceedings{miller-00,
+ author = "Dale Miller",
+ title = "Abstract Syntax for Variable Binders: An Overview",
+ booktitle = "Computational Logic",
+ pages = "239--253",
+ year = "2000",
+ series = lncs,
+ volume = "1861",
+ publisher = springer,
+ URL = "http://www.lix.polytechnique.fr/~dale/papers/cl2000.pdf",
+}
+
+@InProceedings{miller-90,
+ author = "Dale Miller",
+ title = "An Extension to {ML} to Handle Bound Variables in Data
+ Structures",
+ booktitle = "Logical Frameworks BRA Workshop",
+ year = "1990",
+ URL = "http://www.lix.polytechnique.fr/Labo/Dale.Miller/papers/mll.pdf",
+}
+
+@Article{miller-92,
+ author = "Dale Miller",
+ title = "Unification Under a Mixed Prefix",
+ journal = jsc,
+ volume = "14",
+ number = "4",
+ year = "1992",
+ pages = "321--358",
+ URL = "http://www.lix.polytechnique.fr/~dale/papers/jsc92.pdf",
+}
+
+@Article{millstein-chambers-02,
+ author = "Todd Millstein and Craig Chambers",
+ title = "Modular statically typed multimethods",
+ journal = ic,
+ year = "2002",
+ volume = "175",
+ number = "1",
+ pages = "76--118",
+ URL = "http://www.cs.ucla.edu/~todd/research/iandc.ps",
+}
+
+@InProceedings{millstein-chambers-99,
+ author = "Todd Millstein and Craig Chambers",
+ title = "Modular statically typed multimethods",
+ booktitle = ecoop,
+ pages = "279--303",
+ year = "1999",
+ volume = "1628",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.cs.ucla.edu/~todd/research/ecoop99.ps",
+}
+
+@Article{milner-78,
+ title = "A Theory of Type Polymorphism in Programming",
+ author = "Robin Milner",
+ pages = "348--375",
+ journal = "Journal of Computer and System Sciences",
+ year = "1978",
+ volume = "17",
+ number = "3",
+ URL = "http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.67.5276",
+}
+
+@TechReport{milner-91,
+ author = "Robin Milner",
+ institution = "Laboratory for Foundations of Computer Science,
+ Department of Computer Science, University of
+ Edinburgh",
+ number = "{ECS--LFCS--91--180}",
+ title = "The Polyadic $\pi$-Calculus: a Tutorial",
+ year = "1991",
+ URL = "ftp://ftp.cl.cam.ac.uk/users/rm135/ppi.ps.Z",
+}
+
+@InProceedings{milner-lcf-72,
+ author = "Robin Milner",
+ title = "Implementation and applications of {Scott's} logic for
+ computable functions",
+ booktitle = "Proceedings of the {ACM} conference on proving
+ assertions about programs",
+ year = "1972",
+ pages = "1--6",
+ URL = "http://doi.acm.org/10.1145/800235.807067",
+}
+
+@TechReport{milner-lcf-tr-72,
+ author = "Robin Milner",
+ title = "Logic for Computable Functions -- Description of a
+ Machine Implementation",
+ institution = "Stanford University, Department of Computer Science",
+ year = "1972",
+ number = "CS-TR-72-288",
+ URL = "ftp://reports.stanford.edu/pub/cstr/reports/cs/tr/72/288/CS-TR-72-288.pdf",
+}
+
+@TechReport{milner-lcf-tr-73,
+ author = "Robin Milner",
+ title = "Models of {LCF}",
+ institution = "Stanford University, Department of Computer Science",
+ year = "1973",
+ number = "CS-TR-73-332",
+ URL = "ftp://reports.stanford.edu/pub/cstr/reports/cs/tr/73/332/CS-TR-73-332.pdf",
+}
+
+@TechReport{milner-parrow-walker-89b,
+ author = "Robin Milner and Joachim Parrow and David Walker",
+ title = "A Calculus of Mobile Processes, part 2",
+ institution = "Laboratory for Foundations of Computer Science, School
+ of Informatics at the University of Edinburgh",
+ year = "1989",
+ number = "ECS-LFCS-89-86",
+ URL = "http://www.lfcs.inf.ed.ac.uk/reports/89/ECS-LFCS-89-86/ECS-LFCS-89-86.ps",
+}
+
+@InProceedings{milner-sangiorgi-92,
+ title = "Barbed Bisimulation",
+ author = "Robin Milner and Davide Sangiorgi",
+ booktitle = icalp,
+ year = "1992",
+ series = lncs,
+ volume = "623",
+ publisher = springer,
+ pages = "685--695",
+ URL = "ftp://ftp-sop.inria.fr/meije/theorie-par/davides/bn.ps.gz",
+}
+
+@InProceedings{minamide-98,
+ author = "Yasuhiko Minamide",
+ title = "A functional representation of data structures with a
+ hole",
+ booktitle = popl,
+ year = "1998",
+ pages = "75--84",
+ URL = "http://www.score.cs.tsukuba.ac.jp/~minamide/papers/hole.popl98.pdf",
+}
+
+@InProceedings{minamide-al-96,
+ author = "Yasuhiko Minamide and Greg Morrisett and Robert
+ Harper",
+ title = "Typed closure conversion",
+ booktitle = popl,
+ year = "1996",
+ pages = "271--283",
+ URL = "http://www.cs.cornell.edu/Info/People/jgm/papers/closure-summary.ps",
+}
+
+@InProceedings{minamide-okuma-03,
+ author = "Yasuhiko Minamide and Koji Okuma",
+ title = "Verifying {CPS} transformations in {Isabelle/HOL}",
+ booktitle = merlin,
+ year = "2003",
+ URL = "http://doi.acm.org/10.1145/976571.976576",
+}
+
+@Article{mitchell-05,
+ author = "David G. Mitchell",
+ title = "A {SAT} Solver Primer",
+ journal = "Bulletin of the EATCS",
+ volume = "85",
+ year = "2005",
+ pages = "112--133",
+ URL = "http://www.cs.sfu.ca/~mitchell/papers/colLogCS85.pdf",
+}
+
+@InProceedings{mitchell-84,
+ author = "John C. Mitchell",
+ title = "Coercion and type inference",
+ booktitle = popl,
+ pages = "175--185",
+ year = "1984",
+ URL = "http://portal.acm.org/citation.cfm?id=800529&dl=ACM&coll=portal",
+}
+
+@InProceedings{mitchell-86,
+ author = "John C. Mitchell",
+ title = "Representation Independence and Data Abstraction",
+ booktitle = popl,
+ year = "1986",
+ pages = "263--276",
+ URL = "http://dx.doi.org/10.1145/512644.512669",
+}
+
+@Article{mitchell-88,
+ author = "John C. Mitchell",
+ title = "Polymorphic type inference and containment",
+ journal = ic,
+ year = "1988",
+ volume = "76",
+ number = "2--3",
+ pages = "211--249",
+ URL = "http://dx.doi.org/10.1016/0890-5401(88)90009-0",
+}
+
+@Article{mitchell-91,
+ author = "John C. Mitchell",
+ title = "Type Inference with Simple Subtypes",
+ journal = jfp,
+ year = "1991",
+ volume = "1",
+ number = "3",
+ pages = "245--286",
+}
+
+@Book{mitchell-96,
+ author = "John C. Mitchell",
+ title = "Foundations for Programming Languages",
+ publisher = mitp,
+ year = "1996",
+}
+
+@Article{mitchell-plotkin-88,
+ author = "John C. Mitchell and Gordon D. Plotkin",
+ title = "Abstract types have existential type",
+ journal = toplas,
+ volume = "10",
+ number = "3",
+ year = "1988",
+ pages = "470--502",
+ URL = "http://theory.stanford.edu/people/jcm/papers/mitch-plotkin-88.pdf",
+}
+
+@InProceedings{mitls-13,
+ author = "Karthikeyan Bhargavan and C{\'{e}}dric Fournet and
+ Markulf Kohlweiss and Alfredo Pironti and Pierre{-}Yves
+ Strub",
+ title = "Implementing {TLS} with Verified Cryptographic
+ Security",
+ booktitle = sp,
+ pages = "445--459",
+ year = "2013",
+ URL = "http://prosecco.gforge.inria.fr/personal/karthik/pubs/implementing-tls-with-verified-cryptographic-security-sp13.pdf",
+}
+
+@Article{mizuno-schmidt-92,
+ author = "Masaaki Mizuno and David A. Schmidt",
+ journal = fac,
+ title = "A Security Flow Control Algorithm and Its Denotational
+ Semantics Correctness Proof",
+ year = "1992",
+ volume = "4",
+ number = "6A",
+ pages = "727--754",
+ URL = "ftp://ftp.cis.ksu.edu/pub/CIS/Schmidt/papers/security.ps.Z",
+}
+
+@Misc{mlton,
+ author = "Henry Cejtin and Matthew Fluet and Suresh Jagannathan
+ and Stephen Weeks",
+ title = "The {MLton} compiler",
+ year = "2007",
+ URL = "http://mlton.org/",
+}
+
+@InProceedings{mogelberg-staton-10,
+ author = "Rasmus Ejlers Møgelberg and Sam Staton",
+ title = "Full abstraction in a metalanguage for state",
+ booktitle = lola,
+ year = "2010",
+}
+
+@InProceedings{moggi-89,
+ author = "Eugenio Moggi",
+ title = "Computational $\lambda$-Calculus and Monads",
+ booktitle = lics,
+ year = "1989",
+ pages = "14--23",
+ URL = "http://www.disi.unige.it/person/MoggiE/ftp/lics89.ps.gz",
+}
+
+@TechReport{moggi-89b,
+ author = "Eugenio Moggi",
+ title = "An abstract view of programming languages",
+ institution = "University of Edinburgh",
+ number = "ECS-LFCS-90-113",
+ year = "1989",
+ URL = "http://www.disi.unige.it/person/MoggiE/ftp/abs-view.ps.gz",
+}
+
+@Article{moggi-91,
+ author = "Eugenio Moggi",
+ title = "Notions of computation and monads",
+ journal = ic,
+ year = "1991",
+ volume = "93",
+ number = "1",
+ URL = "http://www.disi.unige.it/person/MoggiE/ftp/ic91.pdf",
+}
+
+@Article{moggi-sabry-04,
+ author = "Eugenio Moggi and Amr Sabry",
+ title = "An Abstract Monadic Semantics for Value Recursion",
+ journal = ita,
+ year = "2004",
+ volume = "38",
+ number = "4",
+ pages = "377--400",
+ URL = "http://www.disi.unige.it/person/MoggiE/ftp/ita04.pdf",
+}
+
+@Article{monadic-regions-06,
+ author = "Matthew Fluet and Greg Morrisett",
+ title = "Monadic Regions",
+ journal = jfp,
+ year = "2006",
+ volume = "16",
+ number = "4--5",
+ pages = "485--545",
+ URL = "http://dx.doi.org/10.1017/S095679680600596X",
+}
+
+@Unpublished{monnier-08,
+ author = "Stefan Monnier",
+ title = "Statically tracking state with Typed Regions",
+ note = "Unpublished",
+ year = "2008",
+ URL = "http://www.iro.umontreal.ca/~monnier/tr.pdf",
+}
+
+@InProceedings{montagu-remy-09,
+ author = "Beno{\^\i}t Montagu and Didier R{\'e}my",
+ title = "Modeling Abstract Types in Modules with Open
+ Existential Types",
+ booktitle = popl,
+ year = "2009",
+ URL = "http://gallium.inria.fr/~remy/modules/Montagu-Remy@popl09:fzip.pdf",
+ pages = "63--74",
+}
+
+@Article{morrisett-al-07,
+ title = "${L}^3$: {A} Linear Language with Locations",
+ author = "Amal Ahmed and Matthew Fluet and Greg Morrisett",
+ journal = fundamenta,
+ year = "2007",
+ number = "4",
+ volume = "77",
+ pages = "397--449",
+ URL = "http://ttic.uchicago.edu/~amal/papers/linloc-fi07.pdf",
+}
+
+@Article{morrisett-ftal-99,
+ author = "Greg Morrisett and David Walker and Karl Crary and
+ Neal Glew",
+ title = "From System {F} to Typed Assembly Language",
+ journal = toplas,
+ year = "1999",
+ volume = "21",
+ number = "3",
+ pages = "528--569",
+ URL = "http://www.cs.cornell.edu/talc/papers/tal-toplas.pdf",
+}
+
+@InProceedings{morrisett-rec-98,
+ author = "Greg Morrisett and Robert Harper",
+ title = "Typed Closure Conversion for Recursively-Defined
+ Functions (Extended Abstract)",
+ booktitle = hoots,
+ year = "1998",
+ series = entcs,
+ volume = "10",
+ publisher = elsevier,
+ URL = "http://www.cs.cornell.edu/home/jgm/papers/hootsclosure.ps",
+}
+
+@InProceedings{moskewicz-chaff-01,
+ author = "Matthew W. Moskewicz and Conor F. Madigan and Ying
+ Zhao and Lintao Zhang and Sharad Malik",
+ title = "Chaff: Engineering an efficient {SAT} solver",
+ booktitle = dac,
+ year = "2001",
+ URL = "http://research.microsoft.com/users/lintaoz/papers/dac_2001.pdf",
+}
+
+@Article{mosses-04,
+ author = "Peter D. Mosses",
+ title = "Modular structural operational semantics",
+ journal = jlap,
+ volume = "60--61",
+ year = "2004",
+ pages = "195--228",
+ URL = "http://www.brics.dk/RS/05/7/BRICS-RS-05-7.pdf",
+}
+
+@InProceedings{mueller-94,
+ author = "Martin M{\"u}ller",
+ title = "A Constraint-Based Recast of {ML}-Polymorphism",
+ booktitle = "International Workshop on Unification",
+ year = "1994",
+ note = "Technical Report 94-R-243, CRIN, Nancy, France",
+ URL = "http://www.ps.uni-sb.de/Papers/abstracts/UNIF94.ps",
+}
+
+@Unpublished{mueller-98,
+ author = "Martin M{\"u}ller",
+ title = "Notes on {HM}$({X})$",
+ year = "1998",
+ URL = "http://www.ps.uni-sb.de/~mmueller/papers/HMX.ps.gz",
+ note = "Unpublished",
+}
+
+@Article{mueller-feature-01,
+ title = "The First-Order Theory of Ordering Constraints over
+ Feature Trees",
+ year = "2001",
+ author = "Martin M{\"u}ller and Joachim Niehren and Ralf
+ Treinen",
+ journal = "Discrete Mathematics and Theoretical Computer
+ Science",
+ pages = "193--234",
+ number = "2",
+ volume = "4",
+ URL = "http://www.ps.uni-sb.de/Papers/abstracts/FTSubTheory-Long:99.ps",
+}
+
+@Article{mueller-holcf-99,
+ author = "Olaf Müller and Tobias Nipkow and David von Oheimb
+ and Oskar Slotosch",
+ title = "{HOLCF = HOL + LCF}",
+ journal = jfp,
+ volume = "9",
+ pages = "191--223",
+ year = "1999",
+ URL = "http://www4.informatik.tu-muenchen.de/~nipkow/pubs/jfp99.ps.gz",
+}
+
+@Article{mueller-niehren-podelski-feature-99,
+ author = "Martin Müller and Joachim Niehren and Andreas
+ Podelski",
+ journal = "Constraints, an International Journal",
+ volume = "5",
+ number = "1--2",
+ title = "Ordering Constraints over Feature Trees",
+ mon = jan,
+ year = "2000",
+ pages = "7--42",
+ URL = "ftp://ftp.ps.uni-sb.de/pub/papers/ProgrammingSysLab/ftsub-constraints-99.ps.gz",
+}
+
+@InProceedings{mueller-niehren-podelski-ines-97,
+ author = "Joachim Niehren and Martin M{\"u}ller and Andreas
+ Podelski",
+ booktitle = tapsoft,
+ title = "Inclusion Constraints over Non-Empty Sets of Trees",
+ series = lncs,
+ publisher = springer,
+ volume = "1214",
+ year = "1997",
+ pages = "217--231",
+ URL = "http://www.ps.uni-sb.de/Papers/abstracts/ines97.ps",
+}
+
+@Article{mueller-nishimura-00,
+ author = "Martin M{\"u}ller and Susumu Nishimura",
+ title = "Type Inference for First-Class Messages with Feature
+ Constraints",
+ journal = ijfcs,
+ year = "2000",
+ volume = "11",
+ number = "1",
+ pages = "29--63",
+}
+
+@InProceedings{mueller-nishimura-98,
+ author = "Martin M{\"u}ller and Susumu Nishimura",
+ title = "Type Inference for First-Class Messages with Feature
+ Constraints",
+ booktitle = asian,
+ pages = "169--187",
+ year = "1998",
+ volume = "1538",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.ps.uni-sb.de/Papers/abstracts/FirstClass98.ps",
+}
+
+@TechReport{mueller-poetzsch-heffter-01,
+ author = "Peter M{\"u}ller and Arnd Poetzsch-Heffter",
+ title = "Universes: {A} Type System for Alias and Dependency
+ Control",
+ year = "2001",
+ institution = "Fernuniversit{\"a}t Hagen",
+ number = "279",
+ URL = "http://people.inf.ethz.ch/lehnerh/pm/publications/getpdf.php?bibname=Own&id=MuellerPoetzsch-Heffter01a.pdf",
+}
+
+@InProceedings{mueller-rudich-07,
+ author = "Peter M{\"u}ller and Arsenii Rudich",
+ title = "Ownership transfer in universe types",
+ booktitle = oopsla,
+ year = "2007",
+ pages = "461--478",
+ URL = "http://dx.doi.org/10.1145/1297027.1297061",
+}
+
+@InProceedings{mueller-schwerhoff-summers-16,
+ author = "Peter M{\"{u}}ller and Malte Schwerhoff and Alexander
+ J. Summers",
+ title = "Automatic Verification of Iterated Separating
+ Conjunctions Using Symbolic Execution",
+ booktitle = cav,
+ pages = "405--425",
+ year = "2016",
+ volume = "9779",
+ publisher = springer,
+ series = lncs,
+ URL = "https://arxiv.org/abs/1603.00649",
+}
+
+@InProceedings{muller-rpc-98,
+ title = "Fast, optimized {Sun} {RPC} using automatic program
+ specialization",
+ author = "Gilles Muller and Renaud Marlet and Eugen-Nicolae
+ Volanschi and Charles Consel and Calton Pu and Ashvin
+ Goel",
+ booktitle = cdcs,
+ pages = "240--249",
+ year = "1998",
+ URL = "http://www.cc.gatech.edu/~calton/publications/dcs-98.pdf",
+}
+
+@InProceedings{mycroft-84,
+ author = "Alan Mycroft",
+ title = "Polymorphic Type Schemes and Recursive Definitions",
+ booktitle = "International Symposium on Programming",
+ series = lncs,
+ volume = "167",
+ pages = "217--228",
+ year = "1984",
+ publisher = springer,
+ URL = "http://dx.doi.org/10.1007/3-540-12925-1_41",
+}
+
+@PhdThesis{myers-99,
+ author = "Andrew C. Myers",
+ title = "Mostly-Static Decentralized Information Flow Control",
+ school = "Massachusetts Institute of Technology",
+ year = "1999",
+ pages = "171",
+ note = "Technical Report MIT/LCS/TR-783",
+ URL = "http://www.cs.cornell.edu/andru/release/tr783.ps.gz",
+}
+
+@Article{myers-liskov-00,
+ author = "Andrew C. Myers and Barbara Liskov",
+ title = "Protecting Privacy using the Decentralized Label
+ Model",
+ journal = tosem,
+ volume = "9",
+ number = "4",
+ year = "2000",
+ pages = "410--442",
+ URL = "http://www.cs.cornell.edu/andru/papers/iflow-tosem.ps.gz",
+}
+
+@Article{myers-liskov-97,
+ author = "Andrew C. Myers and Barbara Liskov",
+ title = "A Decentralized Model for Information Flow Control",
+ year = "1997",
+ number = "5",
+ volume = "31",
+ pages = "129--142",
+ journal = "{ACM} Operating Systems Review",
+ URL = "http://www.cs.cornell.edu/andru/papers/iflow-sosp97/paper.html",
+}
+
+@InProceedings{myers-liskov-98,
+ author = "Andrew C. Myers and Barbara Liskov",
+ title = "Complete, Safe Information Flow with Decentralized
+ Labels",
+ year = "1998",
+ pages = "186--197",
+ booktitle = sp,
+ URL = "http://www.cs.cornell.edu/andru/papers/sp98/top.html",
+}
+
+@InProceedings{myers-popl-99,
+ author = "Andrew C. Myers",
+ title = "{JFlow}: practical mostly-static information flow
+ control",
+ booktitle = popl,
+ year = "1999",
+ pages = "228--241",
+ URL = "http://www.cs.cornell.edu/andru/papers/popl99/myers-popl99.ps.gz",
+}
+
+@Article{myers-sabelfeld-03,
+ author = "Andrew C. Myers and Andrei Sabelfeld",
+ title = "Language-Based Information-Flow Security",
+ journal = "IEEE Journal on Selected Areas in Communications",
+ year = "2003",
+ volume = "21",
+ number = "1",
+ pages = "5--19",
+ URL = "http://www.cs.cornell.edu/andru/papers/jsac/sm-jsac03.pdf",
+}
+
+@InProceedings{nadathur-miller-88,
+ author = "Gopalan Nadathur and Dale Miller",
+ title = "An Overview of Lambda-Prolog",
+ booktitle = "Logic Programming",
+ pages = "810--827",
+ year = "1988",
+ URL = "http://repository.upenn.edu/cis_reports/595/",
+}
+
+@InProceedings{nadathur-qi-03,
+ author = "Gopalan Nadathur and Xiaochu Qi",
+ title = "Explicit Substitutions in the Reduction of Lambda
+ Terms",
+ booktitle = ppdp,
+ pages = "195--206",
+ year = "2003",
+ URL = "http://www-users.cs.umn.edu/~gopalan/papers/reduction.ps",
+ alturl = "http://doi.acm.org/10.1145/888270",
+}
+
+@Book{naftalin-wadler-06,
+ author = "Maurice Naftalin and Philip Wadler",
+ title = "{Java} generics and collections",
+ publisher = "O'Reilly",
+ year = "2006",
+ URL = "http://shop.oreilly.com/product/9780596527754.do",
+}
+
+@InProceedings{nakano-00,
+ author = "Hiroshi Nakano",
+ title = "A Modality for Recursion",
+ booktitle = lics,
+ pages = "255--266",
+ year = "2000",
+ URL = "http://www602.math.ryukoku.ac.jp/~nakano/papers/modality-lics00.ps.gz",
+}
+
+@InProceedings{nakano-01,
+ author = "Hiroshi Nakano",
+ title = "Fixed-point Logic with the Approximation Modality and
+ Its {Kripke} Completeness",
+ booktitle = tacs,
+ pages = "165--182",
+ year = "2001",
+ volume = "2215",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www602.math.ryukoku.ac.jp/~nakano/papers/modality-tacs01.pdf",
+}
+
+@TechReport{nanevski-02,
+ author = "Aleksandar Nanevski",
+ title = "Meta-Programming with Names and Necessity",
+ institution = "School of Computer Science, Carnegie Mellon
+ University",
+ year = "2002",
+ number = "CMU-CS-02-123R",
+ URL = "http://www.eecs.harvard.edu/~aleks/papers/necessity/techrep2.ps",
+}
+
+@InProceedings{nanevski-htt-06,
+ author = "Aleksandar Nanevski and Greg Morrisett and Lars
+ Birkedal",
+ title = "Polymorphism and Separation in {Hoare} Type Theory",
+ booktitle = icfp,
+ pages = "62--73",
+ year = "2006",
+ URL = "http://www.eecs.harvard.edu/~aleks/papers/hoarelogic/icfp06.pdf",
+}
+
+@InProceedings{nanevski-htt-07,
+ author = "Aleksandar Nanevski and Amal Ahmed and Greg Morrisett
+ and Lars Birkedal",
+ title = "Abstract Predicates and Mutable {ADTs} in {Hoare} Type
+ Theory",
+ booktitle = esop,
+ year = "2007",
+ series = lncs,
+ volume = "4421",
+ pages = "189--204",
+ publisher = springer,
+ URL = "http://ynot.cs.harvard.edu/papers/esop07.pdf",
+}
+
+@Article{nanevski-htt-08,
+ author = "Aleksandar Nanevski and Greg Morrisett and Lars
+ Birkedal",
+ title = "{Hoare} Type Theory, Polymorphism and Separation",
+ journal = jfp,
+ year = "2008",
+ volume = "18",
+ number = "5--6",
+ pages = "865--911",
+ URL = "http://ynot.cs.harvard.edu/papers/jfpsep07.pdf",
+}
+
+@InProceedings{nanevski-structuring-10,
+ author = "Aleksandar Nanevski and Viktor Vafeiadis and Josh
+ Berdine",
+ title = "Structuring the verification of heap-manipulating
+ programs",
+ booktitle = popl,
+ year = "2010",
+ pages = "261--274",
+ URL = "http://software.imdea.org/~aleks/papers/reflect/reflect.pdf",
+}
+
+@InProceedings{nanevski-ynot-08,
+ author = "Aleksandar Nanevski and Greg Morrisett and Avraham
+ Shinnar and Paul Govereau and Lars Birkedal",
+ title = "Ynot: dependent types for imperative programs",
+ booktitle = icfp,
+ year = "2008",
+ pages = "229--240",
+ URL = "http://software.imdea.org/~aleks/htt/ynot08.pdf",
+}
+
+@Article{naraschewski-nipkow-99,
+ author = "Wolfgang Naraschewski and Tobias Nipkow",
+ title = "Type Inference Verified: Algorithm {W} in
+ {Isabelle/HOL}",
+ journal = jar,
+ year = "1999",
+ volume = "23",
+ pages = "299--318",
+ URL = "http://www4.informatik.tu-muenchen.de/~nipkow/pubs/W.ps.gz",
+}
+
+@Article{naumann-survey-07,
+ author = "David A. Naumann",
+ title = "On assertion-based encapsulation for object invariants
+ and simulations",
+ journal = fac,
+ volume = "19",
+ number = "2",
+ year = "2007",
+ pages = "205--224",
+ publisher = springer,
+ URL = "https://guinness.cs.stevens-tech.edu/~naumann/publications/fmcoFinal.pdf",
+}
+
+@InProceedings{navarro-perez-rybalchenko-11,
+ author = "Juan Antonio {Navarro P{\'e}rez} and Andrey
+ Rybalchenko",
+ title = "Separation logic + superposition calculus = heap
+ theorem prover",
+ booktitle = pldi,
+ year = "2011",
+ pages = "556--566",
+ URL = "http://www7.informatik.tu-muenchen.de/um/bibdb/navarro/pldi2011.pdf",
+}
+
+@InProceedings{needle-knot-16,
+ author = "Steven Keuchel and Stephanie Weirich and Tom
+ Schrijvers",
+ title = "Needle {\&} Knot: Binder Boilerplate Tied Up",
+ booktitle = esop,
+ pages = "419--445",
+ year = "2016",
+ series = lncs,
+ volume = "9632",
+ publisher = springer,
+ URL = "https://users.ugent.be/~skeuchel/publications/knot.pdf",
+}
+
+@InProceedings{neron-tolmach-visser-wachsmuth-15,
+ author = "Pierre Neron and Andrew P. Tolmach and Eelco Visser
+ and Guido Wachsmuth",
+ title = "A Theory of name resolution",
+ booktitle = esop,
+ pages = "205--231",
+ year = "2015",
+ series = lncs,
+ volume = "9032",
+ publisher = springer,
+ URL = "http://web.cecs.pdx.edu/~apt/esop15.pdf",
+}
+
+@InProceedings{neumann-12,
+ author = "René Neumann",
+ booktitle = "ATx/WInG: Joint Proceedings of the Workshops on
+ Automated Theory eXploration and on Invariant
+ Generation",
+ pages = "36--45",
+ title = "A Framework for Verified Depth-First Algorithms",
+ publisher = "EasyChair",
+ series = "EPiC Series",
+ volume = "17",
+ year = "2012",
+ URL = "http://www.easychair.org/publications/?page=722211206",
+}
+
+@InProceedings{nguyen-07,
+ author = "Huu Hai Nguyen and Cristina David and Shengchao Qin
+ and Wei-Ngan Chin",
+ title = "Automated Verification of Shape and Size Properties
+ Via Separation Logic",
+ booktitle = vmcai,
+ year = "2007",
+ pages = "251--266",
+ publisher = springer,
+ series = lncs,
+ volume = "4349",
+ URL = "http://www.scm.tees.ac.uk/s.qin/papers/vmcai07.pdf",
+}
+
+@InProceedings{nicklisch-peyton-jones-96,
+ author = "Jan Nicklisch and Simon {Peyton Jones}",
+ title = "An exploration of modular programs",
+ booktitle = "Functional Programming Workshop",
+ year = "1996",
+ URL = "http://www.dcs.gla.ac.uk/fp/workshops/fpw96/Nicklisch.ps.gz",
+}
+
+@InProceedings{niehren-priesnitz-01,
+ author = "Joachim Niehren and Tim Priesnitz",
+ title = "Non-Structural Subtype Entailment in Automata Theory",
+ booktitle = tacs,
+ publisher = springer,
+ year = "2001",
+ URL = "ftp://ftp.ps.uni-sb.de/pub/papers/ProgrammingSysLab/pauto.ps.gz",
+}
+
+@Article{niehren-priesnitz-03,
+ author = "Joachim Niehren and Tim Priesnitz",
+ title = "Non-Structural Subtype Entailment in Automata Theory",
+ journal = ic,
+ year = "2003",
+ volume = "186",
+ number = "2",
+ pages = "319--354",
+ URL = "http://www.ps.uni-sb.de/Papers/abstracts/subtype.pdf",
+}
+
+@TechReport{nielsen-00,
+ author = "Lasse R. Nielsen",
+ title = "A denotational investigation of defunctionalization",
+ year = "2000",
+ institution = "BRICS",
+ number = "RS-00-47",
+ URL = "http://www.brics.dk/RS/00/47/",
+}
+
+@Article{nielson-02,
+ author = "Flemming Nielson and Hanne Riis Nielson and Helmut
+ Seidl",
+ title = "A Succinct Solver for {ALFP}",
+ journal = njc,
+ year = "2002",
+ volume = "9",
+ number = "4",
+ pages = "335--372",
+ URL = "http://www.informatik.uni-trier.de/~seidl/papers/succinct.pdf",
+}
+
+@Article{nielson-88,
+ author = "Flemming Nielson and Hanne Riis Nielson",
+ title = "Two-Level Semantics and Code Generation",
+ year = "1988",
+ pages = "59--133",
+ journal = tcs,
+ volume = "56",
+ number = "1",
+ URL = "http://dx.doi.org/10.1016/0304-3975(86)90006-X",
+}
+
+@Article{nieuwenhuis-oliveras-tinelli-06,
+ author = "Robert Nieuwenhuis and Albert Oliveras and Cesare
+ Tinelli",
+ title = "Solving {SAT} and {SAT Modulo Theories}: From an
+ abstract {Davis--Putnam--Logemann--Loveland} procedure
+ to {DPLL(T)}",
+ journal = jacm,
+ volume = "53",
+ number = "6",
+ year = "2006",
+ pages = "937--977",
+ URL = "ftp://ftp.cs.uiowa.edu/pub/tinelli/papers/NieOT-JACM-06.pdf",
+}
+
+@InProceedings{nipkow-15,
+ author = "Tobias Nipkow",
+ title = "Amortized Complexity Verified",
+ year = "2015",
+ booktitle = itp,
+ pages = "310--324",
+ volume = "9236",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www21.in.tum.de/~nipkow/pubs/itp15.pdf",
+}
+
+@InProceedings{nishimura-98,
+ title = "Static Typing for Dynamic Messages",
+ author = "Susumu Nishimura",
+ pages = "266--278",
+ booktitle = popl,
+ year = "1998",
+ URL = "ftp://ftp.kurims.kyoto-u.ac.jp/pub/paper/member/nisimura/dmesg-popl98.ps.gz",
+}
+
+@InProceedings{ntzik-gardner-15,
+ author = "Gian Ntzik and Philippa Gardner",
+ title = "Reasoning about the {POSIX} file system: local update
+ and global pathnames",
+ booktitle = oopsla,
+ pages = "201--220",
+ year = "2015",
+ URL = "https://www.doc.ic.ac.uk/~pg/papers/oopsla2015.pdf",
+}
+
+@Article{o'hearn-03,
+ author = "Peter O'Hearn",
+ title = "On Bunched Typing",
+ journal = jfp,
+ year = "2003",
+ volume = "13",
+ number = "4",
+ pages = "747--796",
+ URL = "http://www.cs.ucl.ac.uk/staff/p.ohearn/papers/BunchedTyping.pdf",
+}
+
+@Manual{objective-caml,
+ author = "Xavier Leroy and Damien Doligez and Jacques Garrigue
+ and Didier Rémy and Jérôme Vouillon",
+ title = "The {Objective Caml} system",
+ year = "2005",
+ URL = "http://caml.inria.fr/",
+}
+
+@Misc{ocaml,
+ author = "Xavier Leroy and Damien Doligez and Alain Frisch and
+ Jacques Garrigue and Didier Rémy and Jérôme
+ Vouillon",
+ title = "The {OCaml} system: documentation and user's manual",
+ year = "2016",
+ URL = "http://caml.inria.fr/pub/docs/manual-ocaml-4.04/index.html",
+}
+
+@Article{oconnor-07,
+ author = "Russell O'Connor",
+ title = "Assembly: Circular Programming with Recursive do",
+ journal = "The Monad.Reader",
+ year = "2007",
+ volume = "6",
+ URL = "http://www.haskell.org/sitewiki/images/1/14/TMR-Issue6.pdf",
+}
+
+@InProceedings{odersky-laufer-96,
+ author = "Martin Odersky and Konstantin Läufer",
+ title = "Putting Type Annotations To Work",
+ booktitle = popl,
+ year = "1996",
+ pages = "54--67",
+ URL = "http://lamp.epfl.ch/~odersky/papers/popl96.ps.gz",
+}
+
+@InProceedings{odersky-local-94,
+ author = "Martin Odersky",
+ title = "A Functional Theory of Local Names",
+ pages = "48--59",
+ booktitle = popl,
+ year = "1994",
+ URL = "http://lampwww.epfl.ch/~odersky/papers/popl94.ps.gz",
+}
+
+@InProceedings{odersky-observers-92,
+ author = "Martin Odersky",
+ title = "Observers for Linear Types",
+ booktitle = esop,
+ pages = "390--407",
+ year = "1992",
+ volume = "582",
+ series = lncs,
+ publisher = springer,
+ URL = "http://lamp.epfl.ch/~odersky/papers/esop92.ps.gz",
+}
+
+@Article{odersky-sulzmann-wehr-99,
+ author = "Martin Odersky and Martin Sulzmann and Martin Wehr",
+ title = "Type Inference with Constrained Types",
+ journal = tapos,
+ year = "1999",
+ volume = "5",
+ number = "1",
+ pages = "35--55",
+ URL = "http://eprints.kfupm.edu.sa/73647/1/73647.pdf",
+}
+
+@InProceedings{odersky-wadler-wehr-95,
+ author = "Martin Odersky and Philip Wadler and Martin Wehr",
+ title = "A Second Look at Overloading",
+ booktitle = fpca,
+ pages = "135--146",
+ year = "1995",
+ URL = "http://lampwww.epfl.ch/~odersky/papers/fpca95.ps.gz",
+}
+
+@InProceedings{odersky-zenger-zenger-01,
+ author = "Martin Odersky and Matthias Zenger and Christoph
+ Zenger",
+ title = "Colored Local Type Inference",
+ booktitle = popl,
+ year = "2001",
+ pages = "41--53",
+ URL = "http://lampwww.epfl.ch/papers/clti-colored.ps.gz",
+}
+
+@Article{ohearn-07,
+ author = "Peter W. O'Hearn",
+ title = "Resources, Concurrency and Local Reasoning",
+ journal = tcs,
+ year = "2007",
+ volume = "375",
+ number = "1--3",
+ pages = "271--307",
+ URL = "http://www.cs.ucl.ac.uk/staff/p.ohearn/papers/concurrency.pdf",
+}
+
+@InProceedings{ohearn-hiding-04,
+ author = "Peter W. O'Hearn and Hongseok Yang and John C.
+ Reynolds",
+ title = "Separation and information hiding",
+ booktitle = popl,
+ pages = "268--280",
+ year = "2004",
+ URL = "http://www.cs.ucl.ac.uk/staff/p.ohearn/papers/separation-and-hiding.pdf",
+}
+
+@Article{ohearn-hiding-09,
+ author = "Peter W. O'Hearn and Hongseok Yang and John C.
+ Reynolds",
+ title = "Separation and information hiding",
+ journal = toplas,
+ volume = "31",
+ number = "3",
+ year = "2009",
+ URL = "http://www.cs.ucl.ac.uk/staff/p.ohearn/papers/toplas09.pdf",
+}
+
+@Article{ohearn-reynolds-00,
+ author = "Peter W. O'Hearn and John C. Reynolds",
+ title = "From {Algol} to polymorphic linear lambda-calculus",
+ journal = jacm,
+ volume = "47",
+ number = "1",
+ year = "2000",
+ pages = "167--223",
+ URL = "http://www.cs.ucl.ac.uk/staff/p.ohearn/papers/AlgolToPolyLin.ps",
+}
+
+@Article{ohearn-scir-99,
+ author = "Peter W. O'Hearn and John Power and Makoto Takeyama
+ and Robert D. Tennent",
+ title = "Syntactic Control of Interference Revisited",
+ journal = tcs,
+ volume = "228",
+ number = "1-2",
+ pages = "211--252",
+ year = "1999",
+ URL = "http://surface.syr.edu/cgi/viewcontent.cgi?article=1011&context=lcsmith_other",
+}
+
+@Article{ohori-95,
+ author = "Atsushi Ohori",
+ title = "A Polymorphic Record Calculus and Its Compilation",
+ journal = toplas,
+ volume = "17",
+ number = "6",
+ pages = "844--895",
+ year = "1995",
+ URL = "http://doi.acm.org/10.1145/218570.218572",
+}
+
+@InProceedings{ohori-buneman-88,
+ author = "Atsushi Ohori and Peter Buneman",
+ title = "Type Inference in a Database Programming Language",
+ booktitle = lfp,
+ pages = "174--183",
+ year = "1988",
+ URL = "http://www.jaist.ac.jp/~ohori/research/lfp88.pdf",
+}
+
+@InProceedings{okasaki-96,
+ author = "Chris Okasaki",
+ title = "The role of lazy evaluation in amortized data
+ structures",
+ booktitle = icfp,
+ year = "1996",
+ pages = "62--72",
+ URL = "http://www.eecs.usma.edu/webs/people/okasaki/icfp96.ps",
+}
+
+@InProceedings{okasaki-98,
+ author = "Chris Okasaki and Andy Gill",
+ title = "Fast Mergeable Integer Maps",
+ booktitle = ml,
+ pages = "77--86",
+ year = "1998",
+ URL = "http://www.cse.ogi.edu/~andy/papers/ml98maps.ps",
+}
+
+@Book{okasaki-book-99,
+ author = "Chris Okasaki",
+ title = "Purely Functional Data Structures",
+ publisher = cup,
+ year = "1999",
+ URL = "http://www.cambridge.org/us/catalogue/catalogue.asp?isbn=0521663504",
+}
+
+@TechReport{okasaki-phd-96,
+ author = "Chris Okasaki",
+ title = "Purely Functional Data Structures",
+ institution = "School of Computer Science, Carnegie Mellon
+ University",
+ year = "1996",
+ number = "CMU-CS-96-177",
+ URL = "http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf",
+}
+
+@InProceedings{okasaki-views-98,
+ author = "Chris Okasaki",
+ title = "Views for {Standard ML}",
+ booktitle = ml,
+ pages = "14--23",
+ year = "1998",
+ URL = "http://www.eecs.usma.edu/Personnel/okasaki/ml98views.ps",
+}
+
+@InProceedings{olderog-83,
+ author = "Ernst-Rüdiger Olderog",
+ title = "A characterization of {Hoare's} logic for programs
+ with {Pascal}-like procedures",
+ booktitle = stoc,
+ year = "1983",
+ pages = "320--329",
+ URL = "http://doi.acm.org/10.1145/800061.808761",
+}
+
+@Manual{omega,
+ title = "{${\Omega}$}mega",
+ author = "Tim Sheard",
+ year = "2005",
+ URL = "http://www.cs.pdx.edu/~sheard/Omega/",
+}
+
+@Article{oostrom-94,
+ author = "Vincent van Oostrom",
+ title = "Confluence by decreasing diagrams",
+ journal = tcs,
+ volume = "126",
+ number = "2",
+ pages = "259--280",
+ year = "1994",
+ URL = "ftp://ftp.cs.vu.nl/pub/papers/theory/IR-298.ps.Z",
+}
+
+@Book{orourke-98,
+ author = "Joseph O'Rourke",
+ title = "Computational Geometry in {C}, Second Edition",
+ publisher = cup,
+ year = "1998",
+ URL = "http://maven.smith.edu/~orourke/books/compgeom.html",
+}
+
+@InProceedings{otoole-gifford-89,
+ author = "James William {O'Toole, Jr.} and David K. Gifford",
+ title = "Type reconstruction with first-class polymorphic
+ values",
+ booktitle = pldi,
+ year = "1989",
+ pages = "207--217",
+ URL = "http://www.psrg.lcs.mit.edu/history/publications/Papers/pldi89-otoole.ps",
+}
+
+@Article{ott-10,
+ author = "Peter Sewell and Francesco {Zappa Nardelli} and Scott
+ Owens and Gilles Peskine and Thomas Ridge and Susmit
+ Sarkar and Rok Strnisa",
+ title = "{Ott}: Effective tool support for the working
+ semanticist",
+ journal = jfp,
+ volume = "20",
+ number = "1",
+ pages = "71--122",
+ year = "2010",
+ URL = "http://www.cl.cam.ac.uk/~pes20/ott/ott-jfp.pdf",
+}
+
+@Article{owens-reppy-turon-09,
+ author = "Scott Owens and John H. Reppy and Aaron Turon",
+ title = "Regular-expression derivatives re-examined",
+ journal = jfp,
+ volume = "19",
+ number = "2",
+ year = "2009",
+ pages = "173--190",
+ URL = "http://www.cl.cam.ac.uk/~so294/documents/jfp09.pdf",
+}
+
+@Article{pager-77,
+ author = "David Pager",
+ title = "A Practical General Method for Constructing ${LR}(k)$
+ Parsers",
+ journal = acta,
+ year = "1977",
+ volume = "7",
+ pages = "249--268",
+ URL = "http://dx.doi.org/10.1007/BF00290336",
+}
+
+@Article{paige-tarjan-87,
+ author = "Robert Paige and Robert E. Tarjan",
+ title = "Three partition refinement algorithms",
+ journal = siamjc,
+ volume = "16",
+ number = "6",
+ pages = "973--989",
+ year = "1987",
+ URL = "http://locus.siam.org/fulltext/SICOMP/volume-16/0216062.pdf",
+}
+
+@InProceedings{pale-01,
+ author = "Anders M{\o}ller and Michael I. Schwartzbach",
+ title = "The Pointer Assertion Logic Engine",
+ booktitle = pldi,
+ year = "2001",
+ pages = "221--231",
+ URL = "http://www.brics.dk/~amoeller/papers/pale/pale.pdf",
+}
+
+@Article{palsberg-efficient-object-95,
+ author = "Jens Palsberg",
+ title = "Efficient inference of object types",
+ journal = ic,
+ volume = "123",
+ number = "2",
+ pages = "198--209",
+ year = "1995",
+ URL = "http://www.cs.ucla.edu/~palsberg/paper/ic95-p.pdf",
+}
+
+@Article{palsberg-okeefe-flow-95,
+ author = "Jens Palsberg and Patrick M. O'Keefe",
+ title = "A Type System Equivalent to Flow Analysis",
+ journal = toplas,
+ year = "1995",
+ volume = "17",
+ number = "4",
+ pages = "576--599",
+ URL = "http://www.cs.ucla.edu/~palsberg/paper/toplas95-po.pdf",
+}
+
+@InProceedings{palsberg-orbaek-95,
+ author = "Jens Palsberg and Peter {\O}rb{\ae}k",
+ booktitle = sas,
+ title = "Trust in the {$\lambda$}-calculus",
+ series = "Lecture Notes in Computer Science",
+ volume = "983",
+ pages = "314--330",
+ year = "1995",
+ URL = "ftp://ftp.daimi.au.dk/pub/empl/poe/lambda-trust.dvi.gz",
+}
+
+@Article{palsberg-orbaek-97,
+ title = "Trust in the {$\lambda$}-calculus",
+ author = "Peter {\O}rb{\ae}k and Jens Palsberg",
+ pages = "557--591",
+ journal = jfp,
+ year = "1997",
+ volume = "7",
+ number = "6",
+ URL = "http://www.cs.ucla.edu/~palsberg/paper/jfp97.pdf",
+}
+
+@Article{palsberg-smith-96,
+ author = "Jens Palsberg and Scott Smith",
+ title = "Constrained types and their expressiveness",
+ journal = toplas,
+ volume = "18",
+ number = "5",
+ pages = "519--527",
+ year = "1996",
+ URL = "http://www.cs.ucla.edu/~palsberg/paper/toplas96-ps.pdf",
+}
+
+@Article{palsberg-wand-okeefe-97,
+ title = "Type inference with non-structural subtyping",
+ author = "Jens Palsberg and Mitchell Wand and Patrick M.
+ O'Keefe",
+ journal = fac,
+ year = "1997",
+ pages = "49--67",
+ volume = "9",
+ URL = "http://www.cs.ucla.edu/~palsberg/paper/fac97.pdf",
+}
+
+@Article{palsberg-zhao-01,
+ author = "Jens Palsberg and Tian Zhao",
+ title = "Efficient and Flexible Matching of Recursive Types",
+ journal = ic,
+ volume = "171",
+ pages = "364--387",
+ year = "2001",
+ URL = "http://www.cs.ucla.edu/~palsberg/paper/ic01.pdf",
+}
+
+@InProceedings{palsberg-zhao-02,
+ author = "Jens Palsberg and Tian Zhao",
+ title = "Efficient Type Inference for Record Concatenation and
+ Subtyping",
+ pages = "125--136",
+ booktitle = lics,
+ year = "2002",
+}
+
+@Article{palsberg-zhao-04,
+ author = "Jens Palsberg and Tian Zhao",
+ title = "Type Inference for Record Concatenation and
+ Subtyping",
+ journal = ic,
+ year = "2004",
+ volume = "189",
+ pages = "54--86",
+ URL = "http://www.cs.ucla.edu/~palsberg/paper/ic04.pdf",
+}
+
+@Misc{pangolin,
+ author = "Yann Régis-Gianas",
+ title = "The {Pangolin} programming language",
+ note = "\url{http://code.google.com/p/pangolin-programming-language/}",
+ year = "2008",
+ URL = "http://code.google.com/p/pangolin-programming-language/",
+}
+
+@InProceedings{parkinson-bierman-05,
+ author = "Matthew Parkinson and Gavin Bierman",
+ title = "Separation logic and abstraction",
+ booktitle = popl,
+ year = "2005",
+ pages = "247--258",
+ URL = "http://dx.doi.org/10.1145/1040305.1040326",
+}
+
+@InProceedings{parkinson-bierman-08,
+ author = "Matthew Parkinson and Gavin Bierman",
+ title = "Separation logic, abstraction and inheritance",
+ booktitle = popl,
+ year = "2008",
+ pages = "75--86",
+ URL = "http://dx.doi.org/10.1145/1328438.1328451",
+}
+
+@InProceedings{parnas-71,
+ author = "David Lorge Parnas",
+ title = "Information distribution aspects of design
+ methodology",
+ booktitle = "Information Processing 71",
+ pages = "339--344",
+ volume = "1",
+ year = "1971",
+ URL = "http://cseweb.ucsd.edu/~wgg/CSE218/Parnas-IFIP71-information-distribution.PDF",
+}
+
+@Article{parnas-72,
+ author = "David Lorge Parnas",
+ title = "On the criteria to be used in decomposing systems into
+ modules",
+ journal = cacm,
+ volume = "15",
+ number = "12",
+ year = "1972",
+ pages = "1053--1058",
+ URL = "http://doi.acm.org/10.1145/361598.361623",
+}
+
+@TechReport{pasalic-dali-00,
+ author = "Emir Pa{\v s}ali{\'c} and Tim Sheard and Walid Taha",
+ title = "{DALI}: An Untyped, {CBV} Functional Language
+ Supporting First-Order Datatypes with Binders
+ (Technical Development)",
+ institution = "Oregon Graduate Institute",
+ year = "2000",
+ number = "00-007",
+ URL = "http://www.cse.ogi.edu/PacSoft/publications/phaseiiiq13papers/dali.pdf",
+}
+
+@InProceedings{pasalic-linger-04,
+ author = "Pa{\v s}ali{\'c} and Nathan Linger",
+ title = "Meta-programming with Typed Object-Language
+ Representations",
+ booktitle = gpce,
+ pages = "136--167",
+ year = "2004",
+ URL = "http://web.cecs.pdx.edu/~sheard/papers/MetaProgTypObjLangReps.ps",
+}
+
+@InProceedings{pasalic-tagless-02,
+ author = "Emir Pa{\v s}ali{\'c} and Walid Taha and Tim Sheard",
+ title = "Tagless staged interpreters for typed languages",
+ booktitle = icfp,
+ year = "2002",
+ pages = "218--229",
+ URL = "http://www.cs.rice.edu/~taha/teaching/02F/511/papers/pts02.pdf",
+}
+
+@InProceedings{paterson-wegman-76,
+ author = "M. S. Paterson and M. N. Wegman",
+ title = "Linear Unification",
+ booktitle = "Annual {ACM} Symposium on Theory of Computing",
+ pages = "181--186",
+ year = "1976",
+}
+
+@InProceedings{patwary-10,
+ author = "Md. Mostofa Ali Patwary and Jean Blair and Fredrik
+ Manne",
+ title = "Experiments on Union-Find Algorithms for the
+ Disjoint-Set Data Structure",
+ booktitle = "International Symposium on Experimental Algorithms
+ (SEA)",
+ pages = "411--423",
+ year = "2010",
+ series = lncs,
+ volume = "6049",
+ publisher = springer,
+ URL = "http://www.ii.uib.no/~fredrikm/fredrik/papers/SEA2010.pdf",
+}
+
+@InProceedings{paulin-89,
+ author = "Christine Paulin-Mohring",
+ title = "Extracting ${F}_{\omega}$'s programs from proofs in
+ the Calculus of Constructions",
+ year = "1989",
+ booktitle = popl,
+ pages = "89--104",
+ URL = "http://doi.acm.org/10.1145/75277.75285",
+}
+
+@TechReport{paulin-92,
+ author = "Christine Paulin-Mohring",
+ title = "Inductive Definitions in the system {Coq}: rules and
+ Properties",
+ institution = "ENS Lyon",
+ year = "1992",
+ type = "Research Report",
+ number = "RR1992-49",
+ URL = "ftp://ftp.ens-lyon.fr/pub/LIP/Rapports/RR/RR1992/RR1992-49.ps.Z",
+}
+
+@InProceedings{pennello-86,
+ author = "Thomas J. Pennello",
+ title = "Very fast {LR} parsing",
+ booktitle = "Symposium on Compiler Construction",
+ pages = "145--151",
+ year = "1986",
+ URL = "http://doi.acm.org/10.1145/12276.13326",
+}
+
+@Article{pessaux-leroy-00,
+ author = "Fran\c{c}ois Pessaux and Xavier Leroy",
+ title = "Type-based analysis of uncaught exceptions",
+ journal = toplas,
+ pages = "340--377",
+ volume = "22",
+ number = "2",
+ year = "2000",
+ URL = "http://gallium.inria.fr/~xleroy/publi/exceptions-toplas.ps.gz",
+}
+
+@InProceedings{peterson-jones-93,
+ author = "John Peterson and Mark P. Jones",
+ title = "Implementing Type Classes",
+ booktitle = pldi,
+ pages = "227--236",
+ year = "1993",
+ URL = "http://web.cecs.pdx.edu/~mpj/pubs/pldi93.ps",
+}
+
+@Book{peyton-jones-ifl-87,
+ author = "Simon {Peyton Jones}",
+ title = "The Implementation of Functional Programming
+ Languages",
+ publisher = prentice,
+ year = "1987",
+ URL = "http://research.microsoft.com/Users/simonpj/papers/slpj-book-1987/",
+}
+
+@Article{peyton-jones-marlow-ghc-inliner-02,
+ author = "Simon {Peyton Jones} and Simon Marlow",
+ title = "Secrets of the {Glasgow Haskell Compiler} inliner",
+ journal = jfp,
+ volume = "12",
+ number = "4{\&}5",
+ pages = "393--433",
+ year = "2002",
+ URL = "http://research.microsoft.com/en-us/um/people/simonpj/Papers/inlining/inline-jfp.ps.gz",
+}
+
+@Article{peyton-jones-rank-07,
+ author = "Simon {Peyton Jones} and Dimitrios Vytiniotis and
+ Stephanie Weirich and Mark Shields",
+ title = "Practical type inference for arbitrary-rank types",
+ journal = jfp,
+ volume = "17",
+ number = "1",
+ pages = "1--82",
+ year = "2007",
+ URL = "http://research.microsoft.com/en-us/um/people/simonpj/papers/higher-rank/putting.pdf",
+}
+
+@Unpublished{peyton-jones-shields-04,
+ author = "Simon {Peyton Jones} and Mark Shields",
+ title = "Lexically-Scoped Type Variables",
+ year = "2004",
+ note = "Manuscript",
+ URL = "http://www.cse.ogi.edu/~mbs/pub/scoped/",
+}
+
+@InProceedings{peyton-jones-simple-gadts-06,
+ author = "Simon {Peyton Jones} and Dimitrios Vytiniotis and
+ Stephanie Weirich and Geoffrey Washburn",
+ title = "Simple unification-based type inference for {GADTs}",
+ booktitle = icfp,
+ year = "2006",
+ pages = "50--61",
+ URL = "https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/gadt-pldi.pdf",
+}
+
+@Misc{peyton-jones-tackling-09,
+ author = "Simon {Peyton Jones}",
+ title = "Tackling the Awkward Squad: monadic input/output,
+ concurrency, exceptions, and foreign-language calls in
+ {Haskell}",
+ howpublished = "Online lecture notes",
+ year = "2009",
+ URL = "http://research.microsoft.com/en-us/um/people/simonpj/papers/marktoberdorf/mark.pdf",
+}
+
+@InProceedings{peyton-jones-wadler-93,
+ author = "Simon {Peyton Jones} and Philip Wadler",
+ title = "Imperative functional programming",
+ booktitle = popl,
+ year = "1993",
+ pages = "71--84",
+ URL = "http://homepages.inf.ed.ac.uk/wadler/papers/imperative/imperative.ps.gz",
+}
+
+@TechReport{peyton-jones-wobbly-04,
+ author = "Simon {Peyton Jones} and Geoffrey Washburn and
+ Stephanie Weirich",
+ title = "Wobbly types: type inference for generalised algebraic
+ data types",
+ institution = "University of Pennsylvania",
+ year = "2004",
+ number = "MS-CIS-05-26",
+ URL = "http://www.cis.upenn.edu/~geoffw/research/papers/MS-CIS-05-26.pdf",
+}
+
+@InProceedings{pfenning-elliott-88,
+ author = "Frank Pfenning and Conal Elliott",
+ title = "Higher-Order Abstract Syntax",
+ pages = "199--208",
+ booktitle = pldi,
+ year = "1988",
+ URL = "http://doi.acm.org/10.1145/53990.54010",
+}
+
+@InProceedings{pfenning-lee-89,
+ author = "Frank Pfenning and Peter Lee",
+ title = "{LEAP}: {A} Language with Eval And Polymorphism",
+ booktitle = tapsoft,
+ year = "1989",
+ publisher = springer,
+ series = lncs,
+ volume = "352",
+ pages = "345--359",
+ URL = "http://dx.doi.org/10.1007/3-540-50940-2_46",
+}
+
+@InProceedings{pientka-08,
+ author = "Brigitte Pientka",
+ title = "A type-theoretic foundation for programming with
+ higher-order abstract syntax and first-class
+ substitutions",
+ booktitle = popl,
+ year = "2008",
+ pages = "371--382",
+ URL = "http://www.cs.mcgill.ca/~bpientka/papers/hoasfun-short.pdf",
+}
+
+@InProceedings{pientka-dunfield-08,
+ author = "Brigitte Pientka and Joshua Dunfield",
+ title = "Programming with Proofs and Explicit Contexts",
+ booktitle = ppdp,
+ pages = "163--173",
+ year = "2008",
+ URL = "http://www.cs.mcgill.ca/~bpientka/papers/ppdp-pientka.pdf",
+}
+
+@InProceedings{pientka-pearl-07,
+ author = "Brigitte Pientka",
+ title = "Proof Pearl: The power of higher-order encodings in
+ the logical framework {LF}",
+ booktitle = tphol,
+ pages = "246--261",
+ year = "2007",
+ volume = "4732",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.cs.mcgill.ca/~bpientka/papers/pearl.pdf",
+}
+
+@InProceedings{pierce-sangiorgi-93,
+ author = "Benjamin Pierce and Davide Sangiorgi",
+ title = "Typing and Subtyping for Mobile Processes",
+ pages = "376--385",
+ booktitle = lics,
+ year = "1993",
+ URL = "http://www.cis.upenn.edu/~bcpierce/papers/pi-lics.ps",
+}
+
+@Book{pierce-tapl,
+ author = "Benjamin C. Pierce",
+ title = "Types and Programming Languages",
+ publisher = mitp,
+ year = "2002",
+ URL = "http://www.cis.upenn.edu/~bcpierce/tapl/",
+}
+
+@Article{pierce-turner-00,
+ author = "Benjamin C. Pierce and David N. Turner",
+ title = "Local Type Inference",
+ journal = toplas,
+ year = "2000",
+ volume = "22",
+ number = "1",
+ pages = "1--44",
+ URL = "http://doi.acm.org/10.1145/345099.345100",
+}
+
+@TechReport{pierce-turner-92,
+ author = "Benjamin C. Pierce and David N. Turner",
+ title = "Statically Typed Friendly Functions via Partially
+ Abstract Types",
+ institution = "University of Edinburgh, LFCS",
+ type = "Technical Report",
+ number = "ECS-LFCS-93-256",
+ year = "1993",
+ note = "Also available as INRIA Research Report 1899",
+ URL = "http://www.cis.upenn.edu/~bcpierce/papers/friendly.ps",
+}
+
+@Article{pierce-turner-94,
+ author = "Benjamin C. Pierce and David N. Turner",
+ title = "Simple Type-Theoretic Foundations for Object-Oriented
+ Programming",
+ journal = jfp,
+ volume = "4",
+ number = "2",
+ pages = "207--247",
+ year = "1994",
+ URL = "http://www.cis.upenn.edu/~bcpierce/papers/oop.ps",
+}
+
+@Article{pierce-undecidable-92,
+ author = "Benjamin C. Pierce",
+ title = "Bounded Quantification is Undecidable",
+ journal = ic,
+ year = "1994",
+ volume = "112",
+ number = "1",
+ pages = "131--165",
+ URL = "http://www.cis.upenn.edu/~bcpierce/papers/fsubpopl.ps",
+}
+
+@InProceedings{pilkiewicz-pottier-monotonicity-11,
+ author = "Alexandre Pilkiewicz and François Pottier",
+ title = "The essence of monotonic state",
+ booktitle = tldi,
+ year = "2011",
+ URL = "http://gallium.inria.fr/~fpottier/publis/pilkiewicz-pottier-monotonicity.pdf",
+}
+
+@InProceedings{piskac-13,
+ author = "Ruzica Piskac and Thomas Wies and Damien Zufferey",
+ title = "Automating Separation Logic Using {SMT}",
+ booktitle = cav,
+ pages = "773--789",
+ year = "2013",
+ series = lncs,
+ volume = "8044",
+ publisher = springer,
+ URL = "https://www.mpi-sws.org/~piskac/publications/PiskacWiesZuffrey13SepLog.pdf",
+}
+
+@InProceedings{piskac-14,
+ author = "Ruzica Piskac and Thomas Wies and Damien Zufferey",
+ title = "Automating Separation Logic with Trees and Data",
+ booktitle = cav,
+ pages = "711--728",
+ year = "2014",
+ series = lncs,
+ volume = "8559",
+ publisher = springer,
+ URL = "http://cs.nyu.edu/wies/publ/automating_separation_logic_with_trees_and_data.pdf",
+}
+
+@Article{pitts-03,
+ author = "Andrew M. Pitts",
+ title = "Nominal Logic, {A} First Order Theory of Names and
+ Binding",
+ journal = ic,
+ year = "2003",
+ volume = "186",
+ pages = "165--193",
+ URL = "http://www.cl.cam.ac.uk/~amp12/papers/nomlfo/nomlfo-jv.pdf",
+}
+
+@InProceedings{pitts-05,
+ author = "Andrew M. Pitts",
+ title = "Alpha-Structural Recursion and Induction",
+ booktitle = tphol,
+ year = "2005",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.cl.cam.ac.uk/~amp12/papers/alpsri/alpsri-ea.pdf",
+}
+
+@Article{pitts-06,
+ author = "Andrew M. Pitts",
+ title = "Alpha-Structural Recursion and Induction",
+ journal = jacm,
+ year = "2006",
+ volume = "53",
+ pages = "459--506",
+ URL = "http://www.cl.cam.ac.uk/~amp12/papers/alpsri/alpsri.pdf",
+}
+
+@InProceedings{pitts-10,
+ author = "Andrew M. Pitts",
+ title = "Nominal {System} ${T}$",
+ booktitle = popl,
+ pages = "159--170",
+ year = "2010",
+ URL = "http://www.cl.cam.ac.uk/~amp12/papers/nomst/nomst-popl.pdf",
+}
+
+@InProceedings{pitts-gabbay-00,
+ author = "Andrew M. Pitts and Murdoch J. Gabbay",
+ title = "A Metalanguage for Programming with Bound Names Modulo
+ Renaming",
+ booktitle = mpc,
+ pages = "230--255",
+ year = "2000",
+ volume = "1837",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.cl.cam.ac.uk/~amp12/papers/metpbn/metpbn.pdf",
+}
+
+@Article{pitts-parametric-00,
+ author = "Andrew M. Pitts",
+ title = "Parametric Polymorphism and Operational Equivalence",
+ journal = mscs,
+ year = "2000",
+ volume = "10",
+ pages = "321--359",
+ URL = "http://www.cl.cam.ac.uk/~amp12/papers/parpoe/parpoe.pdf",
+}
+
+@InProceedings{plaid-permissions-11,
+ author = "Jonathan Aldrich and Ronald Garcia and Mark Hahnenberg
+ and Manuel Mohr and Karl Naden and Darpan Saini and
+ Sven Stork and Joshua Sunshine and {\'E}ric Tanter and
+ Roger Wolff",
+ title = "Permission-based programming languages",
+ booktitle = icse,
+ year = "2011",
+ pages = "828--831",
+ URL = "http://www.cs.cmu.edu/~aldrich/papers/plaid-NIER2010.pdf",
+}
+
+@Article{plotkin-75,
+ author = "Gordon D. Plotkin",
+ title = "Call-by-name, call-by-value and the
+ $\lambda$-calculus",
+ journal = tcs,
+ volume = "1",
+ number = "2",
+ pages = "125--159",
+ year = "1975",
+ URL = "http://homepages.inf.ed.ac.uk/gdp/publications/cbn_cbv_lambda.pdf",
+}
+
+@InCollection{plotkin-90,
+ author = "Gordon Plotkin",
+ title = "An illative theory of relations",
+ booktitle = "Situation Theory and its Applications",
+ pages = "133--146",
+ publisher = "Stanford University",
+ year = "1990",
+ number = "22",
+ series = "CSLI Lecture Notes",
+ URL = "http://homepages.inf.ed.ac.uk/gdp/publications/illative.pdf",
+}
+
+@Article{plotkin-lcf-77,
+ author = "Gordon D. Plotkin",
+ title = "{LCF} Considered as a Programming Language",
+ journal = tcs,
+ volume = "5",
+ number = "3",
+ year = "1977",
+ pages = "225--255",
+ URL = "http://homepages.inf.ed.ac.uk/gdp/publications/LCF.pdf",
+}
+
+@InCollection{plural-11,
+ author = "Kevin Bierhoff and Nels E. Beckman and Jonathan
+ Aldrich",
+ title = "Checking Concurrent Typestate with Access Permissions
+ in {Plural}: {A} Retrospective",
+ booktitle = "Engineering of Software",
+ pages = "35--48",
+ publisher = springer,
+ year = "2011",
+ editor = "Peri L. Tarr and Alexander L. Wolf",
+ URL = "http://www.cs.cmu.edu/~aldrich/papers/bierhoff-plural-festschrift11.pdf",
+}
+
+@InProceedings{polikarpova-15,
+ author = "Nadia Polikarpova and Julian Tschannen and Carlo A.
+ Furia",
+ title = "A Fully Verified Container Library",
+ booktitle = fm,
+ pages = "414--434",
+ year = "2015",
+ series = lncs,
+ volume = "9109",
+ publisher = springer,
+ URL = "http://se.inf.ethz.ch/people/tschannen/publications/ptf-fm15.pdf",
+}
+
+@Article{pollack-sato-ricciotti-11,
+ author = "Randy Pollack and Masahiko Sato and Wilmer Ricciotti",
+ title = "A Canonical Locally Named Representation of Binding",
+ year = "2012",
+ journal = jar,
+ volume = "49",
+ number = "2",
+ pages = "185--207",
+ URL = "http://homepages.inf.ed.ac.uk/rpollack/export/PollackSatoRicciottiJAR.pdf",
+}
+
+@InProceedings{poplmark,
+ author = "Brian E. Aydemir and Aaron Bohannon and Matthew
+ Fairbairn and J. Nathan Foster and Benjamin C. Pierce
+ and Peter Sewell and Dimitrios Vytiniotis and Geoffrey
+ Washburn and Stephanie Weirich and Steve Zdancewic",
+ title = "Mechanized Metatheory for the Masses: The
+ \textsc{PoplMark} Challenge",
+ booktitle = tphol,
+ year = "2005",
+ series = lncs,
+ volume = "3603",
+ pages = "50--65",
+ publisher = springer,
+ URL = "http://research.microsoft.com/en-us/people/dimitris/poplmark.pdf",
+}
+
+@Misc{popuri-bison-06,
+ author = "Satya Kiran Popuri",
+ title = "Understanding {C} parsers generated by {GNU Bison}",
+ year = "2006",
+ URL = "http://www.cs.uic.edu/~spopuri/cparser.html",
+}
+
+@InCollection{potanin-13,
+ author = "Alex Potanin and Johan {\"{O}}stlund and Yoav Zibin
+ and Michael D. Ernst",
+ title = "Immutability",
+ booktitle = "Aliasing in Object-Oriented Programming. Types,
+ Analysis and Verification",
+ pages = "233--269",
+ year = "2013",
+ series = lncs,
+ volume = "7850",
+ publisher = springer,
+ URL = "https://homes.cs.washington.edu/~mernst/pubs/immutability-aliasing-2013-lncs7850.pdf",
+}
+
+@InProceedings{pottier-alphacaml,
+ author = "François Pottier",
+ title = "An overview of {C$\alpha$ml}",
+ year = "2006",
+ booktitle = "ACM Workshop on ML",
+ pages = "27--52",
+ volume = "148",
+ number = "2",
+ series = entcs,
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-alphacaml.pdf",
+}
+
+@Misc{pottier-alphacaml-software,
+ author = "François Pottier",
+ title = "{C$\alpha$ml}",
+ year = "2005",
+ URL = "http://gallium.inria.fr/~fpottier/alphaCaml/",
+}
+
+@InProceedings{pottier-antiframe-08,
+ author = "François Pottier",
+ title = "Hiding local state in direct style: a higher-order
+ anti-frame rule",
+ year = "2008",
+ booktitle = lics,
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-antiframe-2008.pdf",
+ pages = "331--340",
+}
+
+@Unpublished{pottier-caf,
+ author = "François Pottier",
+ title = "Three comments on the anti-frame rule",
+ note = "Unpublished",
+ year = "2009",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-caf-2009.pdf",
+}
+
+@InProceedings{pottier-conchon-icfp-00,
+ author = "François Pottier and Sylvain Conchon",
+ title = "Information Flow Inference for Free",
+ booktitle = icfp,
+ year = "2000",
+ pages = "46--57",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-conchon-icfp00.ps.gz",
+}
+
+@InProceedings{pottier-cpp-17,
+ author = "François Pottier",
+ title = "Verifying a hash table and its iterators in
+ higher-order separation logic",
+ booktitle = cpp,
+ year = "2017",
+ pages = "3--16",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-hashtable.pdf",
+}
+
+@InProceedings{pottier-csfw-02,
+ author = "François Pottier",
+ title = "A Simple View of Type-Secure Information Flow in the
+ $\pi$-Calculus",
+ year = "2002",
+ booktitle = csfw,
+ pages = "320--330",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-csfw15.ps.gz",
+}
+
+@TechReport{pottier-dea-95,
+ author = "François Pottier",
+ title = "Implémentation d'un système de modules évolué en
+ {Caml-Light}",
+ institution = "INRIA",
+ number = "2449",
+ type = "Research Report",
+ year = "1995",
+ URL = "http://gallium.inria.fr/~fpottier/publis/memoire-dea.ps.gz",
+}
+
+@Unpublished{pottier-dfs-scc-15,
+ author = "François Pottier",
+ title = "Depth-First Search and Strong Connectivity in {Coq}",
+ year = "2014",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-dfs-scc.pdf",
+ note = "Submitted for publication",
+}
+
+@InProceedings{pottier-esop-00,
+ author = "François Pottier",
+ title = "A 3-part type inference engine",
+ booktitle = esop,
+ publisher = springer,
+ series = lncs,
+ volume = "1782",
+ pages = "320--335",
+ year = "2000",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-esop-2000.ps.gz",
+}
+
+@Unpublished{pottier-gaf,
+ author = "François Pottier",
+ title = "Generalizing the higher-order frame and anti-frame
+ rules",
+ note = "Unpublished",
+ year = "2009",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-gaf-2009.pdf",
+}
+
+@InProceedings{pottier-gauthier-04,
+ author = "François Pottier and Nadji Gauthier",
+ title = "Polymorphic Typed Defunctionalization",
+ booktitle = popl,
+ year = "2004",
+ pages = "89--98",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-gauthier-popl04.pdf",
+}
+
+@Article{pottier-gauthier-hosc,
+ author = "François Pottier and Nadji Gauthier",
+ title = "Polymorphic Typed Defunctionalization and
+ Concretization",
+ journal = hosc,
+ year = "2006",
+ volume = "19",
+ pages = "125--162",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-gauthier-hosc.pdf",
+}
+
+@InProceedings{pottier-gdr-95,
+ author = "François Pottier",
+ title = "Type inference and simplification for recursively
+ constrained types",
+ booktitle = "Actes du {GDR} Programmation 1995 (journée du pôle
+ Programmation Fonctionnelle)",
+ year = "1995",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-gdr-95.ps.gz",
+}
+
+@TechReport{pottier-hmx-01,
+ author = "François Pottier",
+ title = "A semi-syntactic soundness proof for {HM$(X)$}",
+ institution = "INRIA",
+ number = "4150",
+ type = "Research Report",
+ year = "2001",
+ URL = "http://hal.inria.fr/docs/00/07/24/75/PDF/RR-4150.pdf",
+}
+
+@Article{pottier-ic-01,
+ author = "François Pottier",
+ title = "Simplifying subtyping constraints: a theory",
+ journal = ic,
+ year = "2001",
+ volume = "170",
+ number = "2",
+ pages = "153--183",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-ic01.ps.gz",
+}
+
+@InProceedings{pottier-icfp-96,
+ author = "François Pottier",
+ title = "Simplifying subtyping constraints",
+ booktitle = icfp,
+ year = "1996",
+ pages = "122--133",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-icfp96.ps.gz",
+}
+
+@InProceedings{pottier-icfp-98,
+ author = "François Pottier",
+ title = "A Framework for Type Inference with Subtyping",
+ booktitle = icfp,
+ year = "1998",
+ pages = "228--238",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-icfp98.ps.gz",
+}
+
+@InProceedings{pottier-lics-03,
+ author = "François Pottier",
+ title = "A Constraint-Based Presentation and Generalization of
+ Rows",
+ year = "2003",
+ booktitle = lics,
+ pages = "331--340",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-lics03.ps.gz",
+}
+
+@InProceedings{pottier-lics-07,
+ author = "François Pottier",
+ title = "Static name control for {FreshML}",
+ booktitle = lics,
+ year = "2007",
+ pages = "356--365",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-pure-freshml.pdf",
+}
+
+@Article{pottier-njc-00,
+ author = "François Pottier",
+ title = "A Versatile Constraint-Based Type Inference System",
+ journal = njc,
+ year = "2000",
+ volume = "7",
+ number = "4",
+ pages = "312--347",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-njc-2000.ps.gz",
+}
+
+@Misc{pottier-notes-dea,
+ author = "Xavier Leroy and François Pottier",
+ title = "Notes du cours de {DEA} «~Typage et
+ programmation~»",
+ year = "2002",
+ URL = "http://gallium.inria.fr/~fpottier/dea/dea-typage.ps.gz",
+}
+
+@TechReport{pottier-phd-english-98,
+ author = "François Pottier",
+ title = "Type inference in the presence of subtyping: from
+ theory to practice",
+ institution = "INRIA",
+ number = "3483",
+ type = "Research Report",
+ year = "1998",
+ URL = "http://hal.inria.fr/docs/00/07/32/05/PDF/RR-3483.pdf",
+}
+
+@PhdThesis{pottier-phd-french-98,
+ author = "François Pottier",
+ title = "Synthèse de types en présence de sous-typage: de la
+ théorie à la pratique",
+ school = "Université Paris 7",
+ year = "1998",
+ URL = "http://gallium.inria.fr/~fpottier/publis/these-fpottier.ps.gz",
+}
+
+@InProceedings{pottier-protzenko-13,
+ author = "François Pottier and Jonathan Protzenko",
+ title = "Programming with permissions in {Mezzo}",
+ booktitle = icfp,
+ year = "2013",
+ pages = "173--184",
+ URL = "http://gallium.inria.fr/~fpottier/publis/pottier-protzenko-mezzo.pdf",
+}
+
+@InProceedings{pottier-protzenko-lessons-mezzo-15,
+ author = "François Pottier and Jonathan Protzenko",
+ title = "A few lessons from the {Mezzo} project",
+ booktitle = snapl,
+ year = "2015",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-protzenko-lessons-mezzo.pdf",
+}
+
+@InProceedings{pottier-reachability-cc-2016,
+ author = "François Pottier",
+ title = "Reachability and error diagnosis in {LR}(1) parsers",
+ booktitle = cc,
+ year = "2016",
+ pages = "88--98",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-reachability-cc2016.pdf",
+}
+
+@InProceedings{pottier-reachability-jfla-2016,
+ author = "François Pottier",
+ title = "Reachability and error diagnosis in {LR}(1) automata",
+ booktitle = jfla,
+ year = "2016",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-reachability-jfla2016.pdf",
+}
+
+@InProceedings{pottier-regis-gianas-06,
+ author = "François Pottier and Yann Régis-Gianas",
+ title = "Stratified type inference for generalized algebraic
+ data types",
+ booktitle = popl,
+ year = "2006",
+ pages = "232--244",
+ URL = "http://gallium.inria.fr/~fpottier/publis/pottier-regis-gianas-popl06.pdf",
+}
+
+@Article{pottier-regis-gianas-typed-lr,
+ author = "François Pottier and Yann {Régis-Gianas}",
+ title = "Towards efficient, typed {LR} parsers",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-regis-gianas-typed-lr.pdf",
+ year = "2006",
+ pages = "155--180",
+ journal = entcs,
+ volume = "148",
+ number = "2",
+}
+
+@InCollection{pottier-remy-emlti,
+ author = "François Pottier and Didier Rémy",
+ title = "The Essence of {ML} Type Inference",
+ booktitle = "Advanced Topics in Types and Programming Languages",
+ pages = "389--489",
+ publisher = mitp,
+ year = "2005",
+ editor = "Benjamin C. Pierce",
+ chapter = "10",
+ URL = "http://gallium.inria.fr/~fpottier/publis/emlti-final.pdf",
+}
+
+@Unpublished{pottier-remy-emlti-long,
+ author = "François Pottier and Didier Rémy",
+ title = "The Essence of {ML} Type Inference",
+ note = "Draft of an extended version. Unpublished",
+ year = "2003",
+ URL = "http://cristal.inria.fr/attapl/emlti-long.pdf",
+}
+
+@InProceedings{pottier-simonet-02,
+ author = "François Pottier and Vincent Simonet",
+ title = "Information Flow Inference for {ML}",
+ booktitle = popl,
+ year = "2002",
+ pages = "319--330",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-simonet-popl02.ps.gz",
+}
+
+@Article{pottier-simonet-toplas-03,
+ author = "François Pottier and Vincent Simonet",
+ title = "Information Flow Inference for {ML}",
+ year = "2003",
+ volume = "25",
+ number = "1",
+ pages = "117--158",
+ journal = toplas,
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-simonet-toplas.ps.gz",
+}
+
+@InProceedings{pottier-skalka-smith-01,
+ author = "François Pottier and Christian Skalka and Scott
+ Smith",
+ title = "A Systematic Approach to Static Access Control",
+ booktitle = esop,
+ publisher = springer,
+ series = lncs,
+ volume = "2028",
+ pages = "30--45",
+ year = "2001",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-skalka-smith-esop01.ps.gz",
+}
+
+@Article{pottier-skalka-smith-05,
+ author = "François Pottier and Christian Skalka and Scott
+ Smith",
+ title = "A Systematic Approach to Static Access Control",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-skalka-smith-toplas.ps.gz",
+ volume = "27",
+ number = "2",
+ pages = "344--382",
+ journal = toplas,
+ year = "2005",
+}
+
+@Article{pottier-ssphs-13,
+ author = "François Pottier",
+ title = "Syntactic soundness proof of a type-and-capability
+ system with hidden state",
+ journal = jfp,
+ volume = "23",
+ number = "1",
+ pages = "38--144",
+ year = "2013",
+ URL = "http://gallium.inria.fr/~fpottier/publis/fpottier-ssphs.pdf",
+}
+
+@Misc{pottier-wallace,
+ author = "François Pottier",
+ title = "Wallace: an efficient implementation of type inference
+ with subtyping",
+ year = "2000",
+ URL = "http://gallium.inria.fr/~fpottier/wallace/",
+}
+
+@InCollection{pottinger-80,
+ author = "Garrel Pottinger",
+ title = "A type assignment for the strongly normalizable
+ $\lambda$-terms",
+ booktitle = "To H. B. Curry: Essays on Combinatory Logic, Lambda
+ Calculus, and Formalism",
+ pages = "561--577",
+ publisher = ap,
+ year = "1980",
+ editor = "J. Roger Hindley and Jonathan P. Seldin",
+}
+
+@InProceedings{pouillard-11,
+ author = "Nicolas Pouillard",
+ title = "Nameless, painless",
+ booktitle = icfp,
+ year = "2011",
+ pages = "320--332",
+ URL = "http://nicolaspouillard.fr/publis/nameless-painless.pdf",
+}
+
+@InProceedings{pouillard-pottier-10,
+ author = "Nicolas Pouillard and François Pottier",
+ title = "A fresh look at programming with names and binders",
+ booktitle = icfp,
+ year = "2010",
+ pages = "217--228",
+ URL = "http://gallium.inria.fr/~fpottier/publis/pouillard-pottier-fresh-look.pdf",
+}
+
+@Article{pouillard-pottier-12,
+ author = "Nicolas Pouillard and François Pottier",
+ title = "A unified treatment of syntax with binders",
+ journal = jfp,
+ volume = "22",
+ number = "4--5",
+ pages = "614--704",
+ year = "2012",
+ URL = "http://gallium.inria.fr/~fpottier/publis/pouillard-pottier-unified.pdf",
+}
+
+@Article{pratt-tiuryn-96,
+ author = "Vaughan Pratt and Jerzy Tiuryn",
+ title = "Satisfiability of Inequalities in a Poset",
+ journal = fundamenta,
+ year = "1996",
+ volume = "28",
+ number = "1--2",
+ pages = "165--182",
+ URL = "ftp://ftp.mimuw.edu.pl/pub/users/tiuryn/sat-ineq.ps.gz",
+}
+
+@Article{pretnar-15,
+ author = "Matija Pretnar",
+ title = "An Introduction to Algebraic Effects and Handlers",
+ journal = entcs,
+ volume = "319",
+ pages = "19--35",
+ year = "2015",
+ URL = "http://www.eff-lang.org/handlers-tutorial.pdf",
+}
+
+@Misc{programatica-04,
+ author = "Thomas Hallgren and James Hook and Mark P. Jones and
+ Richard Kieburtz",
+ title = "An overview of the {Programatica} ToolSet",
+ howpublished = "High Confidence Software and Systems Conference
+ (HCSS)",
+ year = "2004",
+ URL = "http://ogi.altocumulus.org/~hallgren/Programatica/HCSS04/hcss04-tools.pdf",
+}
+
+@Book{proofs-and-types,
+ author = "Jean-Yves Girard and Yves Lafont and Paul Taylor",
+ title = "Proofs and Types",
+ publisher = cup,
+ year = "1990",
+ URL = "http://www.paultaylor.eu/stable/prot.pdf",
+}
+
+@PhdThesis{protzenko-phd-14,
+ author = "Jonathan Protzenko",
+ title = "{Mezzo}: a typed language for safe effectful
+ concurrent programs",
+ year = "2014",
+ school = "Université Paris Diderot",
+ URL = "https://hal.inria.fr/tel-01086106/document",
+}
+
+@InProceedings{pugh-weddell-90,
+ author = "William Pugh and Grant Weddell",
+ title = "Two-directional record layout for multiple
+ inheritance",
+ booktitle = pldi,
+ pages = "85--91",
+ year = "1990",
+ URL = "http://doi.acm.org/10.1145/93542.93556",
+}
+
+@Article{purdom-74,
+ author = "Paul Purdom",
+ title = "The size of {LALR(1)} parsers",
+ year = "1974",
+ journal = "BIT Numerical Mathematics",
+ volume = "14",
+ number = "3",
+ URL = "http://dx.doi.org/10.1007/BF01933232",
+ publisher = kluwer,
+ pages = "326--337",
+}
+
+@Article{qian-96,
+ author = "Zhenyu Qian",
+ title = "Unification of higher-order patterns in linear time
+ and space",
+ journal = jlc,
+ year = "1996",
+ volume = "6",
+ number = "3",
+ pages = "315--341",
+}
+
+@TechReport{raffalli-98,
+ author = "Christophe Raffalli",
+ title = "Type checking in system ${F}^\eta$",
+ institution = "LAMA, Université de Savoie",
+ year = "1998",
+ type = "Prépublication",
+ number = "98-05a",
+ URL = "ftp://www.lama.univ-savoie.fr/pub/users/RAFFALLI/Papers/Feta-partial.ps",
+}
+
+@Unpublished{raffalli-99,
+ author = "Christophe Raffalli",
+ title = "An optimized complete semi-algorithm for system
+ ${F}^\eta$",
+ note = "Unpublished",
+ year = "1999",
+ URL = "ftp://www.lama.univ-savoie.fr/pub/users/RAFFALLI/Papers/Feta-total.ps",
+}
+
+@InProceedings{ramachandran-93,
+ author = "Viswanath Ramachandran and Pascal Van Hentenryck",
+ title = "Incremental Algorithms for Constraint Solving and
+ Entailment over Rational Trees",
+ booktitle = fsttcs,
+ pages = "205--217",
+ year = "1993",
+}
+
+@InProceedings{ramalingam-02,
+ author = "G. Ramalingam and Alex Varshavsky and John Field and
+ Deepak Goyal and Shmuel Sagiv",
+ title = "Deriving Specialized Program Analyses for Certifying
+ Component-Client Conformance",
+ booktitle = pldi,
+ pages = "83--94",
+ year = "2002",
+ URL = "http://pages.cs.wisc.edu/~ramali/Papers/pldi02.pdf",
+}
+
+@Book{real-world-ocaml,
+ author = "Yaron Minsky and Anil Madhavapeddy and Jason Hickey",
+ title = "Real World {OCaml}: Functional programming for the
+ masses",
+ publisher = "O'Reilly",
+ year = "2013",
+ URL = "https://realworldocaml.org/",
+}
+
+@InProceedings{recursive-alias-types-00,
+ author = "David Walker and Greg Morrisett",
+ title = "Alias Types for Recursive Data Structures",
+ booktitle = tic,
+ year = "2000",
+ series = lncs,
+ volume = "2071",
+ pages = "177--206",
+ publisher = springer,
+ URL = "http://www.cs.cornell.edu/talc/papers/alias-recursion.pdf",
+}
+
+@TechReport{reed-15,
+ author = "Eric Reed",
+ title = "Patina: {A} Formalization of the {Rust} Programming
+ Language",
+ institution = "University of Washington",
+ year = "2015",
+ number = "UW-CSE-15-03-02",
+ URL = "ftp://ftp.cs.washington.edu/tr/2015/03/UW-CSE-15-03-02.pdf",
+}
+
+@InProceedings{regensburger-holcf-95,
+ author = "Franz Regensburger",
+ title = "{HOLCF}: Higher Order Logic of Computable Functions",
+ booktitle = tphol,
+ year = "1995",
+ pages = "293--307",
+ publisher = springer,
+ series = lncs,
+ volume = "971",
+ URL = "http://www4.informatik.tu-muenchen.de/publ/papers/Regensburger_HOLT1995.pdf",
+}
+
+@PhdThesis{regis-gianas-07,
+ author = "Yann Régis-Gianas",
+ title = "Des types aux assertions logiques : preuve automatique
+ ou assistée de propriétés sur les programmes
+ fonctionnels",
+ school = "Université Paris 7",
+ year = "2007",
+ URL = "http://gallium.inria.fr/~regisgia/these-yann.regis-gianas.pdf",
+}
+
+@InProceedings{regis-gianas-pottier-08,
+ author = "Yann Régis-Gianas and François Pottier",
+ title = "A {Hoare} Logic for Call-by-Value Functional
+ Programs",
+ booktitle = mpc,
+ year = "2008",
+ series = lncs,
+ volume = "5133",
+ publisher = springer,
+ URL = "http://gallium.inria.fr/~fpottier/publis/regis-gianas-pottier-hoarefp.pdf",
+ pages = "305--335",
+}
+
+@InProceedings{rehof-faehndrich-01,
+ author = "Jakob Rehof and Manuel Fähndrich",
+ title = "Type-Based Flow Analysis: From Polymorphic Subtyping
+ to {CFL}-Reachability",
+ booktitle = popl,
+ pages = "54--66",
+ year = "2001",
+ URL = "http://research.microsoft.com/~rehof/popl01.ps",
+}
+
+@TechReport{rehof-minimality-96,
+ author = "Jakob Rehof",
+ year = "1996",
+ title = "Minimal Typings in Atomic Subtyping",
+ institution = "Department of Computer Science, University of
+ Copenhagen",
+ number = "D-278",
+ URL = "ftp://ftp.diku.dk/diku/semantics/papers/D-278.ps.gz",
+}
+
+@InProceedings{rehof-minimality-97,
+ author = "Jakob Rehof",
+ title = "Minimal Typings in Atomic Subtyping",
+ booktitle = popl,
+ year = "1997",
+ pages = "278--291",
+ URL = "http://research.microsoft.com/~rehof/popl97.ps",
+}
+
+@InProceedings{reistad-gifford-94,
+ author = "Brian Reistad and David K. Gifford",
+ title = "Static dependent costs for estimating execution time",
+ booktitle = lfp,
+ year = "1994",
+ pages = "65--78",
+ URL = "https://groups.csail.mit.edu/cgs/pubs/lfp94.pdf",
+}
+
+@InProceedings{remy-89,
+ author = "Didier Rémy",
+ title = "Type checking records and variants in a natural
+ extension of {ML}",
+ booktitle = popl,
+ pages = "77--88",
+ year = "1989",
+ URL = "http://doi.acm.org/10.1145/75277.75284",
+}
+
+@InProceedings{remy-efficient-records-92,
+ author = "Didier Rémy",
+ title = "Efficient Representation of Extensible Records",
+ booktitle = mlapp,
+ year = "1992",
+ URL = "http://gallium.inria.fr/~remy/ftp/eff-repr-of-ext-records.pdf",
+}
+
+@TechReport{remy-equational-92,
+ author = "Didier R{\'e}my",
+ title = "Extending {ML} Type System with a Sorted Equational
+ Theory",
+ institution = "INRIA",
+ number = "1766",
+ year = "1992",
+ URL = "http://gallium.inria.fr/~remy/ftp/eq-theory-on-types.pdf",
+}
+
+@InProceedings{remy-esop-98,
+ author = "Didier R{\'e}my",
+ title = "From Classes to Objects via Subtyping",
+ booktitle = esop,
+ year = "1998",
+ series = lncs,
+ publisher = springer,
+ volume = "1381",
+ pages = "200--220",
+ URL = "http://gallium.inria.fr/~remy/ftp/classes-to-objects.pdf",
+}
+
+@InCollection{remy-for-free-94,
+ author = "Didier R{\'e}my",
+ title = "Typing Record Concatenation for Free",
+ booktitle = "Theoretical Aspects Of Object-Oriented Programming.
+ Types, Semantics and Language Design",
+ publisher = mitp,
+ year = "1994",
+ editor = "Carl A. Gunter and John C. Mitchell",
+ URL = "http://gallium.inria.fr/~remy/ftp/taoop2.pdf",
+}
+
+@InProceedings{remy-icfp-05,
+ author = "Didier Rémy",
+ title = "Simple, partial type inference for System ${F}$ based
+ on type containment",
+ booktitle = icfp,
+ year = "2005",
+ URL = "http://gallium.inria.fr/~remy/work/fml/fml-icfp.pdf",
+}
+
+@InProceedings{remy-icfp05,
+ author = "Didier Rémy",
+ title = "Simple, partial type inference for System ${F}$ based
+ on type containment",
+ booktitle = icfp,
+ year = "2005",
+ URL = "http://gallium.inria.fr/~remy/work/fml/fml-icfp.pdf",
+}
+
+@InProceedings{remy-lfp-92,
+ author = "Didier R{\'e}my",
+ title = "Projective {ML}",
+ booktitle = lfp,
+ pages = "66--75",
+ year = "1992",
+ URL = "http://gallium.inria.fr/~remy/ftp/lfp92.pdf",
+}
+
+@InProceedings{remy-mlart-94,
+ author = "Didier R{\'e}my",
+ title = "Programming Objects with {ML-ART}: An extension to
+ {ML} with Abstract and Record Types",
+ booktitle = tacs,
+ year = "1994",
+ pages = "321--346",
+ publisher = springer,
+ URL = "http://gallium.inria.fr/~remy/ftp/tacs94.pdf",
+}
+
+@Misc{remy-newton-95,
+ author = "Didier R{\'e}my",
+ title = "A case study of typechecking with constrained types:
+ Typing record concatenation",
+ howpublished = "Workshop on Advances in Types for Computer Science",
+ year = "1995",
+ URL = "http://gallium.inria.fr/~remy/work/sub-concat.dvi.gz",
+}
+
+@InCollection{remy-records-94,
+ author = "Didier R{\'e}my",
+ title = "Type Inference for Records in a Natural Extension of
+ {ML}",
+ booktitle = "Theoretical Aspects Of Object-Oriented Programming:
+ Types, Semantics and Language Design",
+ publisher = mitp,
+ year = "1994",
+ editor = "Carl A. Gunter and John C. Mitchell",
+ URL = "http://gallium.inria.fr/~remy/ftp/taoop1.pdf",
+}
+
+@TechReport{remy-start-93,
+ author = "Didier R{\'e}my",
+ title = "Syntactic Theories and the Algebra of Record Terms",
+ institution = "INRIA",
+ number = "1869",
+ year = "1993",
+ type = "Research Report",
+ URL = "http://gallium.inria.fr/~remy/ftp/record-algebras.pdf",
+}
+
+@InProceedings{remy-vouillon-objective-ml-97,
+ author = "Didier R{\'e}my and J{\'e}r{\^o}me Vouillon",
+ title = "{Objective} {ML}: {A} simple object-oriented extension
+ of {ML}",
+ booktitle = popl,
+ year = "1997",
+ pages = "40--53",
+ URL = "http://gallium.inria.fr/~remy/ftp/objective-ml!popl97.pdf",
+}
+
+@Article{remy-vouillon-objective-ml-98,
+ author = "Didier R{\'e}my and J{\'e}r{\^o}me Vouillon",
+ title = "{Objective} {ML}: {An} effective object-oriented
+ extension to {ML}",
+ journal = tapos,
+ year = "1998",
+ pages = "27--50",
+ volume = "4",
+ number = "1",
+ URL = "http://gallium.inria.fr/~remy/ftp/objective-ml!tapos98.pdf",
+}
+
+@Article{remy-yakobowski-11,
+ author = "Didier R{\'e}my and Boris Yakobowski",
+ title = "A {Church}-Style Intermediate Language for {MLF}",
+ journal = tcs,
+ year = "2012",
+ volume = "435",
+ number = "1",
+ pages = "77--105",
+ URL = "http://gallium.inria.fr/~remy/mlf/Remy-Yakobowski:xmlf@tcs2011.pdf",
+}
+
+@Article{reps-98,
+ author = "Thomas Reps",
+ title = "Program analysis via graph reachability",
+ journal = ist,
+ year = "1998",
+ volume = "40",
+ number = "11--12",
+ pages = "701--726",
+ URL = "http://www.cs.wisc.edu/wpis/papers/tr1386.pdf",
+}
+
+@PhdThesis{retert-09,
+ author = "William S. Retert",
+ title = "Implementing Permission Analysis",
+ school = "University of Wisconsin-Milwaukee",
+ year = "2009",
+}
+
+@InProceedings{reus-schwinghammer-06,
+ title = "Separation Logic for Higher-order Store",
+ year = "2006",
+ author = "Bernhard Reus and Jan Schwinghammer",
+ booktitle = csl,
+ series = lncs,
+ volume = "4207",
+ publisher = springer,
+ pages = "575--590",
+ URL = "http://www.ps.uni-sb.de/Papers/abstracts/seplogic-hos.pdf",
+}
+
+@Article{revuz-92,
+ author = "Dominique Revuz",
+ title = "Minimization of acyclic deterministic automata in
+ linear time",
+ journal = tcs,
+ volume = "92",
+ number = "1",
+ year = "1992",
+ pages = "181--189",
+}
+
+@InProceedings{reynolds-02,
+ author = "John C. Reynolds",
+ title = "Separation Logic: {A} Logic for Shared Mutable Data
+ Structures",
+ booktitle = lics,
+ pages = "55--74",
+ year = "2002",
+ URL = "http://www.cs.cmu.edu/~jcr/seplogic.pdf",
+}
+
+@InProceedings{reynolds-69,
+ author = "John C. Reynolds",
+ title = "Automatic Computation of Data Set Definitions",
+ booktitle = "Information Processing 68",
+ volume = "1",
+ publisher = "North Holland",
+ year = "1969",
+ pages = "456--461",
+}
+
+@InProceedings{reynolds-74,
+ author = "John C. Reynolds",
+ title = "Towards a theory of type structure",
+ booktitle = "Colloque sur la Programmation",
+ pages = "408--425",
+ year = "1974",
+ volume = "19",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.springerlink.com/content/p5801737k78207p7/",
+}
+
+@TechReport{reynolds-75,
+ author = "John C. Reynolds",
+ title = "User-defined Types and Procedural Data Structures as
+ Complementary Approaches to Data Abstraction",
+ institution = "Carnegie Mellon University",
+ year = "1975",
+ number = "1278",
+ URL = "http://repository.cmu.edu/compsci/1278/",
+}
+
+@InProceedings{reynolds-78,
+ author = "John C. Reynolds",
+ title = "Syntactic control of interference",
+ booktitle = popl,
+ year = "1978",
+ pages = "39--46",
+ URL = "http://doi.acm.org/10.1145/512760.512766",
+}
+
+@InProceedings{reynolds-83,
+ author = "John C. Reynolds",
+ title = "Types, Abstraction and Parametric Polymorphism",
+ booktitle = "Information Processing 83",
+ publisher = elsevier,
+ year = "1983",
+ pages = "513--523",
+ URL = "http://www.cse.chalmers.se/edu/year/2010/course/DAT140_Types/Reynolds_typesabpara.pdf",
+}
+
+@InProceedings{reynolds-85,
+ author = "John C. Reynolds",
+ title = "Three Approaches to Type Structure",
+ booktitle = tapsoft,
+ series = lncs,
+ volume = "185",
+ publisher = springer,
+ year = "1985",
+ pages = "97--138",
+ URL = "http://dx.doi.org/10.1007/3-540-15198-2_7",
+}
+
+@Article{reynolds-98a,
+ author = "John C. Reynolds",
+ title = "Definitional Interpreters for Higher-Order Programming
+ Languages",
+ journal = "Higher-Order and Symbolic Computation",
+ volume = "11",
+ number = "4",
+ pages = "363--397",
+ year = "1998",
+ URL = "https://cs.au.dk/~hosc/local/HOSC-11-4-pp363-397.pdf",
+}
+
+@Article{reynolds-98b,
+ author = "John C. Reynolds",
+ title = "Definitional Interpreters Revisited",
+ journal = "Higher-Order and Symbolic Computation",
+ volume = "11",
+ number = "4",
+ pages = "355--361",
+ year = "1998",
+ URL = "https://cs.au.dk/~hosc/local/HOSC-11-4-pp355-361.pdf",
+}
+
+@InCollection{reynolds-abstraction-94,
+ author = "John C. Reynolds",
+ title = "User Defined Types and Procedural Data Structures as
+ Complementary Approaches to Data Abstraction",
+ booktitle = taoop,
+ publisher = mitp,
+ year = "1994",
+ pages = "13--23",
+ editor = "Carl A. Gunter and John C. Mitchell",
+}
+
+@InCollection{reynolds-intro-90,
+ author = "John C. Reynolds",
+ title = "An Introduction to the Polymorphic Lambda Calculus",
+ booktitle = "Logical Foundations of Functional Programming",
+ editor = "G{\'e}rard Huet",
+ publisher = aw,
+ year = "1990",
+ pages = "77--86",
+ URL = "http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.7.9916",
+}
+
+@Article{rhiger-03,
+ author = "Morten Rhiger",
+ title = "A Foundation for Embedded Languages",
+ journal = toplas,
+ year = "2003",
+ volume = "25",
+ number = "3",
+ pages = "291--315",
+ URL = "http://doi.acm.org/10.1145/641909.641910",
+}
+
+@InProceedings{riba-09,
+ author = "Colin Riba",
+ title = "On the Values of Reducibility Candidates",
+ booktitle = tlca,
+ year = "2009",
+ pages = "264--278",
+ publisher = springer,
+ series = lncs,
+ volume = "5608",
+ URL = "http://perso.ens-lyon.fr/colin.riba/papers/values.pdf",
+}
+
+@InProceedings{ringenburg-grossman-05,
+ author = "Michael F. Ringenburg and Dan Grossman",
+ title = "Types for Describing Coordinated Data Structures",
+ booktitle = tldi,
+ pages = "25--36",
+ year = "2005",
+ URL = "http://www.cs.washington.edu/homes/miker/coord/coordinated_tldi05.pdf",
+}
+
+@Article{rittri-89,
+ author = "Mikael Rittri",
+ title = "Using types as Search Keys in Function Libraries",
+ journal = jfp,
+ volume = "1",
+ number = "1",
+ pages = "71--89",
+ year = "1991",
+}
+
+@Article{rittri-93,
+ author = "Mikael Rittri",
+ title = "Retrieving library functions by unifying types modulo
+ linear isomorphism",
+ journal = rairo,
+ year = "1993",
+ volume = "27",
+ number = "6",
+ pages = "523--540",
+}
+
+@PhdThesis{rival-hdr,
+ author = "Xavier Rival",
+ title = "Abstract Domains for the Static Analysis of Programs
+ Manipulating Complex Data Structures",
+ school = "École Normale Supérieure",
+ year = "2011",
+ type = "Habilitation à diriger des recherches",
+ URL = "http://www.di.ens.fr/~rival/hdr.pdf",
+}
+
+@Article{robinson-65,
+ author = "J. Alan Robinson",
+ title = "A Machine-Oriented Logic Based on the Resolution
+ Principle",
+ journal = jacm,
+ year = "1965",
+ volume = "12",
+ number = "1",
+ pages = "23--41",
+ URL = "http://doi.acm.org/10.1145/321250.321253",
+}
+
+@InProceedings{rompf-amin-16,
+ author = "Tiark Rompf and Nada Amin",
+ title = "Type soundness for dependent object types {(DOT)}",
+ booktitle = oopsla,
+ pages = "624--641",
+ year = "2016",
+ URL = "http://lampwww.epfl.ch/~amin/dot/soundness_oopsla16.pdf",
+}
+
+@Article{ross-sagiv-98,
+ author = "John L. Ross and Mooly Sagiv",
+ title = "Building a Bridge between Pointer Aliases and Program
+ Dependences",
+ journal = njc,
+ volume = "5",
+ number = "4",
+ year = "1998",
+ mon = "Winter",
+ pages = "361--386",
+ URL = "http://www.math.tau.ac.il/~msagiv/njc98.ps",
+}
+
+@InProceedings{rossberg-15,
+ author = "Andreas Rossberg",
+ title = "{1ML} -- core and modules united ({F}-ing first-class
+ modules)",
+ booktitle = icfp,
+ pages = "35--47",
+ year = "2015",
+ URL = "https://people.mpi-sws.org/~rossberg/papers/Rossberg%20-%201ML%20--%20Core%20and%20modules%20united.pdf",
+}
+
+@Article{rossberg-russo-dreyer-14,
+ author = "Andreas Rossberg and Claudio V. Russo and Derek
+ Dreyer",
+ title = "{F}-ing modules",
+ journal = jfp,
+ volume = "24",
+ number = "5",
+ pages = "529--607",
+ year = "2014",
+ URL = "https://people.mpi-sws.org/~rossberg/papers/Rossberg,%20Russo,%20Dreyer%20-%20F-ing%20Modules%20[JFP].pdf",
+}
+
+@Article{runciman-toyn-91,
+ author = "Colin Runciman and Ian Toyn",
+ title = "Retrieving re-usable software components by
+ polymorphic type",
+ journal = jfp,
+ year = "1991",
+ pages = "191--211",
+ volume = "1",
+ number = "2",
+}
+
+@Book{russell-norvig-09,
+ author = "Stuart Russell and Peter Norvig",
+ title = "Artificial Intelligence: {A} Modern Approach",
+ publisher = prentice,
+ year = "2009",
+ URL = "http://aima.cs.berkeley.edu/",
+}
+
+@PhdThesis{russo-98,
+ school = "University of Edinburgh",
+ title = "Types For Modules",
+ year = "1998",
+ pages = "360",
+ author = "Claudio V. Russo",
+ URL = "http://www.dcs.ed.ac.uk/home/cvr/ECS-LFCS-98-389.html",
+}
+
+@Misc{rust,
+ title = "The {Rust} programming language",
+ author = "{The Mozilla foundation}",
+ year = "2014",
+ URL = "https://doc.rust-lang.org/book/",
+}
+
+@InProceedings{rust-14,
+ author = "Nicholas D. Matsakis and Felix S. {Klock,II}",
+ title = "The {Rust} Language",
+ booktitle = hilt,
+ year = "2014",
+ pages = "103--104",
+ URL = "http://doi.acm.org/10.1145/2663171.2663188",
+}
+
+@Unpublished{rust-servo-15,
+ author = "Brian Anderson and Lars Bergstrom and David Herman and
+ Josh Matthews and Keegan McAllister and Manish
+ Goregaokar and Jack Moffitt and Simon Sapin",
+ title = "Experience Report: Developing the {Servo} Web Browser
+ Engine using {Rust}",
+ year = "2015",
+ URL = "http://arxiv.org/abs/1505.07383",
+}
+
+@InProceedings{sabelfeld-sands-99,
+ author = "Andrei Sabelfeld and David Sands",
+ title = "A {PER} Model of Secure Information Flow in Sequential
+ Programs",
+ booktitle = esop,
+ volume = "1575",
+ series = lncs,
+ year = "1999",
+ publisher = springer,
+ pages = "40--58",
+ URL = "http://www.cse.chalmers.se/~andrei/esop99.ps",
+}
+
+@InProceedings{sabin-freuder-94,
+ author = "Daniel Sabin and Eugene C. Freuder",
+ title = "Contradicting Conventional Wisdom in Constraint
+ Satisfaction",
+ booktitle = ppcp,
+ publisher = springer,
+ series = lncs,
+ volume = "874",
+ year = "1994",
+ pages = "10--20",
+ URL = "http://4c.ucc.ie/web/upload/publications/inProc/sabin94contradicting.pdf",
+}
+
+@Article{sabry-98,
+ author = "Amr Sabry",
+ title = "What is a Purely Functional Language?",
+ journal = jfp,
+ year = "1998",
+ volume = "8",
+ number = "1",
+ pages = "1--22",
+ URL = "http://dx.doi.org/10.1017/S0956796897002943",
+}
+
+@InProceedings{sage-06,
+ author = "Jessica Gronski and Kenneth Knowles and Aaron Tomb and
+ Stephen N. Freund and Cormac Flanagan",
+ title = "{Sage}: Hybrid Checking for Flexible Specifications",
+ booktitle = "Scheme and Functional Programming",
+ year = "2006",
+ pages = "93--104",
+ URL = "http://www.cs.williams.edu/~freund/papers/06-sfp.pdf",
+}
+
+@TechReport{saha-al-98,
+ author = "Bratin Saha and Nevin Heintze and Dino Oliva",
+ title = "Subtransitive {CFA} using Types",
+ institution = "Yale University",
+ year = "1998",
+ number = "YALEU/DCS/TR-1166",
+ URL = "http://flint.cs.yale.edu/flint/publications/cfa.ps.gz",
+}
+
+@InProceedings{sands-90,
+ author = "David Sands",
+ title = "Complexity Analysis for a Lazy Higher-Order Language",
+ booktitle = esop,
+ pages = "361--376",
+ year = "1990",
+ series = lncs,
+ volume = "432",
+ publisher = springer,
+ URL = "http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.42.9125",
+}
+
+@InProceedings{sands-gustavsson-moran-02,
+ author = "David Sands and J{\"{o}}rgen Gustavsson and Andrew
+ Moran",
+ title = "Lambda Calculi and Linear Speedups",
+ booktitle = "The Essence of Computation, Complexity, Analysis,
+ Transformation. Essays Dedicated to Neil D. Jones",
+ pages = "60--84",
+ year = "2002",
+ volume = "2566",
+ publisher = springer,
+ series = lncs,
+ URL = "http://www.cse.chalmers.se/~dave/papers/Sands-Gustavsson-Moran.pdf",
+}
+
+@Article{sangiorgi-98,
+ author = "Davide Sangiorgi",
+ title = "On the bisimulation proof method",
+ journal = mscs,
+ volume = "8",
+ number = "5",
+ pages = "447--479",
+ year = "1998",
+ URL = "http://www.cs.unibo.it/~sangio/DOC_public/bis-proof.ps.gz",
+}
+
+@InProceedings{sansom-93,
+ author = "Patrick M. Sansom",
+ title = "Time profiling a lazy functional compiler",
+ booktitle = "Functional Programming, Workshops in Computing",
+ year = "1993",
+ publisher = springer,
+ URL = "ftp://ftp.dcs.glasgow.ac.uk/pub/glasgow-fp/authors/Patrick_Sansom/1993_profiling-compiler_GLASGOWFP.ps.gz",
+}
+
+@Book{scala,
+ author = "Martin Odersky and Lex Spoon and Bill Venners",
+ title = "Programming in {Scala}, Third Edition: {A}
+ Comprehensive Step-by-step Guide",
+ year = "2016",
+ publisher = "Artima Incorporation",
+ URL = "http://www.artima.com/shop/programming_in_scala_3ed",
+}
+
+@InProceedings{scala-05,
+ author = "Martin Odersky and Matthias Zenger",
+ title = "Scalable Component Abstractions",
+ booktitle = oopsla,
+ pages = "41--57",
+ year = "2005",
+ URL = "http://lamp.epfl.ch/~odersky/papers/ScalableComponent.pdf",
+}
+
+@PhdThesis{schimpf-81,
+ author = "Karl Max Schimpf",
+ title = "Construction Methods of {LR} Parsers",
+ school = "University of Pennsylvania",
+ year = "1981",
+ URL = "http://repository.upenn.edu/cis_reports/725/",
+}
+
+@Article{schneider-00,
+ author = "Fred B. Schneider",
+ title = "Enforceable security policies",
+ year = "2000",
+ journal = tissec,
+ volume = "3",
+ number = "1",
+ pages = "1--50",
+ URL = "http://www.cs.cornell.edu/fbs/publications/EnfSecPols.pdf",
+}
+
+@Book{schneider-97,
+ author = "Fred B. Schneider",
+ title = "On Concurrent Programming",
+ publisher = springer,
+ year = "1997",
+}
+
+@InProceedings{schroeder-mossakowski-02,
+ author = "Lutz Schr{\"o}der and Till Mossakowski",
+ title = "{HasCASL}: Towards Integrated Specification and
+ Development of Functional Programs",
+ booktitle = amast,
+ year = "2002",
+ pages = "99--116",
+ publisher = springer,
+ series = lncs,
+ volume = "2422",
+ URL = "http://www.informatik.uni-bremen.de/~lschrode/hascasl/recursion.ps",
+}
+
+@Article{schubert-83,
+ author = "Lenhart K. Schubert and Mary Angela Papalaskaris and
+ Jay Taugher",
+ title = "Determining Type, Part, Color, and Time
+ Relationships",
+ journal = computer,
+ volume = "16",
+ number = "10",
+ pages = "53--60",
+ year = "1983",
+}
+
+@TechReport{schwartzbach-95,
+ author = "Michael I. Schwartzbach",
+ title = "Polymorphic Type Inference",
+ institution = "BRICS",
+ year = "1995",
+ number = "BRICS-LS-95-3",
+ URL = "http://www.brics.dk/LS/95/3/BRICS-LS-95-3.ps.gz",
+}
+
+@InProceedings{schwinghammer-birkedal-stovring-11,
+ author = "Jan Schwinghammer and Lars Birkedal and Kristian
+ Støvring",
+ title = "A step-indexed {Kripke} model of hidden state via
+ recursive properties on recursively defined metric
+ spaces",
+ booktitle = fossacs,
+ year = "2011",
+ number = "6604",
+ pages = "305--319",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.itu.dk/~birkedal/papers/relpoms-antiframe-conf.pdf",
+}
+
+@InProceedings{schwinghammer-csl-09,
+ author = "Jan Schwinghammer and Lars Birkedal and Bernhard Reus
+ and Hongseok Yang",
+ title = "Nested {Hoare} triples and frame rules for
+ higher-order store",
+ booktitle = csl,
+ pages = "440--454",
+ year = "2009",
+ volume = "5771",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.itu.dk/~birkedal/papers/nested-triples-conf.pdf",
+}
+
+@InProceedings{schwinghammer-sfhs-10,
+ author = "Jan Schwinghammer and Hongseok Yang and Lars Birkedal
+ and François Pottier and Bernhard Reus",
+ title = "A Semantic Foundation for Hidden State",
+ booktitle = fossacs,
+ year = "2010",
+ pages = "2--17",
+ publisher = springer,
+ series = lncs,
+ volume = "6014",
+ URL = "http://gallium.inria.fr/~fpottier/publis/sfhs.pdf",
+}
+
+@PhdThesis{schwoon-02,
+ author = "Stefan Schwoon",
+ title = "Model-Checking Pushdown Systems",
+ school = "Technische Universit{\"a}t M{\"u}nchen",
+ year = "2002",
+ URL = "http://www.lsv.ens-cachan.fr/Publis/PAPERS/PDF/schwoon-phd02.pdf",
+}
+
+@Article{scott-lcf-93,
+ author = "Dana S. Scott",
+ title = "A Type-Theoretical Alternative to {ISWIM}, {CUCH},
+ {OWHY}",
+ journal = tcs,
+ volume = "121",
+ number = "1--2",
+ year = "1993",
+ pages = "411--440",
+ URL = "http://dx.doi.org/10.1016/0304-3975(93)90095-B",
+}
+
+@Book{sedgewick-graphs-java,
+ author = "Robert Sedgewick and Michael Schidlowsky",
+ title = "Algorithms in {Java}: Graph Algorithms",
+ publisher = aw,
+ year = "2003",
+}
+
+@Article{seidel-sharir-05,
+ author = "Raimund Seidel and Micha Sharir",
+ title = "Top-Down Analysis of Path Compression",
+ journal = siamjc,
+ volume = "34",
+ number = "3",
+ pages = "515--525",
+ year = "2005",
+ URL = "http://dx.doi.org/10.1137/S0097539703439088",
+}
+
+@Article{sekar-al-95,
+ title = "Adaptive Pattern Matching",
+ author = "R. C. Sekar and R. Ramesh and I. V. Ramakrishnan",
+ pages = "1207--1234",
+ journal = siamjc,
+ year = "1995",
+ volume = "24",
+ number = "6",
+ URL = "http://seclab.cs.sunysb.edu/sekar/papers/adaptive.ps",
+ alturl = "http://locus.siam.org/fulltext/SICOMP/volume-24/0224073.pdf",
+}
+
+@Article{sethi-ullman-70,
+ author = "Ravi Sethi and J. D. Ullman",
+ title = "The Generation of Optimal Code for Arithmetic
+ Expressions",
+ journal = jacm,
+ volume = "17",
+ number = "4",
+ year = "1970",
+ pages = "715--728",
+ URL = "http://doi.acm.org/10.1145/321607.321620",
+}
+
+@InProceedings{sewell-vitek-00,
+ author = "Peter Sewell and Jan Vitek",
+ title = "Secure Composition of Untrusted Code: Wrappers and
+ Causality Types",
+ year = "2000",
+ booktitle = csfw,
+ URL = "http://www.cl.cam.ac.uk/users/pes20/wraptypes.ps",
+}
+
+@TechReport{sewell-vitek-99,
+ author = "Peter Sewell and Jan Vitek",
+ title = "Secure Composition of Untrusted Code: Wrappers and
+ Causality Types",
+ number = "478",
+ institution = "Computer Laboratory, University of Cambridge",
+ year = "1999",
+ URL = "http://www.cl.cam.ac.uk/users/pes20/wraptypes-tr.ps",
+}
+
+@Article{sha-steiglitz-93,
+ author = "Edwin Hsing-Mean Sha and Kenneth Steiglitz",
+ title = "Maintaining Bipartite Matchings in the Presence of
+ Failures",
+ journal = "Networks",
+ year = "1993",
+ volume = "23",
+ number = "5",
+ pages = "459--471",
+ URL = "http://www.nd.edu/~esha/papers/oldsha/alg.ps",
+}
+
+@Article{shao-certified-05,
+ author = "Zhong Shao and Valery Trifonov and Bratin Saha and
+ Nikolaos Papaspyrou",
+ title = "A type system for certified binaries",
+ journal = toplas,
+ volume = "27",
+ number = "1",
+ year = "2005",
+ pages = "1--45",
+ URL = "http://flint.cs.yale.edu/flint/publications/tscb-toplas.pdf",
+}
+
+@InProceedings{sheard-04,
+ author = "Tim Sheard",
+ title = "Languages of the Future",
+ booktitle = oopsla,
+ year = "2004",
+ pages = "116--119",
+ URL = "http://doi.acm.org/10.1145/1028664.1028711",
+}
+
+@InProceedings{sheard-05,
+ author = "Tim Sheard",
+ title = "Putting {Curry-Howard} To Work",
+ booktitle = hw,
+ year = "2005",
+ pages = "74--85",
+ URL = "http://web.cecs.pdx.edu/~sheard/papers/PutCurryHoward2WorkFinalVersion.ps",
+}
+
+@InProceedings{sheard-challenges-01,
+ author = "Tim Sheard",
+ title = "Accomplishments and Research Challenges in
+ Meta-Programming",
+ booktitle = saig,
+ pages = "2--44",
+ year = "2001",
+ volume = "2196",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.cse.ogi.edu/PacSoft/publications/2001/challeges_sheard.pdf",
+}
+
+@InProceedings{sheard-metaml-98,
+ author = "Tim Sheard",
+ title = "Using {MetaML}: {A} staged Programming Language",
+ booktitle = afp,
+ pages = "207--239",
+ year = "1998",
+ volume = "1608",
+ series = lncs,
+ publisher = springer,
+ URL = "http://web.cecs.pdx.edu/~sheard/papers/summerschool.ps",
+}
+
+@InProceedings{sheard-pasalic-04,
+ author = "Tim Sheard and Emir Pa{\v s}ali{\'c}",
+ title = "Meta-Programming with Built-in Type Equality",
+ booktitle = lfm,
+ year = "2004",
+ URL = "http://cs-www.cs.yale.edu/homes/carsten/lfm04/proceedings/pasalic.pdf",
+}
+
+@InProceedings{shields-peyton-jones-02,
+ author = "Mark B. Shields and Simon {Peyton Jones}",
+ title = "First class modules for {Haskell}",
+ booktitle = fool,
+ year = "2002",
+ pages = "28--40",
+ URL = "http://www.cse.ogi.edu/~mbs/pub/first_class_modules/first_class_modules.pdf",
+}
+
+@InProceedings{shinwell-03,
+ author = "Mark R. Shinwell and Andrew M. Pitts and Murdoch J.
+ Gabbay",
+ title = "{FreshML}: Programming with Binders Made Simple",
+ booktitle = icfp,
+ pages = "263--274",
+ year = "2003",
+ URL = "http://www.cl.cam.ac.uk/~amp12/papers/frepbm/frepbm.pdf",
+}
+
+@Article{shinwell-05,
+ author = "Mark R. Shinwell",
+ title = "{Fresh O'Caml}: nominal abstract syntax for the
+ masses",
+ journal = entcs,
+ year = "2006",
+ volume = "148",
+ number = "2",
+ pages = "53--77",
+ URL = "http://dx.doi.org/10.1016/j.entcs.2005.11.040",
+}
+
+@PhdThesis{shinwell-phd,
+ author = "Mark R. Shinwell",
+ title = "The Fresh Approach: functional programming with names
+ and binders",
+ school = "University of Cambridge",
+ year = "2005",
+ URL = "http://www.cl.cam.ac.uk/users/mrs30/papers/thesis.pdf",
+}
+
+@Article{shinwell-pitts-05,
+ author = "Mark R. Shinwell and Andrew M. Pitts",
+ title = "On a Monadic Semantics for Freshness",
+ journal = tcs,
+ year = "2005",
+ volume = "342",
+ pages = "28--55",
+ URL = "http://www.cl.cam.ac.uk/users/amp12/papers/monsf/monsf-jv.pdf",
+}
+
+@InProceedings{shivers-96,
+ author = "Olin Shivers",
+ title = "A universal scripting framework or, {Lambda}: the
+ ultimate ``little language''",
+ booktitle = "Concurrency and Parallelism: Programming, Networking
+ and Security",
+ pages = "254--265",
+ year = "1996",
+ volume = "1179",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.ai.mit.edu/people/shivers/ll.ps",
+}
+
+@Article{sikmhs-12,
+ author = "Jan Schwinghammer and Lars Birkedal and François
+ Pottier and Bernhard Reus and Kristian St{\o}vring and
+ Hongseok Yang",
+ title = "A step-indexed {Kripke} Model of Hidden State",
+ journal = mscs,
+ note = "To appear",
+ year = "2012",
+ URL = "http://gallium.inria.fr/~fpottier/publis/sikmhs.pdf",
+}
+
+@InProceedings{simonet-02,
+ author = "Vincent Simonet",
+ title = "Fine-grained Information Flow Analysis for a
+ $\lambda$-calculus with Sum Types",
+ booktitle = csfw,
+ pages = "223--237",
+ year = "2002",
+ URL = "http://gallium.inria.fr/~simonet/publis/simonet-csfw-02.ps.gz",
+}
+
+@InProceedings{simonet-03,
+ author = "Vincent Simonet",
+ title = "An Extension of {HM(X)} with Bounded Existential and
+ Universal Data-Types",
+ year = "2003",
+ booktitle = icfp,
+ URL = "http://gallium.inria.fr/~simonet/publis/simonet-icfp03.ps.gz",
+}
+
+@TechReport{simonet-flowcaml-manual,
+ author = "Vincent Simonet",
+ title = "The {Flow Caml} system: documentation and user's
+ manual",
+ institution = "INRIA",
+ number = "0282",
+ year = "2003",
+ URL = "http://gallium.inria.fr/~simonet/soft/flowcaml/manual/",
+}
+
+@TechReport{simonet-pottier-hmg,
+ author = "Vincent Simonet and François Pottier",
+ title = "Constraint-Based Type Inference for Guarded Algebraic
+ Data Types",
+ year = "2005",
+ institution = "INRIA",
+ type = "Research Report",
+ number = "5462",
+ URL = "http://www.inria.fr/rrrt/rr-5462.html",
+}
+
+@InProceedings{simonet-solver-03,
+ author = "Vincent Simonet",
+ title = "Type inference with structural subtyping: a faithful
+ formalization of an efficient constraint solver",
+ booktitle = aplas,
+ publisher = springer,
+ series = lncs,
+ volume = "2895",
+ year = "2003",
+ URL = "http://gallium.inria.fr/~simonet/publis/simonet-aplas03.pdf",
+}
+
+@PhdThesis{simonet-these,
+ author = "Vincent Simonet",
+ title = "Inférence de flots d'information pour {ML}:
+ formalisation et implantation",
+ school = "Université Paris 7",
+ year = "2004",
+ URL = "http://gallium.inria.fr/~simonet/publis/simonet-these.pdf",
+}
+
+@Article{simplify,
+ author = "David Detlefs and Greg Nelson and James B. Saxe",
+ title = "{Simplify}: a theorem prover for program checking",
+ journal = jacm,
+ volume = "52",
+ number = "3",
+ year = "2005",
+ pages = "365--473",
+ URL = "http://doi.acm.org/10.1145/1066100.1066102",
+}
+
+@PhdThesis{skalka-phd-02,
+ author = "Christian Skalka",
+ title = "Types for Programming Language-Based Security",
+ school = "The Johns Hopkins University",
+ year = "2002",
+ URL = "http://www.cs.uvm.edu/~skalka/skalka-pubs/skalka-phd-thesis.ps",
+}
+
+@InProceedings{skalka-pottier-tip-02,
+ author = "Christian Skalka and François Pottier",
+ title = "Syntactic Type Soundness for {HM}{$(X)$}",
+ year = "2002",
+ booktitle = "Workshop on Types in Programming (TIP)",
+ series = entcs,
+ volume = "75",
+ URL = "http://gallium.inria.fr/~fpottier/publis/skalka-fpottier-tip-02.ps.gz",
+}
+
+@InProceedings{skalka-smith-00,
+ author = "Christian Skalka and Scott Smith",
+ title = "Static Enforcement of Security with Types",
+ booktitle = icfp,
+ year = "2000",
+ pages = "34--45",
+ URL = "http://www.cs.uvm.edu/~skalka/skalka-pubs/skalka-smith-icfp00.ps",
+}
+
+@InProceedings{smallfoot-05,
+ author = "Josh Berdine and Cristiano Calcagno and Peter W.
+ O'Hearn",
+ title = "Smallfoot: Modular Automatic Assertion Checking with
+ Separation Logic",
+ booktitle = fmco,
+ pages = "115--137",
+ year = "2005",
+ volume = "4111",
+ series = lncs,
+ publisher = springer,
+ URL = "http://research.microsoft.com/pubs/67598/smallfoot.pdf",
+}
+
+@InProceedings{smans-implicit-09,
+ title = "Implicit Dynamic Frames: Combining Dynamic Frames and
+ Separation Logic",
+ year = "2009",
+ author = "Jan Smans and Bart Jacobs and Frank Piessens",
+ booktitle = ecoop,
+ pages = "148--172",
+ volume = "5653",
+ series = lncs,
+ publisher = springer,
+ URL = "http://people.cs.kuleuven.be/~jan.smans/ecoop09.pdf",
+}
+
+@InProceedings{smetsers-94,
+ author = "Sjaak Smetsers and Erik Barendsen and Marko C. J. D.
+ van Eekelen and Marinus J. Plasmeijer",
+ title = "Guaranteeing Safe Destructive Updates Through a Type
+ System with Uniqueness Information for Graphs",
+ booktitle = "Dagstuhl Seminar on Graph Transformations in Computer
+ Science",
+ year = "1994",
+ pages = "358--379",
+ publisher = springer,
+ series = lncs,
+ volume = "776",
+ URL = "http://www.mbsd.cs.ru.nl/publications/papers/1994/smes94-guaranteeing.pdf",
+}
+
+@InProceedings{smith-01,
+ author = "Geoffrey S. Smith",
+ title = "A New Type System for Secure Information Flow",
+ booktitle = csfw,
+ pages = "115--125",
+ year = "2001",
+ URL = "http://www.cs.fiu.edu/~smithg/papers/csfw01.pdf",
+}
+
+@InProceedings{smith-93,
+ author = "Geoffrey S. Smith",
+ title = "Polymorphic type Inference with Overloading and
+ Subtyping",
+ booktitle = tapsoft,
+ series = lncs,
+ volume = "668",
+ publisher = springer,
+ year = "1993",
+ pages = "671--685",
+ URL = "http://dx.doi.org/10.1007/3-540-56610-4_97",
+}
+
+@Article{smith-94,
+ author = "Geoffrey S. Smith",
+ title = "Principal Type Schemes for Functional Programs with
+ Overloading and Subtyping",
+ journal = scp,
+ year = "1994",
+ volume = "23",
+ number = "2--3",
+ pages = "197--226",
+ URL = "http://www.cs.fiu.edu/~smithg/papers/scp94.pdf",
+}
+
+@PhdThesis{smith-phd-89,
+ author = "Scott Fraser Smith",
+ title = "Partial Objects in Type Theory",
+ school = "Cornell University",
+ year = "1989",
+ URL = "http://www.cs.jhu.edu/~scott/pll/older-papers/thesis.pdf",
+}
+
+@InProceedings{smith-volpano-98,
+ title = "Secure Information Flow in a Multi-Threaded Imperative
+ Language",
+ booktitle = popl,
+ author = "Geoffrey Smith and Dennis Volpano",
+ year = "1998",
+ pages = "355--364",
+ URL = "http://www.cs.nps.navy.mil/people/faculty/volpano/papers/popl98.ps.Z",
+}
+
+@InProceedings{smith-wang-00,
+ author = "Scott Smith and Tiejun Wang",
+ title = "Polyvariant Flow Analysis with Constrained Types",
+ booktitle = esop,
+ publisher = springer,
+ series = lncs,
+ volume = "1782",
+ pages = "382--396",
+ year = "2000",
+ URL = "http://link.springer.de/link/service/series/0558/papers/1782/17820382.pdf",
+}
+
+@Book{sml-97,
+ author = "Robin Milner and Mads Tofte and Robert Harper and
+ David MacQueen",
+ title = "The Definition of {Standard ML} -- Revised",
+ publisher = mitp,
+ year = "1997",
+}
+
+@Article{smolka-treinen-94,
+ title = "Records for Logic Programming",
+ year = "1994",
+ author = "Gert Smolka and Ralf Treinen",
+ volume = "18",
+ journal = jlp,
+ number = "3",
+ pages = "229--258",
+ URL = "http://www.ps.uni-sb.de/Papers/abstracts/RecordsLogProg.ps",
+}
+
+@Article{smyth-plotkin-82,
+ author = "Michael B. Smyth and Gordon D. Plotkin",
+ title = "The Category-Theoretic Solution of Recursive Domain
+ Equations",
+ journal = siamjc,
+ volume = "11",
+ number = "4",
+ year = "1982",
+ pages = "761--783",
+ URL = "http://homepages.inf.ed.ac.uk/gdp/publications/Category_Theoretic_Solution.pdf",
+}
+
+@InProceedings{snyder-86,
+ author = "Alan Snyder",
+ title = "Encapsulation and inheritance in object-oriented
+ programming languages",
+ booktitle = oopsla,
+ year = "1986",
+ pages = "38--45",
+ URL = "http://doi.acm.org/10.1145/28697.28702",
+}
+
+@InProceedings{sobel-friedman-98,
+ author = "Jonathan Sobel and Daniel P. Friedman",
+ title = "Recycling continuations",
+ booktitle = icfp,
+ year = "1998",
+ pages = "251--260",
+ URL = "http://www.cs.indiana.edu/hyplan/dfried/rc.ps",
+}
+
+@Article{soisalon-soininen-82,
+ author = "Eljas Soisalon-Soininen",
+ title = "Inessential Error Entries and Their Use in {LR} Parser
+ Optimization",
+ journal = toplas,
+ volume = "4",
+ number = "2",
+ year = "1982",
+ pages = "179--195",
+ URL = "http://doi.acm.org/10.1145/357162.357165",
+}
+
+@InProceedings{solomon-78,
+ author = "Marvin H. Solomon",
+ title = "Type Definitions with Parameters",
+ booktitle = popl,
+ year = "1978",
+ pages = "31--38",
+ URL = "http://doi.acm.org/10.1145/512760.512765",
+}
+
+@Article{soloviev-83,
+ author = "Sergei V. Soloviev",
+ title = "The category of finite sets and Cartesian Closed
+ Categories",
+ journal = "Journal of Soviet Mathematics",
+ year = "1983",
+ volume = "22",
+ number = "3",
+ pages = "1387--1400",
+}
+
+@InProceedings{sozeau-06,
+ author = "Matthieu Sozeau",
+ title = "Subset Coercions in {Coq}",
+ booktitle = types,
+ year = "2006",
+ volume = "4502",
+ pages = "237--252",
+ URL = "http://www.lri.fr/~sozeau/research/russell/article.pdf",
+}
+
+@InProceedings{sozeau-finger-07,
+ author = "Matthieu Sozeau",
+ booktitle = icfp,
+ pages = "13--24",
+ URL = "http://mattam.org/research/publications/Program-ing_Finger_Trees_in_Coq.pdf",
+ title = "Program-ing Finger Trees in {Coq}",
+ year = "2007",
+}
+
+@Article{spec-sharp-04,
+ author = "Mike Barnett and Rob DeLine and Manuel Fähndrich and
+ K. Rustan M. Leino and Wolfram Schulte",
+ title = "Verification of object-oriented programs with
+ invariants",
+ journal = jot,
+ year = "2004",
+ volume = "3",
+ number = "6",
+ URL = "http://research.microsoft.com/research/pubs/view.aspx?type=article&id=1161",
+}
+
+@Article{spivey-90,
+ year = "1990",
+ volume = "14",
+ title = "A Functional Theory of Exceptions",
+ pages = "25--42",
+ journal = scp,
+ author = "Mike Spivey",
+}
+
+@InProceedings{stata-abadi-98,
+ author = "R. Stata and M. Abadi",
+ title = "A Type System for {Java} Bytecode Subroutines",
+ year = "1998",
+ pages = "149--160",
+ booktitle = popl,
+ URL = "http://gatekeeper.dec.com/pub/DEC/SRC/research-reports/abstracts/src-rr-158.html",
+}
+
+@Article{steckler-wand-97,
+ author = "Paul A. Steckler and Mitchell Wand",
+ title = "Lightweight closure conversion",
+ journal = toplas,
+ volume = "19",
+ number = "1",
+ year = "1997",
+ pages = "48--86",
+ URL = "ftp://ftp.ccs.neu.edu/pub/people/wand/papers/steckler-wand-97.ps",
+}
+
+@InProceedings{steensgaard-96,
+ author = "Bjarne Steensgaard",
+ booktitle = popl,
+ title = "Points-to Analysis in Almost Linear Time",
+ year = "1996",
+ pages = "32--41",
+ URL = "ftp://ftp.research.microsoft.com/users/rusa/popl96.ps",
+}
+
+@InProceedings{steffen-fix-machine-95,
+ author = "Bernhard Steffen and Andreas Cla{\ss}en and Marion
+ Klein and Jens Knoop and Tiziana Margaria",
+ title = "The Fixpoint-Analysis Machine",
+ booktitle = concur,
+ year = "1995",
+ pages = "72--87",
+ publisher = springer,
+ series = lncs,
+ volume = "962",
+ URL = "http://dx.doi.org/10.1007/3-540-60218-6_6",
+}
+
+@InProceedings{stehr-00,
+ author = "Mark-Oliver Stehr",
+ title = "{CINNI} -- {A} Generic Calculus of Explicit
+ Substitutions and its Application to $\lambda$-,
+ $\sigma$- and $\pi$-calculi",
+ booktitle = wrla,
+ year = "2000",
+ volume = "36",
+ series = entcs,
+ publisher = elsevier,
+ URL = "http://formal.cs.uiuc.edu/stehr/extcinni.ps",
+}
+
+@InProceedings{stewart-veristar-12,
+ author = "Gordon Stewart and Lennart Beringer and Andrew W.
+ Appel",
+ title = "Verified heap theorem prover by paramodulation",
+ booktitle = icfp,
+ year = "2012",
+ pages = "3--14",
+ URL = "http://www.cs.princeton.edu/~appel/papers/veristar.pdf",
+}
+
+@InProceedings{stoughton-81,
+ author = "Allen Stoughton",
+ title = "Access Flow: {A} Protection Model Which Integrates
+ Access Control and Information Flow",
+ pages = "9--18",
+ booktitle = sp,
+ year = "1981",
+}
+
+@Article{strachey-fundamental,
+ author = "Christopher Strachey",
+ title = "Fundamental Concepts in Programming Languages",
+ journal = hosc,
+ year = "2000",
+ volume = "13",
+ number = "1--2",
+ pages = "11--49",
+ URL = "http://dx.doi.org/10.1023/A:1010000313106",
+}
+
+@Article{strom-yemini-86,
+ author = "Robert E. Strom and Shaula Yemini",
+ title = "Typestate: {A} programming language concept for
+ enhancing software reliability",
+ journal = tose,
+ volume = "12",
+ number = "1",
+ year = "1986",
+ pages = "157--171",
+ URL = "http://www.cs.cmu.edu/~aldrich/papers/classic/tse12-typestate.pdf",
+}
+
+@InProceedings{stuckey-sulzmann-02,
+ author = "Peter J. Stuckey and Martin Sulzmann",
+ title = "A Theory of Overloading",
+ booktitle = icfp,
+ pages = "167--178",
+ year = "2002",
+ URL = "http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.62.8605",
+}
+
+@InProceedings{stuckey-sulzmann-wazny-03,
+ author = "Peter J. Stuckey and Martin Sulzmann and Jeremy
+ Wazny",
+ title = "Interactive type debugging in {Haskell}",
+ booktitle = hw,
+ pages = "72--83",
+ year = "2003",
+ URL = "http://www.cs.mu.oz.au/~pjs/papers/p316-stuckey.pdf",
+}
+
+@InProceedings{su-aiken-01,
+ author = "Zhendong Su and Alexander Aiken",
+ title = "Entailment with Conditional Equality Constraints",
+ booktitle = esop,
+ year = "2001",
+ pages = "170--189",
+ series = lncs,
+ volume = "2028",
+ URL = "http://www.cs.ucdavis.edu/~su/publications/esop01.pdf",
+}
+
+@InProceedings{su-al-02,
+ author = "Zhendong Su and Alexander Aiken and Joachim Niehren
+ and Tim Priesnitz and Ralf Treinen",
+ title = "The First-Order Theory of Subtyping Constraints",
+ booktitle = popl,
+ pages = "203--216",
+ year = "2002",
+ URL = "http://theory.stanford.edu/~aiken/publications/papers/popl02.pdf",
+}
+
+@PhdThesis{sulzmann-00,
+ author = "Martin Sulzmann",
+ title = "A general framework for {Hindley/Milner} type systems
+ with constraints",
+ school = "Yale University, Department of Computer Science",
+ year = "2000",
+ URL = "http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.7.7745",
+}
+
+@InProceedings{sulzmann-01,
+ author = "Martin Sulzmann",
+ title = "A General Type Inference Framework for
+ {Hindley/Milner} Style Systems",
+ booktitle = "International Symposium on Functional and Logic
+ Programming",
+ series = lncs,
+ volume = "2024",
+ pages = "246--263",
+ publisher = springer,
+ year = "2001",
+ URL = "http://link.springer.de/link/service/series/0558/papers/2024/20240248.pdf",
+}
+
+@TechReport{sulzmann-mueller-zenger-99,
+ author = "Martin Sulzmann and Martin Müller and Christoph
+ Zenger",
+ title = "{Hindley/Milner} style type systems in constraint
+ form",
+ institution = "University of South Australia, School of Computer and
+ Information Science",
+ type = "Research Report",
+ year = "1999",
+ number = "ACRC--99--009",
+ URL = "http://www.ps.uni-sb.de/~mmueller/papers/hm-constraints.ps.gz",
+}
+
+@InProceedings{sulzmann-odersky-wehr-97,
+ author = "Martin Sulzmann and Martin Odersky and Martin Wehr",
+ title = "Type Inference with Constrained Types",
+ booktitle = fool,
+ year = "1997",
+ URL = "ftp://ftp.ira.uka.de/pub/uni-karlsruhe/papers/techreports/1996/1996-28.ps.gz",
+}
+
+@TechReport{sulzmann-records-97,
+ author = "Martin Sulzmann",
+ title = "Designing Record Systems",
+ institution = "Yale University",
+ year = "1997",
+ type = "Research Report",
+ number = "YALEU/DCS/RR-1128",
+ URL = "http://www.cs.mu.oz.au/~sulzmann/publications/tr-1128.ps.gz",
+}
+
+@TechReport{sulzmann-wang-04,
+ author = "Martin Sulzmann and Meng Wang",
+ title = "A Systematic Translation of Guarded Recursive Data
+ Types to Existential Types",
+ institution = "National University of Singapore",
+ number = "TR22/04",
+ year = "2004",
+ ps = "http://www.cs.mu.oz.au/~sulzmann/publications/translate-grdts.ps.gz",
+}
+
+@InProceedings{sumii-09,
+ author = "Eijiro Sumii",
+ title = "A Complete Characterization of Observational
+ Equivalence in Polymorphic lambda-Calculus with General
+ References",
+ booktitle = csl,
+ series = lncs,
+ publisher = springer,
+ volume = "5771",
+ pages = "455--469",
+ year = "2009",
+ URL = "http://www.kb.ecei.tohoku.ac.jp/~sumii/pub/poly-ref.pdf",
+}
+
+@InProceedings{svendsen-birkedal-icap-14,
+ author = "Kasper Svendsen and Lars Birkedal",
+ title = "Impredicative Concurrent Abstract Predicates",
+ booktitle = esop,
+ year = "2014",
+ pages = "149--168",
+ volume = "8410",
+ publisher = springer,
+ series = lncs,
+ URL = "http://cs.au.dk/~birke/papers/icap-conf.pdf",
+}
+
+@InProceedings{svendsen-birkedal-parkinson-hocap-13,
+ author = "Kasper Svendsen and Lars Birkedal and Matthew J.
+ Parkinson",
+ booktitle = esop,
+ pages = "169--188",
+ publisher = springer,
+ series = lncs,
+ title = "Modular Reasoning about Separation of Concurrent Data
+ Structures",
+ volume = "7792",
+ year = "2013",
+ URL = "http://cs.au.dk/~birke/papers/hocap-conf.pdf",
+}
+
+@InProceedings{svendsen-birkedal-parkinson-joins-13,
+ author = "Kasper Svendsen and Lars Birkedal and Matthew J.
+ Parkinson",
+ title = "Joins: {A} Case Study in Modular Specification of a
+ Concurrent Reentrant Higher-Order Library",
+ booktitle = ecoop,
+ year = "2013",
+ pages = "327--351",
+ publisher = springer,
+ series = lncs,
+ volume = "7920",
+ URL = "http://cs.au.dk/~birke/papers/joins-conf.pdf",
+}
+
+@Article{swamy-06,
+ author = "Nikhil Swamy and Michael Hicks and Greg Morrisett and
+ Dan Grossman and Trevor Jim",
+ title = "Safe Manual Memory Management in {Cyclone}",
+ journal = scp,
+ year = "2006",
+ volume = "62",
+ number = "2",
+ pages = "122--144",
+ URL = "http://www.cs.umd.edu/~mwh/papers/cyc-mm-scp.pdf",
+}
+
+@InProceedings{swierstra-duponcheel-96,
+ author = "S. Doaitse Swierstra and Luc Duponcheel",
+ title = "Deterministic, Error-Correcting Combinator Parsers",
+ booktitle = "Advanced Functional Programming",
+ year = "1996",
+ publisher = "Springer",
+ series = "Lecture Notes in Computer Science",
+ volume = "1129",
+ pages = "184--207",
+ URL = "http://www.staff.science.uu.nl/~swier101/Papers/1996/DetErrCorrComPars.pdf",
+}
+
+@InProceedings{syb,
+ author = "Ralf L{\"{a}}mmel and Simon {Peyton Jones}",
+ title = "Scrap your boilerplate: a practical design pattern for
+ generic programming",
+ booktitle = tldi,
+ pages = "26--37",
+ year = "2003",
+ URL = "https://www.microsoft.com/en-us/research/wp-content/uploads/2003/01/hmap.pdf",
+}
+
+@InProceedings{syb-reloaded,
+ author = "Ralf Hinze and Andres L{\"{o}}h and Bruno C. d. S.
+ Oliveira",
+ title = "``Scrap Your Boilerplate'' Reloaded",
+ booktitle = flops,
+ pages = "13--29",
+ year = "2006",
+ series = lncs,
+ volume = "3945",
+ publisher = springer,
+ URL = "http://www.cs.ox.ac.uk/bruno.oliveira/SYB0.pdf",
+}
+
+@InProceedings{syb-revolutions,
+ author = "Ralf Hinze and Andres L{\"{o}}h",
+ title = "``Scrap Your Boilerplate'' Revolutions",
+ booktitle = mpc,
+ pages = "180--208",
+ year = "2006",
+ series = lncs,
+ volume = "4014",
+ publisher = springer,
+ URL = "https://www.andres-loeh.de/SYB1.pdf",
+}
+
+@InProceedings{syb2,
+ author = "Ralf L{\"{a}}mmel and Simon {Peyton Jones}",
+ title = "Scrap more boilerplate: reflection, zips, and
+ generalised casts",
+ booktitle = icfp,
+ pages = "244--255",
+ year = "2004",
+ URL = "https://doi.org/10.1145/1016848.1016883",
+}
+
+@InProceedings{syb3,
+ author = "Ralf L{\"{a}}mmel and Simon {Peyton Jones}",
+ title = "Scrap your boilerplate with class: extensible generic
+ functions",
+ booktitle = icfp,
+ pages = "204--215",
+ year = "2005",
+ URL = "https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/gmap3.pdf",
+}
+
+@PhdThesis{taha-99,
+ author = "Walid Taha",
+ title = "Multi-stage Programming: Its Theory and Applications",
+ school = "Oregon Graduate Institute",
+ year = "1999",
+ URL = "http://www.cs.rice.edu/~taha/publications/thesis/thesis.pdf",
+}
+
+@InProceedings{taha-gentle-04,
+ author = "Walid Taha",
+ title = "A Gentle Introduction to Multi-stage Programming",
+ booktitle = dspg,
+ pages = "30--50",
+ year = "2004",
+ volume = "3016",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.cs.rice.edu/~taha/publications/journal/dspg04a.pdf",
+}
+
+@InProceedings{taha-nielsen-03,
+ author = "Walid Taha and Michael Florentin Nielsen",
+ title = "Environment classifiers",
+ booktitle = popl,
+ year = "2003",
+ pages = "26--37",
+ URL = "http://www.cs.rice.edu/~taha/publications/conference/popl03.pdf",
+}
+
+@Article{takahashi-95,
+ author = "Masako Takahashi",
+ title = "Parallel Reductions in $\lambda$-Calculus",
+ journal = ic,
+ year = "1995",
+ volume = "118",
+ number = "1",
+ pages = "120--127",
+ URL = "http://dx.doi.org/10.1006/inco.1995.1057",
+}
+
+@Article{talcott-93,
+ author = "Carolyn Talcott",
+ title = "A Theory of Binding Structures and Applications to
+ Rewriting",
+ journal = tcs,
+ year = "1993",
+ volume = "112",
+ number = "1",
+ pages = "99--143",
+ URL = "http://dx.doi.org/10.1016/0304-3975(93)90240-T",
+}
+
+@Article{talpin-jouvelot-94,
+ author = "Jean-Pierre Talpin and Pierre Jouvelot",
+ title = "The type and effect discipline",
+ journal = ic,
+ year = "1994",
+ volume = "11",
+ number = "2",
+ pages = "245--296",
+ URL = "http://www.irisa.fr/prive/talpin/papers/ic94.pdf",
+}
+
+@InProceedings{tan-wusl-09,
+ author = "Gang Tan and Zhong Shao and Xinyu Feng and Hongxu
+ Cai",
+ title = "Weak Updates and Separation Logic",
+ booktitle = aplas,
+ pages = "178--193",
+ year = "2009",
+ volume = "5904",
+ series = lncs,
+ publisher = springer,
+ URL = "http://flint.cs.yale.edu/flint/publications/wusl.pdf",
+}
+
+@Book{tapl,
+ author = "Benjamin C. Pierce",
+ title = "Types and Programming Languages",
+ publisher = mitp,
+ year = "2002",
+}
+
+@Manual{tarditi-appel-00,
+ title = "{ML-Yacc} User's Manual",
+ author = "David R. Tarditi and Andrew W. Appel",
+ year = "2000",
+ URL = "http://www.smlnj.org/doc/ML-Yacc/",
+}
+
+@Article{tarjan-72,
+ author = "Robert Tarjan",
+ title = "Depth-First Search and Linear Graph Algorithms",
+ journal = siamjc,
+ year = "1972",
+ volume = "1",
+ number = "2",
+ pages = "146--160",
+ URL = "http://epubs.siam.org/doi/abs/10.1137/0201010",
+}
+
+@Article{tarjan-75,
+ author = "Robert Endre Tarjan",
+ title = "Efficiency of a Good But Not Linear Set Union
+ Algorithm",
+ journal = jacm,
+ year = "1975",
+ volume = "22",
+ number = "2",
+ pages = "215--225",
+ URL = "http://www.csd.uwo.ca/~eschost/Teaching/07-08/CS445a/p215-tarjan.pdf",
+}
+
+@Article{tarjan-79,
+ author = "Robert Endre Tarjan",
+ title = "Applications of Path Compression on Balanced Trees",
+ journal = jacm,
+ year = "1979",
+ volume = "26",
+ number = "4",
+ pages = "690--715",
+ URL = "http://doi.acm.org/10.1145/322154.322161",
+}
+
+@Unpublished{tarjan-99-notes,
+ title = "Class notes: Disjoint Set Union",
+ author = "Robert E. Tarjan",
+ year = "1999",
+ URL = "http://www.cs.princeton.edu/courses/archive/spr00/cs423/handout3.pdf",
+}
+
+@Article{tarjan-amortized-85,
+ author = "Robert Endre Tarjan",
+ title = "Amortized Computational Complexity",
+ year = "1985",
+ journal = "SIAM Journal on Algebraic and Discrete Methods",
+ volume = "6",
+ number = "2",
+ pages = "306--318",
+ URL = "http://dx.doi.org/10.1137/0606031",
+}
+
+@Article{tarjan-leeuwen-84,
+ author = "Robert E. Tarjan and Jan {van Leeuwen}",
+ title = "Worst-Case Analysis of Set Union Algorithms",
+ journal = jacm,
+ volume = "31",
+ number = "2",
+ pages = "245--281",
+ year = "1984",
+ URL = "http://dx.doi.org/10.1145/62.2160",
+}
+
+@Article{tarjan-yannakakis-84,
+ author = "Robert E. Tarjan and Mihalis Yannakakis",
+ title = "Simple Linear-Time Algorithms to Test Chordality of
+ Graphs, Test Acyclicity of Hypergraphs, and Selectively
+ Reduce Acyclic Hypergraphs",
+ journal = siamjc,
+ year = "1984",
+ volume = "13",
+ number = "3",
+ pages = "566--579",
+ URL = "http://dx.doi.org/10.1137/0213035",
+}
+
+@Article{tarjan-yao-79,
+ author = "Robert Endre Tarjan and Andrew Chi-Chih Yao",
+ title = "Storing a sparse table",
+ journal = cacm,
+ volume = "22",
+ number = "11",
+ year = "1979",
+ pages = "606--611",
+ URL = "http://doi.acm.org/10.1145/359168.359175",
+}
+
+@InProceedings{template-haskell-02,
+ author = "Tim Sheard and Simon {Peyton Jones}",
+ title = "Template metaprogramming for {Haskell}",
+ booktitle = hw,
+ year = "2002",
+ pages = "1--16",
+ URL = "https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/meta-haskell.pdf",
+}
+
+@Article{tennent-ghica-00,
+ author = "Robert D. Tennent and Dan Ghica",
+ title = "Abstract models of storage",
+ journal = hosc,
+ year = "2000",
+ volume = "13",
+ pages = "119--129",
+ URL = "http://dx.doi.org/10.1023/A:1010022312623",
+}
+
+@InProceedings{thatte-94,
+ author = "Satish R. Thatt{\'e}",
+ title = "Automated synthesis of interface adapters for reusable
+ classes",
+ booktitle = popl,
+ year = "1994",
+ pages = "174--187",
+ URL = "http://doi.acm.org/10.1145/174675.177850",
+}
+
+@InProceedings{thielecke-03,
+ author = "Hayo Thielecke",
+ title = "From control effects to typed continuation passing",
+ booktitle = popl,
+ year = "2003",
+ pages = "139--149",
+ URL = "http://www.cs.bham.ac.uk/~hxt/research/effects.pdf",
+}
+
+@InProceedings{thielecke-06,
+ author = "Hayo Thielecke",
+ title = "Frame rules from answer types for code pointers",
+ booktitle = popl,
+ year = "2006",
+ pages = "309--319",
+ URL = "http://www.cs.bham.ac.uk/~hxt/research/popl06thielecke.pdf",
+}
+
+@Article{thielecke-barrel-02,
+ author = "Hayo Thielecke",
+ title = "Comparing Control Constructs by Double-barrelled
+ {CPS}",
+ journal = hosc,
+ year = "2002",
+ volume = "15",
+ number = "2--3",
+ pages = "141--160",
+ URL = "http://www.cs.bham.ac.uk/~hxt/research/HOSC-double-barrel.pdf",
+}
+
+@InProceedings{thiemann-01,
+ author = "Peter Thiemann",
+ title = "Enforcing Security Properties Using Type
+ Specialization",
+ booktitle = esop,
+ publisher = springer,
+ series = lncs,
+ year = "2001",
+ URL = "http://www.informatik.uni-freiburg.de/~thiemann/papers/espps-het.ps.gz",
+}
+
+@InProceedings{thiemann-99,
+ author = "Peter Thiemann",
+ title = "{ML}-Style Typing, Lambda Lifting, and Partial
+ Evaluation",
+ booktitle = "Latin American Conference on Functional Programming",
+ year = "1999",
+ URL = "http://www.informatik.uni-freiburg.de/~thiemann/papers/clapf99.ps.gz",
+}
+
+@InProceedings{tian-06,
+ author = "Ye Henry Tian",
+ title = "Mechanically Verifying Correctness of {CPS}
+ Compilation",
+ booktitle = "Computing: The Australasian Theory Symposium (CATS)",
+ pages = "41--51",
+ year = "2006",
+ URL = "http://crpit.com/confpapers/CRPITV51Tian.pdf",
+ series = "{CRPIT}",
+ volume = "51",
+ publisher = "Australian Computer Society",
+}
+
+@InProceedings{tiuryn-92,
+ author = "Jerzy Tiuryn",
+ title = "Subtype inequalities",
+ pages = "308--317",
+ booktitle = lics,
+ year = "1992",
+}
+
+@Article{tiuryn-urzyczyn-02,
+ author = "Jerzy Tiuryn and Pawel Urzyczyn",
+ title = "The subtyping problem for second-order types is
+ undecidable",
+ journal = ic,
+ volume = "179",
+ number = "1",
+ year = "2002",
+ pages = "1--18",
+ URL = "http://dx.doi.org/10.1006/inco.2001.2950",
+}
+
+@InProceedings{tiuryn-wand-93,
+ author = "Jerzy Tiuryn and Mitchell Wand",
+ title = "Type Reconstruction with Recursive Types and Atomic
+ Subtyping",
+ pages = "686--701",
+ year = "1993",
+ booktitle = tapsoft,
+ series = lncs,
+ volume = "668",
+ publisher = springer,
+ URL = "ftp://ftp.ccs.neu.edu/pub/people/wand/papers/caap-93.dvi",
+}
+
+@PhdThesis{tofte-88,
+ author = "Mads Tofte",
+ title = "Operational Semantics and Polymorphic Type Inference",
+ school = "University of Edinburgh",
+ year = "1988",
+ URL = "http://www.itu.dk/people/tofte/publ/phdthesis/thesis-part1and2.ps",
+}
+
+@Article{tofte-retro-04,
+ author = "Mads Tofte and Lars Birkedal and Martin Elsman and
+ Niels Hallenberg",
+ title = "A Retrospective on Region-Based Memory Management",
+ journal = hosc,
+ year = "2004",
+ volume = "17",
+ number = "3",
+ pages = "245--265",
+ URL = "http://www.itu.dk/people/birkedal/papers/regmmp.ps.gz",
+}
+
+@InProceedings{tofte-talpin-94,
+ author = "Mads Tofte and Jean-Pierre Talpin",
+ title = "Implementation of the Typed Call-by-Value
+ $\lambda$-Calculus using a Stack of Regions",
+ booktitle = popl,
+ year = "1994",
+ pages = "188--201",
+ URL = "http://www.irisa.fr/prive/talpin/papers/popl94.pdf",
+}
+
+@Article{tofte-talpin-97,
+ author = "Mads Tofte and Jean-Pierre Talpin",
+ title = "Region-based memory management",
+ journal = ic,
+ volume = "132",
+ number = "2",
+ year = "1997",
+ pages = "109--176",
+ URL = "http://www.irisa.fr/prive/talpin/papers/ic97.pdf",
+}
+
+@InProceedings{tolmach-97,
+ author = "Andrew Tolmach",
+ title = "Combining Closure Conversion with Closure Analysis
+ using Algebraic Types",
+ booktitle = tic,
+ year = "1997",
+ URL = "http://www.cs.pdx.edu/~apt/tic97.ps",
+}
+
+@Article{tolmach-oliva-98,
+ author = "Andrew Tolmach and Dino P. Oliva",
+ title = "From {ML} to {Ada}: Strongly-typed Language
+ Interoperability via Source Translation",
+ journal = jfp,
+ year = "1998",
+ volume = "8",
+ number = "4",
+ pages = "367--412",
+ URL = "http://dx.doi.org/10.1017/S0956796898003086",
+}
+
+@Article{topor-82,
+ author = "Rodney W. Topor",
+ title = "A Note on Error Recovery in Recursive Descent
+ Parsers",
+ journal = notices,
+ volume = "17",
+ number = "2",
+ year = "1982",
+ pages = "37--40",
+ URL = "http://doi.acm.org/10.1145/947902.947905",
+}
+
+@InProceedings{tov-pucella-10,
+ author = "Jesse A. Tov and Riccardo Pucella",
+ title = "Stateful Contracts for Affine Types",
+ booktitle = esop,
+ year = "2010",
+ pages = "550--569",
+ publisher = springer,
+ series = lncs,
+ volume = "6012",
+ URL = "http://www.eecs.harvard.edu/~tov/pubs/affine-contracts/affinecontracts10-bw.pdf",
+}
+
+@InProceedings{tov-pucella-11,
+ author = "Jesse A. Tov and Riccardo Pucella",
+ title = "Practical Affine Types",
+ booktitle = popl,
+ year = "2011",
+ pages = "447--458",
+ URL = "http://www.eecs.harvard.edu/~tov/pubs/alms/",
+}
+
+@InProceedings{trifonov-smith-96,
+ author = "Valery Trifonov and Scott Smith",
+ title = "Subtyping Constrained Types",
+ booktitle = sas,
+ series = lncs,
+ volume = "1145",
+ pages = "349--365",
+ year = "1996",
+ publisher = springer,
+ URL = "http://flint.cs.yale.edu/trifonov/papers/subcon.pdf",
+}
+
+@InProceedings{tschantz-ernst-05,
+ author = "Matthew S. Tschantz and Michael D. Ernst",
+ title = "Javari: adding reference immutability to {Java}",
+ booktitle = oopsla,
+ year = "2005",
+ pages = "211--230",
+ URL = "https://homes.cs.washington.edu/~mernst/pubs/ref-immutability-oopsla2005.pdf",
+}
+
+@InProceedings{tse-zdancewic-04,
+ author = "Stephen Tse and Steve Zdancewic",
+ title = "Run-time Principals in Information-flow Type Systems",
+ booktitle = sp,
+ year = "2004",
+ URL = "http://www.cis.upenn.edu/~stevez/papers/TZ04a.pdf",
+}
+
+@InProceedings{tsuiki-94,
+ author = "Hideki Tsuiki",
+ title = "On Typed Calculi with a Merge Operator",
+ booktitle = fsttcs,
+ pages = "101--112",
+ year = "1994",
+ volume = "880",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.i.h.kyoto-u.ac.jp/~tsuiki/papers/fsttcs.ps.gz",
+}
+
+@Unpublished{tuerk-10,
+ author = "Thomas Tuerk",
+ title = "Local reasoning about while-loops",
+ year = "2010",
+ note = "Unpublished",
+ URL = "http://www.cl.cam.ac.uk/~tt291/talks/vstte10.pdf",
+}
+
+@PhdThesis{turner-95,
+ author = "David N. Turner",
+ title = "The Polymorphic Pi-Calculus: Theory and
+ Implementation",
+ school = "University of Edinburgh",
+ year = "1995",
+ URL = "http://www.lfcs.inf.ed.ac.uk/reports/96/ECS-LFCS-96-345/",
+}
+
+@InProceedings{turner-wadler-mossin-95,
+ author = "David N. Turner and Philip Wadler and Christian
+ Mossin",
+ year = "1995",
+ title = "Once upon a type",
+ booktitle = fpca,
+ publisher = acmp,
+ pages = "1--11",
+ URL = "ftp://ftp.dcs.gla.ac.uk/pub/glasgow-fp/authors/Philip_Wadler/once.dvi",
+}
+
+@InProceedings{turon-caresl-13,
+ author = "Aaron Turon and Derek Dreyer and Lars Birkedal",
+ title = "Unifying refinement and {Hoare}-style reasoning in a
+ logic for higher-order concurrency",
+ booktitle = icfp,
+ year = "2013",
+ pages = "377--390",
+ URL = "http://www.mpi-sws.org/~turon/caresl/caresl.pdf",
+}
+
+@Misc{unicon,
+ title = "Unicon",
+ note = "\url{http://unicon.sourceforge.net/}",
+ URL = "http://unicon.sourceforge.net/",
+}
+
+@Article{urban-04,
+ author = "Christian Urban and Andrew Pitts and Murdoch Gabbay",
+ title = "Nominal Unification",
+ journal = tcs,
+ year = "2004",
+ URL = "http://gabbay.org.uk/papers/nomu-jv.pdf",
+ volume = "323",
+ pages = "473--497",
+}
+
+@Article{urban-08,
+ author = "Christian Urban",
+ title = "Nominal Techniques in {Isabelle/HOL}",
+ journal = jar,
+ volume = "40",
+ number = "4",
+ pages = "327--356",
+ year = "2008",
+ URL = "https://nms.kcl.ac.uk/christian.urban/Publications/nom-tech.pdf",
+}
+
+@Unpublished{urban-nipkow-08,
+ author = "Christian Urban and Tobias Nipkow",
+ title = "Nominal Verification of Algorithm {W}",
+ year = "2008",
+ note = "Unpublished",
+ URL = "http://www4.in.tum.de/~urbanc/Publications/w-07.pdf",
+}
+
+@InProceedings{urban-tasson-05,
+ author = "Christian Urban and Christine Tasson",
+ title = "Nominal Techniques in {Isabelle/HOL}",
+ booktitle = cade,
+ year = "2005",
+ series = lncs,
+ publisher = springer,
+ volume = "3632",
+ pages = "38--53",
+ URL = "http://www4.in.tum.de/~urbanc/Publications/nom-cade-05.ps",
+}
+
+@Unpublished{vacid,
+ author = "K. Rustan M. Leino and Michal Moskal",
+ title = "{VACID}-0: Verification of Ample Correctness of
+ Invariants of Data-structures, Edition 0",
+ note = "Manuscript KRML 209",
+ year = "2010",
+ URL = "http://research.microsoft.com/en-us/um/people/moskal/pdf/vacid0.pdf",
+}
+
+@Article{vafeiadis-11,
+ author = "Viktor Vafeiadis",
+ title = "Concurrent Separation Logic and Operational
+ Semantics",
+ journal = entcs,
+ volume = "276",
+ year = "2011",
+ pages = "335--351",
+ URL = "http://www.mpi-sws.org/~viktor/papers/mfps2011-cslsound.pdf",
+}
+
+@InProceedings{vaziri-jackson-03,
+ author = "Mandana Vaziri and Daniel Jackson",
+ title = "Checking Heap-Manipulating Procedures with a
+ Constraint Solver",
+ booktitle = tacas,
+ year = "2003",
+ publisher = springer,
+ series = lncs,
+ volume = "2619",
+ URL = "http://sdg.lcs.mit.edu/pubs/2003/checkingHMPs.pdf",
+}
+
+@InProceedings{vdw-mckinna-08,
+ author = "Eelis {van der Weegen} and James McKinna",
+ title = "A Machine-Checked Proof of the Average-Case Complexity
+ of {Quicksort} in {Coq}",
+ booktitle = types,
+ year = "2008",
+ pages = "256--271",
+ publisher = springer,
+ series = lncs,
+ volume = "5497",
+ URL = "http://www.xs4all.nl/~weegen/eelis/research/quicksort/",
+}
+
+@InProceedings{vergauwen-lewi-94,
+ author = "Bart Vergauwen and Johan Lewi",
+ title = "Efficient Local Correctness Checking for Single and
+ Alternating {Boolean} Equation Systems",
+ booktitle = icalp,
+ year = "1994",
+ pages = "304--315",
+ publisher = springer,
+ series = lncs,
+ volume = "820",
+ URL = "http://dx.doi.org/10.1007/3-540-58201-0_77",
+}
+
+@InProceedings{vergauwen-nested-94,
+ author = "Bart Vergauwen and Johan Lewi and I. Avau and A.
+ Poté",
+ title = "Efficient computation of nested fix-points, with
+ applications to model checking",
+ booktitle = ictl,
+ pages = "165--179",
+ year = "1994",
+ volume = "827",
+ series = lncs,
+ publisher = springer,
+ URL = "http://dx.doi.org/10.1007/BFb0013987",
+}
+
+@InProceedings{vergauwen-wauman-lewi-94,
+ author = "Bart Vergauwen and J. Wauman and Johan Lewi",
+ title = "Efficient fixpoint computation",
+ booktitle = sas,
+ pages = "314--328",
+ year = "1994",
+ volume = "864",
+ series = lncs,
+ publisher = springer,
+ URL = "http://dx.doi.org/10.1007/3-540-58485-4_49",
+}
+
+@TechReport{verifast,
+ author = "Bart Jacobs and Frank Piessens",
+ title = "The {VeriFast} Program Verifier",
+ institution = "Department of Computer Science, Katholieke
+ Universiteit Leuven",
+ year = "2008",
+ number = "CW-520",
+ URL = "http://people.cs.kuleuven.be/~bart.jacobs/verifast/verifast.pdf",
+}
+
+@InProceedings{villard-lozes-calcagno-09,
+ author = "Jules Villard and Étienne Lozes and Cristiano
+ Calcagno",
+ booktitle = aplas,
+ pages = "194--209",
+ publisher = springer,
+ series = lncs,
+ title = "Proving Copyless Message Passing",
+ URL = "http://www.lsv.ens-cachan.fr/Publis/PAPERS/PDF/VLC-aplas09.pdf",
+ volume = "5904",
+ year = "2009",
+}
+
+@InProceedings{villard-lozes-calcagno-10,
+ author = "Jules Villard and Étienne Lozes and Cristiano
+ Calcagno",
+ booktitle = tacas,
+ pages = "275--279",
+ publisher = springer,
+ series = lncs,
+ title = "Tracking Heaps that Hop with {Heap-Hop}",
+ URL = "http://www.lsv.ens-cachan.fr/Publis/PAPERS/PDF/VLC-tacas10.pdf",
+ volume = "6015",
+ year = "2010",
+}
+
+@Article{vitek-bokowski-01,
+ author = "Jan Vitek and Boris Bokowski",
+ title = "Confined types in {Java}",
+ journal = spe,
+ volume = "31",
+ number = "6",
+ pages = "507--532",
+ year = "2001",
+ URL = "https://www.cerias.purdue.edu/assets/pdf/bibtex_archive/2001-63.pdf",
+}
+
+@Article{volpano-97,
+ author = "Dennis Volpano",
+ title = "Provably-Secure Programming Languages for Remote
+ Evaluation",
+ journal = notices,
+ volume = "32",
+ number = "1",
+ pages = "117--119",
+ year = "1997",
+}
+
+@Article{volpano-smith-97,
+ author = "Dennis Volpano and Geoffrey Smith",
+ title = "A Type-Based Approach to Program Security",
+ journal = lncs,
+ volume = "1214",
+ pages = "607--621",
+ year = "1997",
+ URL = "http://www.cs.nps.navy.mil/people/faculty/volpano/papers/tapsoft97.ps.Z",
+}
+
+@InProceedings{volpano-smith-csfw-97,
+ author = "Dennis Volpano and Geoffrey Smith",
+ year = "1997",
+ title = "Eliminating Covert Flows with Minimum Typings",
+ booktitle = csfw,
+ pages = "156--168",
+ URL = "http://www.cs.nps.navy.mil/people/faculty/volpano/papers/csfw97.ps.Z",
+}
+
+@Article{volpano-smith-irvine-96,
+ author = "Dennis Volpano and Geoffrey Smith and Cynthia Irvine",
+ title = "A Sound Type System for Secure Flow Analysis",
+ journal = "Journal of Computer Security",
+ volume = "4",
+ number = "3",
+ pages = "167--187",
+ year = "1996",
+ URL = "http://www.cs.nps.navy.mil/people/faculty/volpano/papers/jcs96.ps.Z",
+}
+
+@InProceedings{vorobyov-96,
+ author = "Sergei G. Vorobyov",
+ title = "An Improved Lower Bound for the Elementary Theories of
+ Trees",
+ booktitle = cade,
+ pages = "275--287",
+ year = "1996",
+ volume = "1104",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.mpi-sb.mpg.de/~sv/publications/complexity/2ILB.ps.Z",
+}
+
+@InProceedings{vouillon-mellies-04,
+ author = "Jérôme Vouillon and Paul-André Melliès",
+ title = "Semantic types: a fresh look at the ideal model for
+ types",
+ booktitle = popl,
+ year = "2004",
+ pages = "52--63",
+ URL = "http://www.pps.jussieu.fr/~vouillon/publi/cbv.ps.gz",
+}
+
+@InProceedings{vries-06,
+ author = "Edsko de Vries and Rinus Plasmeijer and David
+ Abrahamson",
+ title = "Uniqueness Typing Redefined",
+ booktitle = ifl,
+ pages = "181--198",
+ year = "2006",
+ volume = "4449",
+ series = lncs,
+ publisher = springer,
+ URL = "https://www.cs.tcd.ie/~devriese/pub/ifl06-paper.pdf",
+}
+
+@InProceedings{vries-07,
+ author = "Edsko de Vries and Rinus Plasmeijer and David
+ Abrahamson",
+ title = "Equality Based Uniqueness Typing",
+ booktitle = tfp,
+ year = "2007",
+ URL = "https://www.cs.tcd.ie/~devriese/pub/tfp07-paper.pdf",
+}
+
+@Unpublished{vytiniotis-boxy-05,
+ author = "Dimitrios Vytiniotis and Stephanie Weirich and Simon
+ {Peyton Jones}",
+ title = "Boxy types: type inference for higher-rank types and
+ impredicativity",
+ note = "Manuscript",
+ year = "2005",
+ URL = "http://research.microsoft.com/Users/simonpj/papers/boxy/",
+}
+
+@Article{vytiniotis-outsidein-11,
+ author = "Dimitrios Vytiniotis and Simon {Peyton Jones} and Tom
+ Schrijvers and Martin Sulzmann",
+ title = "{OutsideIn(X)}: Modular type inference with local
+ assumptions",
+ journal = jfp,
+ volume = "21",
+ number = "4--5",
+ year = "2011",
+ pages = "333--412",
+ URL = "http://research.microsoft.com/en-us/um/people/simonpj/papers/constraints/jfp-outsidein.pdf",
+}
+
+@InProceedings{vytiniotis-pie-07,
+ author = "Dimitrios Vytiniotis and Stephanie Weirich",
+ title = "Dependent Types: Easy as {PIE}",
+ booktitle = tfp,
+ year = "2007",
+ URL = "http://www.seas.upenn.edu/~sweirich/papers/tfp07.pdf",
+}
+
+@InProceedings{wadler-85,
+ author = "Philip L. Wadler",
+ title = "How to replace failure by a list of successes",
+ booktitle = fpca,
+ publisher = springer,
+ series = lncs,
+ volume = "201",
+ year = "1985",
+ pages = "113--128",
+ URL = "http://dx.doi.org/10.1007/3-540-15975-4_33",
+}
+
+@InProceedings{wadler-blott-89,
+ author = "Philip Wadler and Stephen Blott",
+ title = "How to make ad-hoc polymorphism less ad-hoc",
+ pages = "60--76",
+ booktitle = popl,
+ year = "1989",
+ URL = "http://homepages.inf.ed.ac.uk/wadler/papers/class/class.ps.gz",
+}
+
+@Article{wadler-comprehending-92,
+ author = "Philip Wadler",
+ title = "Comprehending monads",
+ journal = mscs,
+ year = "1992",
+ volume = "2",
+ pages = "461--493",
+ URL = "http://homepages.inf.ed.ac.uk/wadler/papers/monads/monads.ps.gz",
+}
+
+@InProceedings{wadler-essence-92,
+ author = "Philip Wadler",
+ title = "The essence of functional programming",
+ booktitle = popl,
+ year = "1992",
+ pages = "1--14",
+ note = "Invited talk",
+ URL = "http://homepages.inf.ed.ac.uk/wadler/papers/essence/essence.ps",
+}
+
+@InProceedings{wadler-free-89,
+ author = "Philip Wadler",
+ title = "Theorems for free!",
+ booktitle = fpca,
+ year = "1989",
+ pages = "347--359",
+ URL = "http://homepages.inf.ed.ac.uk/wadler/papers/free/free.ps.gz",
+}
+
+@Article{wadler-isomorphism-07,
+ author = "Philip Wadler",
+ title = "The {Girard}-{Reynolds} isomorphism (second edition)",
+ journal = tcs,
+ year = "2007",
+ volume = "375",
+ number = "1--3",
+ pages = "201--226",
+ URL = "http://homepages.inf.ed.ac.uk/wadler/papers/gr2/gr2.pdf",
+}
+
+@InCollection{wadler-linear-90,
+ author = "Philip Wadler",
+ title = "Linear types can change the world!",
+ booktitle = "Programming Concepts and Methods",
+ publisher = "North Holland",
+ year = "1990",
+ editor = "M. Broy and C. Jones",
+ URL = "http://homepages.inf.ed.ac.uk/wadler/papers/linear/linear.ps",
+}
+
+@Article{wadler-thiemann-03,
+ author = "Philip Wadler and Peter Thiemann",
+ title = "The marriage of effects and monads",
+ journal = tocl,
+ volume = "4",
+ number = "1",
+ pages = "1--32",
+ year = "2003",
+ URL = "http://homepages.inf.ed.ac.uk/wadler/papers/effectstocl/effectstocl.ps.gz",
+}
+
+@InProceedings{walker-00,
+ author = "David Walker",
+ title = "A Type System for Expressive Security Policies",
+ booktitle = popl,
+ year = "2000",
+ pages = "254--267",
+ URL = "http://www.cs.cornell.edu/home/walker/papers/sa-popl00_ps.gz",
+}
+
+@InCollection{walker-attapl-05,
+ author = "David Walker",
+ title = "Substructural Type Systems",
+ booktitle = "Advanced Topics in Types and Programming Languages",
+ pages = "3--43",
+ publisher = mitp,
+ year = "2005",
+ editor = "Benjamin C. Pierce",
+ chapter = "1",
+}
+
+@Article{walker-capabilities-00,
+ author = "David Walker and Karl Crary and Greg Morrisett",
+ title = "Typed memory management via static capabilities",
+ journal = toplas,
+ volume = "22",
+ number = "4",
+ year = "2000",
+ pages = "701--771",
+ URL = "http://www.cs.princeton.edu/~dpw/papers/capabilities-toplas.pdf",
+}
+
+@PhdThesis{wallach-99,
+ author = "Dan S. Wallach",
+ title = "A New Approach to Mobile Code Security",
+ school = "Princeton University",
+ year = "1999",
+ URL = "http://www.cs.princeton.edu/sip/pub/dwallach-dissertation.html",
+}
+
+@Article{wallach-appel-felten-00,
+ author = "Dan S. Wallach and Andrew W. Appel and Edward W.
+ Felten",
+ title = "Safkasi: {A} Security Mechanism for Language-based
+ Systems",
+ journal = tosem,
+ year = "2000",
+ volume = "9",
+ number = "4",
+ pages = "341--378",
+ URL = "http://www.cs.rice.edu/~dwallach/pub/tosem2000.ps",
+}
+
+@InProceedings{wallach-felten-stack-98,
+ author = "Dan S. Wallach and Edward Felten",
+ title = "Understanding {Java} Stack Inspection",
+ booktitle = sp,
+ year = "1998",
+ URL = "http://www.cs.princeton.edu/sip/pub/oakland98.php3",
+}
+
+@Article{wand-80,
+ author = "Mitchell Wand",
+ title = "Continuation-Based Program Transformation Strategies",
+ journal = jacm,
+ volume = "27",
+ number = "1",
+ year = "1980",
+ pages = "164--180",
+ URL = "http://dx.doi.org/10.1145/322169.322183",
+}
+
+@InProceedings{wand-85,
+ author = "Mitchell Wand",
+ title = "Embedding type structure in semantics",
+ booktitle = popl,
+ year = "1985",
+ pages = "1--6",
+ URL = "http://doi.acm.org/10.1145/318593.318602",
+}
+
+@InProceedings{wand-86,
+ author = "Mitchell Wand",
+ title = "Finding the Source of Type Errors",
+ booktitle = popl,
+ pages = "38--43",
+ year = "1986",
+ URL = "http://doi.acm.org/10.1145/512644.512648",
+}
+
+@Article{wand-87,
+ author = "Mitchell Wand",
+ title = "A Simple Algorithm and Proof for Type Inference",
+ journal = fundamenta,
+ volume = "10",
+ pages = "115--122",
+ year = "1987",
+ URL = "http://www.cs.ucla.edu/~palsberg/course/cs239/reading/wand87.pdf",
+}
+
+@Article{wand-concat,
+ author = "Mitchell Wand",
+ title = "Type Inference for Record Concatenation and Multiple
+ Inheritance",
+ year = "1991",
+ volume = "93",
+ number = "1",
+ pages = "1--15",
+ journal = ic,
+ URL = "ftp://ftp.ccs.neu.edu/pub/people/wand/papers/ic-91.dvi",
+}
+
+@InCollection{wand-objects,
+ author = "Mitchell Wand",
+ title = "Type Inference for Objects with Instance Variables and
+ Inheritance",
+ booktitle = taoop,
+ editor = "Carl A. Gunter and John C. Mitchell",
+ publisher = mitp,
+ pages = "97--120",
+ year = "1994",
+ URL = "ftp://ftp.ccs.neu.edu/pub/people/wand/papers/gunter-mitchell-94.dvi",
+}
+
+@InProceedings{wand-steckler-94,
+ author = "Mitchell Wand and Paul A. Steckler",
+ title = "Selective and lightweight closure conversion",
+ booktitle = popl,
+ year = "1994",
+ pages = "435--445",
+ URL = "http://doi.acm.org/10.1145/174675.178044",
+}
+
+@Article{ward-96,
+ author = "Martin Ward",
+ title = "Derivation of Data Intensive Algorithms by Formal
+ Transformation -- The {Schorr-Waite} Graph Marking
+ Algorithm",
+ journal = tose,
+ year = "1996",
+ volume = "22",
+ number = "9",
+ pages = "665--686",
+ URL = "http://www.cse.dmu.ac.uk/~mward/martin/papers/sw-alg-t.pdf",
+}
+
+@InCollection{warren-82,
+ author = "D. H. D. Warren",
+ title = "Higher-order extensions to {PROLOG}: are they
+ needed?",
+ booktitle = "Machine Intelligence 10",
+ pages = "441--454",
+ publisher = ellis,
+ year = "1982",
+ editor = "J. E. Hayes and D. Michie and Y-H. Pao",
+}
+
+@InProceedings{warth-douglass-millstein-08,
+ author = "Alessandro Warth and James R. Douglass and Todd D.
+ Millstein",
+ title = "Packrat parsers can support left recursion",
+ booktitle = pepm,
+ year = "2008",
+ pages = "103--110",
+ URL = "http://www.cs.ucla.edu/~todd/research/pepm08.pdf",
+}
+
+@Article{wegbreit-75,
+ author = "Ben Wegbreit",
+ title = "Mechanical Program Analysis",
+ journal = cacm,
+ volume = "18",
+ number = "9",
+ year = "1975",
+ pages = "528--539",
+ URL = "http://doi.acm.org/10.1145/361002.361016",
+}
+
+@Article{wegener-02,
+ author = "Ingo Wegener",
+ title = "A simplified correctness proof for a well-known
+ algorithm computing strongly connected components",
+ journal = "Information Processing Letters",
+ year = "2002",
+ volume = "83",
+ number = "1",
+ pages = "17--19",
+ URL = "http://ls2-www.cs.uni-dortmund.de/~wegener/papers/connected.pdf",
+}
+
+@InProceedings{weirich-00,
+ author = "Stephanie Weirich",
+ title = "Type-Safe Cast: Functional Pearl",
+ booktitle = icfp,
+ year = "2000",
+ pages = "58--67",
+ URL = "http://www.cis.upenn.edu/~sweirich/papers/cast/cast.pdf",
+}
+
+@Article{weirich-polytypic-06,
+ author = "Stephanie Weirich",
+ title = "Type-Safe Run-time Polytypic Programming",
+ journal = jfp,
+ year = "2006",
+ volume = "16",
+ number = "10",
+ pages = "681--710",
+ URL = "http://www.seas.upenn.edu/~sweirich/papers/erasure/erasure-jfp.pdf",
+}
+
+@InProceedings{weirich-replib-06,
+ author = "Stephanie Weirich",
+ title = "{RepLib}: a library for derivable type classes",
+ booktitle = hw,
+ pages = "1--12",
+ year = "2006",
+ URL = "http://www.seas.upenn.edu/~sweirich/RepLib/haskell08-weirich.pdf",
+}
+
+@Misc{weirich-tc-04,
+ author = "Stephanie Weirich",
+ title = "A typechecker that produces a typed term from an
+ untyped source",
+ howpublished = "Part of the Glasgow Haskell compiler's test suite",
+ year = "2004",
+ URL = "http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/testsuite/tests/ghc-regress/gadt/tc.hs?rev=1.1",
+}
+
+@InProceedings{weirich-yorgey-sheard-11,
+ author = "Stephanie Weirich and Brent A. Yorgey and Tim Sheard",
+ title = "Binders unbound",
+ booktitle = icfp,
+ pages = "333--345",
+ year = "2011",
+ URL = "http://www.seas.upenn.edu/~sweirich/papers/icfp11.pdf",
+}
+
+@InProceedings{wells-02,
+ author = "J. B. Wells",
+ title = "The Essence of Principal Typings",
+ booktitle = icalp,
+ pages = "913--925",
+ publisher = springer,
+ volume = "2380",
+ series = lncs,
+ year = "2002",
+ URL = "http://www.macs.hw.ac.uk/~jbw/papers/Wells:The-Essence-of-Principal-Typings:ICALP-2002.pdf",
+}
+
+@TechReport{wells-95,
+ author = "J. B. Wells",
+ title = "The Undecidability of {Mitchell's} Subtyping
+ Relation",
+ institution = "Computer Science Department, Boston University",
+ year = "1995",
+ URL = "http://www.cs.bu.edu/ftp/pub/jbw/types/subtyping-undecidable.ps.gz",
+ type = "Technical Report",
+ number = "95-019",
+}
+
+@Article{wells-99,
+ author = "J. B. Wells",
+ title = "Typability and type checking in System {F} are
+ equivalent and undecidable",
+ journal = apal,
+ year = "1999",
+ volume = "98",
+ number = "1--3",
+ pages = "111--156",
+ URL = "http://www.macs.hw.ac.uk/~jbw/papers/f-undecidable-APAL.ps.gz",
+}
+
+@PhdThesis{werner-94,
+ author = "Benjamin Werner",
+ title = "Une Théorie des Constructions Inductives",
+ school = "Université Paris 7",
+ year = "1994",
+}
+
+@InProceedings{westbrook-05,
+ author = "Edwin Westbrook and Aaron Stump and Ian Wehrman",
+ title = "A language-based approach to functionally correct
+ imperative programming",
+ booktitle = icfp,
+ year = "2005",
+ pages = "268--279",
+ URL = "http://cl.cse.wustl.edu/papers/rsp1-icfp05.pdf",
+}
+
+@PhdThesis{westbrook-08,
+ author = "Edwin M. Westbrook",
+ title = "Higher-Order Encodings with Constructors",
+ school = "Washington University",
+ year = "2008",
+ URL = "http://www.cs.rice.edu/~emw4/thesis-westbrook.pdf",
+}
+
+@TechReport{why,
+ author = "Jean-Christophe Filliâtre",
+ title = "{Why}: a multi-language multi-prover verification
+ tool",
+ institution = "LRI, Université Paris Sud",
+ type = "Research Report",
+ number = "1366",
+ year = "2003",
+ URL = "http://www.lri.fr/~filliatr/ftp/publis/why-tool.ps.gz",
+}
+
+@InProceedings{why-07,
+ author = "Jean-Christophe Filliâtre and Claude Marché",
+ title = "The {Why}/{Kra\-ka\-toa}/{Ca\-du\-ceus} Platform for
+ Deductive Program Verification",
+ booktitle = cav,
+ year = "2007",
+ pages = "173--177",
+ volume = "4590",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.lri.fr/~filliatr/ftp/publis/cav07.pdf",
+}
+
+@Article{williams-64,
+ author = "J. W. J. Williams",
+ title = "Algorithm 232: Heapsort",
+ journal = cacm,
+ year = "1964",
+ volume = "7",
+ number = "6",
+ pages = "347--348",
+ URL = "http://doi.acm.org/10.1145/512274.512284",
+}
+
+@InProceedings{wing-rollins-zaremsky-92,
+ author = "Jeannette M. Wing and Eugene Rollins and Amy Moormann
+ Zaremski",
+ title = "Thoughts on a {Larch/ML} and a New Application for
+ {LP}",
+ booktitle = "First International Workshop on Larch",
+ year = "1992",
+ URL = "http://reports-archive.adm.cs.cmu.edu/anon/usr0/ftp/home/ftp/1992/CMU-CS-92-135.ps",
+ pages = "297--312",
+}
+
+@Book{wirth-78,
+ author = "Niklaus Wirth",
+ title = "Algorithms + Data Structures = Programs",
+ year = "1978",
+ publisher = prentice,
+}
+
+@InProceedings{wisnesky-malecha-morrisett-09,
+ author = "Ryan Wisnesky and Gregory Malecha and Greg Morrisett",
+ title = "Certified Web Services in {Ynot}",
+ booktitle = wwv,
+ year = "2009",
+ URL = "http://wisnesky.net/wwv09.pdf",
+}
+
+@InProceedings{wolff-11,
+ author = "Roger Wolff and Ronald Garcia and \'{E}ric Tanter and
+ Jonathan Aldrich",
+ title = "Gradual typestate",
+ booktitle = ecoop,
+ year = "2011",
+ pages = "459--483",
+ publisher = springer,
+ series = lncs,
+ volume = "6813",
+ URL = "http://www.cs.cmu.edu/~aldrich/papers/aldrich-gradual-ecoop11.pdf",
+}
+
+@InProceedings{woodward-79,
+ author = "J. P. L. Woodward",
+ title = "Applications for Multilevel Secure Operating Systems",
+ booktitle = "Proceedings NCC",
+ year = "1979",
+ pages = "319--328",
+ volume = "48",
+ publisher = "{AFIPS} Press",
+}
+
+@Article{wright-cartwright-97,
+ author = "Andrew K. Wright and Robert Cartwright",
+ title = "A Practical Soft Type System for {Scheme}",
+ journal = toplas,
+ volume = "19",
+ number = "1",
+ pages = "87--152",
+ year = "1997",
+ URL = "http://doi.acm.org/10.1145/239912.239917",
+}
+
+@Article{wright-felleisen-94,
+ title = "A Syntactic Approach to Type Soundness",
+ author = "Andrew K. Wright and Matthias Felleisen",
+ pages = "38--94",
+ journal = ic,
+ year = "1994",
+ volume = "115",
+ number = "1",
+ URL = "http://www.cs.rice.edu/CS/PLT/Publications/Scheme/ic94-wf.ps.gz",
+}
+
+@TechReport{wright-restriction-93,
+ author = "Andrew K. Wright",
+ institution = "Rice University",
+ title = "Polymorphism for Imperative Languages without
+ Imperative Types",
+ year = "1993",
+ number = "93-200",
+}
+
+@Article{wright-restriction-95,
+ author = "Andrew K. Wright",
+ title = "Simple Imperative Polymorphism",
+ journal = lsc,
+ volume = "8",
+ number = "4",
+ year = "1995",
+ pages = "343--356",
+ URL = "http://www.cs.rice.edu/CS/PLT/Publications/Scheme/lasc95-w.ps.gz",
+}
+
+@InProceedings{wyk-99,
+ author = "Eric van Wyk and Oege de Moor and Simon {Peyton
+ Jones}",
+ title = "Aspect-oriented compilers",
+ booktitle = gcse,
+ pages = "121--133",
+ year = "1999",
+ volume = "1799",
+ series = lncs,
+ publisher = springer,
+ URL = "https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/aspects.pdf",
+}
+
+@PhdThesis{xi-98,
+ author = "Hongwei Xi",
+ title = "Dependent Types in Practical Programming",
+ school = "Carnegie Mellon University",
+ year = "1998",
+ URL = "http://www.cs.bu.edu/~hwxi/academic/papers/thesis.ps",
+}
+
+@InProceedings{xi-ats,
+ author = "Hongwei Xi",
+ title = "Applied Type System",
+ year = "2004",
+ booktitle = "{TYPES} 2003",
+ publisher = springer,
+ series = lncs,
+ volume = "3085",
+ pages = "394--408",
+ URL = "http://www.cs.bu.edu/~hwxi/academic/papers/types03.pdf",
+}
+
+@InProceedings{xi-chen-chen-03,
+ author = "Hongwei Xi and Chiyan Chen and Gang Chen",
+ title = "Guarded Recursive Datatype Constructors",
+ booktitle = popl,
+ year = "2003",
+ pages = "224--235",
+ URL = "http://www.cs.bu.edu/fac/hwxi/academic/papers/popl03.ps",
+}
+
+@InProceedings{xi-cps-01,
+ author = "Hongwei Xi and Carsten Schürmann",
+ title = "{CPS} Transform for {Dependent ML}",
+ booktitle = wollic,
+ year = "2001",
+ URL = "http://www.cs.bu.edu/~hwxi/academic/papers/DMLcps.pdf",
+}
+
+@InProceedings{xi-dead-99,
+ author = "Hongwei Xi",
+ title = "Dead Code Elimination through Dependent Types",
+ booktitle = padl,
+ pages = "228--242",
+ year = "1999",
+ volume = "1551",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.cs.bu.edu/~hwxi/academic/papers/padl99.ps",
+}
+
+@Misc{xi-dml,
+ author = "Hongwei Xi",
+ title = "Dependent {ML}",
+ year = "2001",
+ URL = "http://www.cs.bu.edu/~hwxi/DML/DML.html",
+}
+
+@Article{xi-dml-07,
+ author = "Hongwei Xi",
+ title = "Dependent {ML}: an approach to practical programming
+ with dependent types",
+ journal = jfp,
+ year = "2007",
+ volume = "17",
+ number = "2",
+ pages = "215--286",
+ URL = "http://www.cs.bu.edu/~hwxi/academic/papers/JFPdml.pdf",
+}
+
+@Article{xi-patterns-03,
+ author = "Hongwei Xi",
+ title = "{Dependently Typed Pattern Matching}",
+ journal = jucs,
+ volume = "9",
+ number = "8",
+ year = "2003",
+ pages = "851--872",
+ URL = "http://www.cs.bu.edu/~hwxi/academic/papers/jucs03.pdf",
+}
+
+@InProceedings{xi-pfenning-99,
+ author = "Hongwei Xi and Frank Pfenning",
+ title = "Dependent Types in Practical Programming",
+ booktitle = popl,
+ year = "1999",
+ pages = "214--227",
+ URL = "http://www.ececs.uc.edu/~hwxi/academic/papers/popl99.ps",
+}
+
+@InProceedings{xi-views-05,
+ author = "Dengping Zhu and Hongwei Xi",
+ title = "Safe Programming with Pointers through Stateful
+ Views",
+ booktitle = padl,
+ publisher = springer,
+ series = lncs,
+ volume = "3350",
+ year = "2005",
+ pages = "83--97",
+ URL = "http://www.cs.bu.edu/~hwxi/academic/papers/padl05.pdf",
+}
+
+@InProceedings{xie-aiken-05,
+ author = "Yichen Xie and Alex Aiken",
+ title = "Scalable error detection using {Boolean}
+ satisfiability",
+ booktitle = popl,
+ year = "2005",
+ pages = "351--363",
+ URL = "http://glide.stanford.edu/saturn/papers/popl05.pdf",
+}
+
+@InProceedings{xu-06,
+ author = "Dana N. Xu",
+ title = "Extended static checking for {Haskell}",
+ booktitle = hw,
+ year = "2006",
+ pages = "48--59",
+ publisher = acmp,
+ URL = "http://www.cl.cam.ac.uk/~nx200/research/escH-hw.ps",
+}
+
+@InProceedings{xu-09,
+ author = "Dana N. Xu and Simon {Peyton Jones} and Koen
+ Claessen",
+ title = "Static contract checking for {Haskell}",
+ booktitle = popl,
+ year = "2009",
+ pages = "41--52",
+ URL = "http://research.microsoft.com/en-us/um/people/simonpj/papers/verify/HaskellContract.ps",
+}
+
+@InProceedings{yang-join-08,
+ author = "Hongseok Yang and Oukseh Lee and Josh Berdine and
+ Cristiano Calcagno and Byron Cook and Dino Distefano
+ and Peter W. O'Hearn",
+ title = "Scalable Shape Analysis for Systems Code",
+ year = "2008",
+ pages = "385--398",
+ booktitle = cav,
+ publisher = springer,
+ series = lncs,
+ volume = "5123",
+ URL = "http://research.microsoft.com/en-us/um/cambridge/projects/terminator/cav08b.pdf",
+}
+
+@Article{yi-06,
+ author = "Kwangkeun Yi",
+ title = "Educational Pearl: 'Proof-directed debugging'
+ revisited for a first-order version",
+ journal = jfp,
+ volume = "16",
+ number = "6",
+ year = "2006",
+ pages = "663--670",
+ URL = "http://ropas.snu.ac.kr/~kwang/paper/06-jfp-yi.pdf",
+}
+
+@InProceedings{yoshida-96,
+ author = "Nobuko Yoshida",
+ title = "Graph Types for Monadic Mobile Processes",
+ booktitle = fsttcs,
+ mon = dec,
+ year = "1996",
+ publisher = springer,
+ series = lncs,
+ volume = "1180",
+ pages = "371--386",
+ URL = "http://www.mcs.le.ac.uk/~nyoshida/paper/graph1_short.ps.gz",
+}
+
+@TechReport{yoshida-96-full,
+ author = "Nobuko Yoshida",
+ title = "Graph Types for Monadic Mobile Processes",
+ number = "ECS-LFCS-96-350",
+ institution = "University of Edinburgh",
+ year = "1996",
+ URL = "http://www.lfcs.inf.ed.ac.uk/reports/96/ECS-LFCS-96-350/",
+}
+
+@InProceedings{yoshida-al-02,
+ author = "Nobuko Yoshida and Kohei Honda and Martin Berger",
+ title = "Linearity and Bisimulation",
+ booktitle = fossacs,
+ publisher = springer,
+ series = lncs,
+ year = "2002",
+ URL = "http://www.mcs.le.ac.uk/~nyoshida/paper/fossacs_ca_final.ps.gz",
+}
+
+@TechReport{yoshida-al-02-long,
+ author = "Nobuko Yoshida and Kohei Honda and Martin Berger",
+ title = "Linearity and Bisimulation",
+ institution = "University of Leicester",
+ year = "2001",
+ number = "MSC-2001/48",
+ URL = "http://www.mcs.le.ac.uk/~nyoshida/paper/lb.ps.gz",
+}
+
+@InProceedings{yoshida-honda-berger-07,
+ author = "Nobuko Yoshida and Kohei Honda and Martin Berger",
+ title = "Logical Reasoning for Higher-Order Functions with
+ Local State",
+ booktitle = fossacs,
+ pages = "361--377",
+ year = "2007",
+ volume = "4423",
+ series = lncs,
+ publisher = springer,
+ URL = "http://www.doc.ic.ac.uk/~mberger/publications/fossacs07/fossacs07.pdf",
+}
+
+@InProceedings{zdancewic-myers-01,
+ author = "Steve Zdancewic and Andrew C. Myers",
+ title = "Secure Information Flow and {CPS}",
+ booktitle = esop,
+ publisher = springer,
+ series = lncs,
+ year = "2001",
+ URL = "http://www.cs.cornell.edu/zdance/lincont.ps",
+}
+
+@Article{zdancewic-myers-02,
+ author = "Steve Zdancewic and Andrew C. Myers",
+ title = "Secure Information Flow via Linear Continuations",
+ journal = "Higher Order and Symbolic Computation",
+ year = "2002",
+ volume = "15",
+ number = "2--3",
+ pages = "209--234",
+ URL = "http://www.cis.upenn.edu/~stevez/papers/ZM02.pdf",
+}
+
+@InProceedings{zendra-97,
+ author = "Olivier Zendra and Dominique Colnet and Suzanne
+ Collin",
+ title = "Efficient Dynamic Dispatch without Virtual Function
+ Tables. The {SmallEiffel} Compiler",
+ booktitle = oopsla,
+ pages = "125--141",
+ year = "1997",
+ URL = "http://www.loria.fr/~colnet/publis/oopsla97.ps.gz",
+}
+
+@Article{zenger-97,
+ author = "Christoph Zenger",
+ title = "Indexed Types",
+ journal = tcs,
+ year = "1997",
+ volume = "187",
+ number = "1--2",
+ pages = "147--165",
+ URL = "http://dx.doi.org/10.1016/S0304-3975(97)00062-5",
+}
+
+@PhdThesis{zenger-98,
+ author = "Christoph Zenger",
+ title = "Indizierte Typen",
+ school = "Universität Karlsruhe",
+ year = "1998",
+ URL = "http://www.christoph-zenger.de/papers/thesis.ps.gz",
+}
+
+@PhdThesis{zhao-07,
+ author = "Yang Zhao",
+ title = "Concurrency Analysis Based on Fractional Permission
+ System",
+ school = "University of Wisconsin",
+ year = "2007",
+ URL = "http://www.cs.uwm.edu/~boyland/papers/yangzhao-thesis.pdf",
+}
+
+@TechReport{zheng-myers-04,
+ author = "Lantian Zheng and Andrew C. Myers",
+ title = "Dynamic Security Labels and Noninterference",
+ institution = "Cornell University",
+ year = "2004",
+ number = "2004-1924",
+ URL = "http://www.cs.cornell.edu/andru/papers/dynl-tr.pdf",
+}
+
+@InProceedings{zhu-xi-03,
+ author = "Dengping Zhu and Hongwei Xi",
+ title = "A Typeful and Tagless Representation for {XML}
+ Documents",
+ booktitle = aplas,
+ publisher = springer,
+ series = lncs,
+ volume = "2895",
+ year = "2003",
+ pages = "89--104",
+ URL = "http://www.cs.bu.edu/~hwxi/academic/papers/aplas03.pdf",
+}
+
+@Misc{zibin-gil-01,
+ author = "Yoav Zibin and Yossi Gil",
+ title = "Theory and Practice of Incremental Subtyping Tests and
+ Message Dispatching",
+ year = "2001",
+ URL = "http://www.cs.technion.ac.il/~yogi/incremental-dispatching.ps.gz",
+}
+
+@InProceedings{zibin-gil-02,
+ author = "Yoav Zibin and Yossi Gil",
+ title = "Fast Algorithm for Creating Space Efficient
+ Dispatching Tables with Application to
+ Multi-Dispatching",
+ booktitle = oopsla,
+ pages = "142--160",
+ year = "2002",
+ URL = "http://www.cs.technion.ac.il/~zyoav/publications/OOPSLA02-dispatching-TS.pdf",
+}
+
+@InProceedings{zibin-gil-03,
+ author = "Yoav Zibin and Yossi Gil",
+ title = "Incremental Algorithms for Dispatching in Dynamically
+ Typed Languages",
+ booktitle = popl,
+ year = "2003",
+ URL = "http://www.cs.technion.ac.il/~zyoav/publications/POPL03-dispatching-CT.pdf",
+}
+
+@TechReport{zwanenburg-97,
+ author = "Jan Zwanenburg",
+ title = "A Type System for Record Concatenation and Subtyping",
+ year = "1997",
+ institution = "Eindhoven University of Technology",
+ URL = "http://www.cs.ru.nl/~janz/publications/type_check.ps",
+}
diff --git a/doc/from-visitors-to-iterators.md b/doc/from-visitors-to-iterators.md
new file mode 100644
index 0000000..fd1733e
--- /dev/null
+++ b/doc/from-visitors-to-iterators.md
@@ -0,0 +1,493 @@
+I have been asked whether
+an automatically-generated visitor,
+as produced by the [visitors](https://gitlab.inria.fr/fpottier/visitors)
+syntax extension for OCaml,
+can be used to construct an iterator.
+
+It turns out that this can be done
+in a simple and efficient manner.
+(Up to a constant factor, the time complexity of this solution is optimal.)
+As the problem is interesting and
+its solution is somewhat nonobvious,
+I am describing them here.
+
+To play with this code in an OCaml toplevel,
+first install `visitors` via the command `opam install visitors`.
+Then, launch `ocaml` and type this:
+
+```
+#use "topfind";;
+#require "visitors.ppx";;
+#require "visitors.runtime";;
+```
+
+## Problem Statement
+
+Suppose we have an arbitrary data structure that contains elements
+of type `'a`. Here, it is a binary tree, but it could be anything:
+
+```
+type 'a sometree =
+ | Leaf
+ | Node of 'a sometree * 'a * 'a sometree
+```
+
+We would like to enumerate the elements of this data structure.
+More precisely, we would like to construct an iterator, that is,
+an on-demand producer of elements. Here is a simple definition
+of a stateful iterator:
+
+```
+type 'a iterator =
+ unit -> 'a option
+```
+
+The question is, can we construct an iterator for the type `'a sometree`,
+based on an automatically-generated visitor, so that the construction is
+entirely independent of the type `'a sometree`?
+
+## Cascades
+
+For starters, let us define cascades, which are a more pleasant kind of
+iterators. A cascade is a persistent (stateless) iterator. It can be thought
+of as a delayed list, that is, a list whose elements are computed only on
+demand.
+
+Cascades could (should) be part of a separate library.
+As the time of writing (March, 2017), there is in fact
+[a proposal](https://github.com/ocaml/ocaml/pull/1002)
+to add them to OCaml's standard library.
+
+```
+type 'a cascade =
+ unit -> 'a head
+
+and 'a head =
+ | Nil
+ | Cons of 'a * 'a cascade
+```
+
+A delayed computation is represented as a function of type `unit -> _`.
+
+The cascade constructors are as follows:
+
+```
+let nil : 'a cascade =
+ fun () -> Nil
+
+let cons (x : 'a) (xs : 'a cascade) : 'a cascade =
+ fun () -> Cons (x, xs)
+```
+
+Forcing a cascade reveals its head:
+
+```
+let force xs =
+ xs()
+```
+
+A cascade can be easily converted to a stateful iterator:
+
+```
+let cascade_to_iterator (xs : 'a cascade) : 'a iterator =
+ let s = ref xs in
+ fun () ->
+ match force !s with
+ | Nil ->
+ s := nil;
+ None
+ | Cons (x, xs) ->
+ s := xs;
+ Some x
+```
+
+In the above code, writing `nil` into `s` may seem superfluous, but is in fact
+necessary to guarantee that the computation that led to a `Nil` outcome is not
+repeated in the future.
+
+Because cascades are close cousins of lists, they are easy to work with.
+Constructing a cascade for a tree-like data structure is straightforward,
+whereas directly constructing a stateful iterator would be more involved.
+
+## Back to the problem
+
+Now, can we use some kind of visitor to turn a tree of type `'a sometree`
+into a cascade of type `'a cascade`?
+
+At first sight, this does not seem very easy, because of two issues:
+
+ * a visitor usually traverses a tree in an eager manner, whereas we need the
+ traversal to make progress only as cascade elements are demanded;
+
+ * a visitor performs a bottom-up computation, without a left-to-right bias
+ (assuming mutable state is not used), whereas a cascade enumerates elements
+ in a left-to-right manner. (Or in a right-to-left manner. As will be
+ apparent below, both directions are possible.)
+
+The trick is to use another intermediate step. Instead of turning a tree
+directly into a cascade, we first transform it into a generic tree-like
+structure: a *delayed tree*. The first issue above is solved because, by
+introducing delays into the new tree, we allow its construction to be carried
+out on demand. The second issue is solved because this tree-to-tree
+transformation can be carried out in a purely bottom-up manner by a `reduce`
+visitor. Then, finally, it is straightforward to transform a delayed tree into
+a cascade.
+
+## From Delayed Trees to Cascades and Iterators
+
+A delayed tree contains ordinary nodes of arity 0, 1, and 2. Furthermore,
+it contains `DTDelay` nodes, of arity 1, whose child is delayed, that is,
+computed only on demand.
+
+```
+type 'a delayed_tree =
+ | DTZero
+ | DTOne of 'a
+ | DTTwo of 'a delayed_tree * 'a delayed_tree
+ | DTDelay of (unit -> 'a delayed_tree)
+```
+
+A delayed tree is converted to a cascade as follows. As is often the case,
+when building a cascade, one must take a continuation `k` as an argument, so
+as to avoid naive and costly cascade concatenation operations. Thus, the
+specification of the function call `delayed_tree_to_cascade dt k` is to
+construct a cascade whose elements are the elements of the delayed tree `dt`
+(listed from left to right), followed with the elements of the cascade `k`.
+
+```
+let rec delayed_tree_to_cascade (dt : 'a delayed_tree) (k : 'a cascade)
+: 'a cascade =
+ fun () -> delayed_tree_to_head dt k
+
+and delayed_tree_to_head (dt : 'a delayed_tree) (k : 'a cascade) : 'a head =
+ match dt with
+ | DTZero ->
+ force k
+ | DTOne x ->
+ Cons (x, k)
+ | DTTwo (dt1, dt2) ->
+ delayed_tree_to_head dt1 (delayed_tree_to_cascade dt2 k)
+ | DTDelay dt ->
+ delayed_tree_to_head (force dt) k
+
+let delayed_tree_to_cascade (dt : 'a delayed_tree) : 'a cascade =
+ delayed_tree_to_cascade dt nil
+
+let delayed_tree_to_iterator (dt : 'a delayed_tree) : 'a iterator =
+ cascade_to_iterator (delayed_tree_to_cascade dt)
+```
+
+In the above code, we have chosen to perform a left-to-right traversal of
+the delayed tree, but could just as well have chosen a right-to-left traversal.
+
+It is possible to make the delayed tree data structure implicit in the code;
+this is explained [further on](#variant-getting-rid-of-explicit-delayed-trees).
+
+## Constructing Delayed Trees
+
+The type `'a delay` is a synonym for `'a`. We will use it as a decoration, in
+a type definition, to indicate that a call to the method `visit_delay` is
+desired.
+
+```
+type 'a delay = 'a
+```
+
+We now set up four constructor functions or constructor methods, which
+construct delayed trees, and which we will use in a `reduce` visitor.
+
+Delayed trees form a monoid, in the sense that we concatenate them using
+`DTTwo`, and the neutral element is `DTZero`. We package these two data
+constructors in the methods `zero` and `plus`, which are automatically called
+in an automatically-generated `reduce` visitor.
+
+The visitor method `visit_delay` delays the visit of a subtree by constructing
+and returning a `DTDelay` node, which carries a delayed recursive call to a
+visitor.
+
+The visitor function `yield` will be invoked at elements of type `'a`. It
+constructs a one-element delayed tree.
+
+```
+class ['self] delayed_tree_monoid = object (_ : 'self)
+
+ method zero =
+ DTZero
+
+ method plus s1 s2 =
+ match s1, s2 with
+ | DTZero, s
+ | s, DTZero ->
+ s
+ | _, _ ->
+ DTTwo (s1, s2)
+
+ method visit_delay: 'env 'a .
+ ('env -> 'a -> 'b delayed_tree) ->
+ 'env -> 'a delay -> 'b delayed_tree
+ = fun visit_'a env x ->
+ DTDelay (fun () -> visit_'a env x)
+
+end
+
+let yield _env x =
+ DTOne x
+```
+
+In the method `plus`, above, treating `DTZero` specially is not mandatory. It
+is an optimization, which helps allocate fewer nodes.
+
+## Generating a Visitor
+
+It is now time to generate a `reduce` visitor for the type `'a sometree`.
+This is the only part of the code which is specific of `sometree`.
+Everything else is generic.
+
+We must insert *delays* into the structure of the type `'a sometree` so as to
+indicate where `visit_delay` should be called and (therefore) where `DTDelay`
+nodes should be allocated. To do this, we write a copy of the definition of
+the type `'a sometree`, with extra uses of `delay` in it. The new type is
+actually considered equal to `'a sometree` by OCaml. Its role is purely to
+carry a `@@deriving visitors` annotation.
+
+In the data constructor `Node`, the left-hand `delay` is in fact superfluous.
+With or without it, our iterators will eagerly descend along the leftmost
+branch of a tree, anyway.
+
+```
+type 'a mytree = 'a sometree =
+ | Leaf
+ | Node of 'a mytree delay * 'a * 'a mytree delay
+
+and 'a mytree_delay =
+ 'a mytree delay
+
+[@@deriving visitors { variety = "reduce"; polymorphic = true;
+ concrete = true; ancestors = ["delayed_tree_monoid"] }]
+```
+
+This approach is pleasant insofar as one controls exactly where delays are
+inserted. However, it requires copying the type definition, which may be
+unpleasant. Another approach is described
+[further on](#variant-avoiding-duplication-of-the-type-definition).
+
+## Using the Generated Visitor
+
+For demonstration purposes, let us make our visitor verbose. In production,
+one should remove `verbose_reduce` and use `reduce` instead.
+
+```
+class ['self] verbose_reduce = object (_ : 'self)
+ inherit [_] reduce as super
+ method! visit_Leaf visit_'a env =
+ Printf.printf "Visiting a leaf.\n%!";
+ super#visit_Leaf visit_'a env
+ method! visit_Node visit_'a env t1 x t2 =
+ Printf.printf "Visiting a node.\n%!";
+ super#visit_Node visit_'a env t1 x t2
+end
+```
+
+The problem is solved! There remains to write a couple lines of glue code:
+
+```
+let sometree_to_delayed_tree (t : 'a sometree) =
+ new verbose_reduce # visit_mytree_delay yield () t
+
+let sometree_to_iterator (t : 'a sometree) : 'a iterator =
+ delayed_tree_to_iterator (sometree_to_delayed_tree t)
+```
+
+We use `visit_mytree_delay` above, even though `visit_mytree` would work just
+as well, so as to ensure that we get a delayed tree whose root is a `DTDelay`
+node. Thus, absolutely no work is performed when the iterator is created;
+iteration begins only when the first element is demanded.
+
+## Demo
+
+A little demo helps see what is going on.
+
+```
+let t : int sometree =
+ Node (Node (Leaf, 1, Leaf), 2, Node (Leaf, 3, Leaf))
+
+let i : int iterator =
+ sometree_to_iterator t
+```
+
+Here is a transcript of an OCaml toplevel session:
+
+```
+ # i();;
+ Visiting a node.
+ Visiting a node.
+ Visiting a leaf.
+ - : int option = Some 1
+ # i();;
+ Visiting a leaf.
+ - : int option = Some 2
+ # i();;
+ Visiting a node.
+ Visiting a leaf.
+ - : int option = Some 3
+ # i();;
+ Visiting a leaf.
+ - : int option = None
+ # i();;
+ - : int option = None
+```
+
+## Variant: Avoiding Duplication of the Type Definition
+
+Earlier, we have generated a visitor for the existing type `'a sometree` in *a
+posteriori* style. We have manually created an isomorphic copy of the type `'a
+sometree`, which we have named `'a mytree`, and have annotated this copy with
+`[@@deriving visitors { ... }]`. Furthermore, we have taken this opportunity
+to insert `delay` type constructors into the type, so as to influence the
+generated visitor.
+
+This style is relatively pleasant because it is declarative and lets us
+control exactly where delays are inserted. However, it requires duplicating
+the definition of the type `'a sometree`, which may be unpleasant (if the
+definition is large) or impossible (if the definition is hidden behind an
+abstraction barrier).
+
+Another approach is to generate a visitor in *a priori* style. When the type
+`'a sometree` is first defined, a `reduce` visitor can be immediately
+generated for it, as follows:
+
+```
+type 'a sometree =
+ | Leaf
+ | Node of 'a sometree * 'a * 'a sometree
+
+[@@deriving visitors { variety = "reduce"; polymorphic = true;
+ name = "sometree_reduce" }]
+```
+
+At this point, we pretend that we do not know yet what this visitor will be
+used for, so we do not annotate the type definition with `delay`, and do not
+use `delayed_tree_monoid` as a base class. We get a visitor class, named
+`sometree_reduce`. This class has two virtual methods, `zero` and `plus`.
+
+Then, we create a subclass, named `reduce`, which we tailor to our needs.
+We mix the generated class `sometree_reduce` with the class `delayed_tree_monoid`,
+and insert a delay at every tree node by overriding the method `visit_sometree`:
+
+```
+class ['self] reduce = object (self : 'self)
+ inherit [_] sometree_reduce as super
+ inherit [_] delayed_tree_monoid
+ method! visit_sometree visit_'a env t =
+ self#visit_delay (super#visit_sometree visit_'a) env t
+end
+```
+
+The rest of the code is unchanged (except the method `visit_mytree_delay` no
+longer exists; one calls `visit_sometree` instead).
+
+## Variant: Getting Rid of Explicit Delayed Trees
+
+I like to present delayed trees as an explicit data structure, because this
+helps understand what is going on. However, if desired, it is possible to
+hide them by *refunctionalization* (the opposite of *defunctionalization*).
+
+Above, the function `delayed_tree_to_cascade` was written with the help of an
+auxiliary function, `delayed_tree_to_head`. We could also have written it
+directly, as follows:
+
+```
+let rec delayed_tree_to_cascade (dt : 'a delayed_tree) (k : 'a cascade)
+: 'a cascade =
+ match dt with
+ | DTZero ->
+ k
+ | DTOne x ->
+ cons x k
+ | DTTwo (dt1, dt2) ->
+ delayed_tree_to_cascade dt1 (delayed_tree_to_cascade dt2 k)
+ | DTDelay dt ->
+ fun () -> delayed_tree_to_cascade (force dt) k ()
+```
+
+In this form, the only function that is ever applied to a delayed tree is
+`delayed_tree_to_cascade`. Therefore, wherever we construct a delayed tree
+`t`, we could instead directly build a closure whose behavior is equivalent to
+`delayed_tree_to_cascade t`. This is *refunctionalization*.
+
+The data structure of delayed trees seems to disappears.
+The type `'a delayed_tree` can be defined as a synonym
+for a `'a cascade -> 'a cascade`. I usually refer to
+this type as `'a producer`: it is the type of a function
+that concatenates elements in front of the cascade that it
+receives as an argument.
+
+```
+type 'a producer =
+ 'a cascade -> 'a cascade
+
+type 'a delayed_tree =
+ 'a producer
+```
+
+The four data constructors are defined as follows:
+
+```
+let _DTZero k =
+ k
+
+let _DTOne x k =
+ cons x k
+
+let _DTTwo dt1 dt2 k =
+ dt1 (dt2 k)
+
+let _DTDelay dt k =
+ fun () -> force dt k ()
+```
+
+The reader can check that the types of these data constructors are the
+same as in the previous version of the code. For instance, `_DTDelay`
+has type `(unit -> 'a delayed_tree) -> 'a delayed_tree`.
+
+The root function `delayed_tree_to_cascade` (without a continuation argument)
+is defined as follows:
+
+```
+let delayed_tree_to_cascade (dt : 'a delayed_tree) : 'a cascade =
+ dt nil
+```
+
+The delayed tree monoid uses the new versions of the four data constructors:
+
+```
+class ['self] delayed_tree_monoid = object (_ : 'self)
+
+ method zero =
+ _DTZero
+
+ method plus =
+ _DTTwo
+
+ method visit_delay: 'env 'a .
+ ('env -> 'a -> 'b delayed_tree) ->
+ 'env -> 'a delay -> 'b delayed_tree
+ = fun visit_'a env x ->
+ _DTDelay (fun () -> visit_'a env x)
+
+end
+
+let yield _env x =
+ _DTOne x
+```
+
+The four functions `_DTZero`, `_DTOne`, `_DTTwo`, and `_DTDelay` could be
+inlined, if desired, so as to make the above code seem even more concise.
+
+The rest of the code is unchanged.
+
+## Acknowledgements
+
+KC Sivaramakrishnan asked whether a visitor can be used to construct an
+iterator. Gabriel Scherer pointed out that the delayed tree data structure can
+be hidden by refunctionalization.
diff --git a/doc/listings-ocaml.tex b/doc/listings-ocaml.tex
new file mode 100644
index 0000000..4ab8be0
--- /dev/null
+++ b/doc/listings-ocaml.tex
@@ -0,0 +1,24 @@
+% Configuring listings for OCaml.
+
+% Comments in blue.
+\newcommand{\ocamlcommentstyle}{\color{blue}}
+
+\lstdefinelanguage{ocaml}[Objective]{Caml}{
+ % Fix errors in the default definition of ocaml.
+ deletekeywords={closed,ref},
+ morekeywords={initializer},
+ % General settings.
+ flexiblecolumns=false,
+ showstringspaces=false,
+ framesep=5pt,
+ commentstyle=\ocamlcommentstyle,
+ % By default, we use a small font.
+ basicstyle=\tt\small,
+ numberstyle=\footnotesize,
+ % LaTeX escape.
+ escapeinside={$}{$},
+}
+
+% An abbreviation for \lstinline, with a normal font size.
+% To be used in the text of the paper.
+\def\oc{\lstinline[language=ocaml,basicstyle=\tt,flexiblecolumns=true]}
diff --git a/doc/local.bib b/doc/local.bib
new file mode 100644
index 0000000..9d71c5b
--- /dev/null
+++ b/doc/local.bib
@@ -0,0 +1,23 @@
+@Misc{ocaml7465,
+ author = {Fran{\c c}ois Pottier},
+ title = {OCaml issue 7465},
+ month = jan,
+ year = 2017,
+ URL = "https://caml.inria.fr/mantis/view.php?id=7465",
+}
+
+@Misc{milewski-13,
+ author = {Bartosz Milewski},
+ title = {Understanding {$F$-algebras}},
+ month = oct,
+ year = 2013,
+ URL = {https://www.schoolofhaskell.com/user/bartosz/understanding-algebras}
+}
+
+@Misc{iterators,
+ author = {Fran{\c c}ois Pottier},
+ title = {From visitors to iterators},
+ month = mar,
+ year = 2017,
+ URL = {http://gallium.inria.fr/blog/from-visitors-to-iterators/},
+}
diff --git a/doc/macros.tex b/doc/macros.tex
new file mode 100644
index 0000000..1b698b8
--- /dev/null
+++ b/doc/macros.tex
@@ -0,0 +1,126 @@
+% ------------------------------------------------------------------------------
+% Including a source code file foo.ml:
+% \orig{foo}
+
+\mdfsetup{%
+ linewidth=0pt,%
+ skipabove=\baselineskip,%
+ skipbelow=.4\baselineskip,%
+ innertopmargin=0pt,%
+ innerbottommargin=0pt,%
+}
+
+\newenvironment{origenv}{%
+ \begin{mdframed}[backgroundcolor=gray!10]%
+}{%
+ \end{mdframed}%
+}
+
+\newcommand{\orig}[1]{%
+\begin{origenv}
+\lstinputlisting{#1.ml}
+\end{origenv}
+}
+
+\newcommand{\origfirstline}[2]{%
+\begin{origenv}
+\lstinputlisting[firstline=#2]{#1.ml}
+\end{origenv}
+}
+
+%% \newcommand{\codefollowupgeneral}[1]{%
+%% \begin{center}
+%% (This code fragment follows up on #1.)
+%% \end{center}
+%% \vspace{-\baselineskip}
+%% }
+
+\newcommand{\codefollowupgeneral}[1]{%
+\marginnote{\footnotesize This follows #1.}[5mm]%
+}
+
+\newcommand{\codefollowup}[1]{%
+ \codefollowupgeneral{\fref{fig:#1}}%
+}
+
+% ------------------------------------------------------------------------------
+% Including the corresponding auto-generated code:
+% \processed{foo}
+
+\newenvironment{processedenv}{%
+ \begin{mdframed}[backgroundcolor=yellow!40]%
+}{%
+ \end{mdframed}%
+}
+
+\newcommand{\processed}[1]{%
+\begin{processedenv}
+\lstinputlisting{#1.processed.ml}
+\end{processedenv}
+}
+
+% ------------------------------------------------------------------------------
+% Various macros.
+
+\newcommand{\fref}[1]{Figure~\ref{#1}}
+\newcommand{\sref}[1]{\S\ref{#1}}
+\newcommand{\email}[1]{\href{mailto:#1}{\texttt{#1}}}
+
+% ------------------------------------------------------------------------------
+% Abbreviations.
+
+\newcommand{\merlin}{\href{https://github.com/ocaml/merlin}{Merlin}\xspace}
+\newcommand{\ocamlbuild}{\href{https://github.com/ocaml/ocamlbuild/blob/master/manual/manual.adoc}{\texttt{ocamlbuild}}\xspace}
+\newcommand{\ocamlfind}{\texttt{ocamlfind}\xspace}
+\newcommand{\opam}{\href{https://opam.ocaml.org/}{\texttt{opam}}\xspace}
+\newcommand{\ppxderiving}{\href{https://github.com/whitequark/ppx_deriving}{\texttt{ppx\_deriving}}\xspace}
+\newcommand{\ppximport}{\href{https://github.com/whitequark/ppx_import}{\texttt{ppx\_import}}\xspace}
+\newcommand{\dune}{\href{https://github.com/ocaml/dune}{Dune}\xspace}
+
+\newcommand{\hashconsRepoURL}{https://github.com/backtracking/ocaml-hashcons}
+\newcommand{\hashcons}{\href{\hashconsRepoURL}{\texttt{hashcons}}\xspace}
+\newcommand{\hashconsRepoFile}[1]{\href{\hashconsRepoURL/blob/master/#1}{\texttt{#1}}}
+
+\newcommand{\repoURL}{https://gitlab.inria.fr/fpottier/visitors}
+\newcommand{\repoFile}[1]{\href{\repoURL/blob/master/#1}{\texttt{#1}}}
+% \newcommand{\srcFile}[1]{\href{\repoURL/blob/master/src/#1}{\texttt{#1}}}
+\newcommand{\runtimeFile}[1]{\href{\repoURL/blob/master/runtime/#1}{\texttt{#1}}}
+
+\newcommand{\iter}{\texttt{iter}\xspace}
+\newcommand{\map}{\texttt{map}\xspace}
+\newcommand{\mapendo}{\texttt{endo}\xspace}
+\newcommand{\reduce}{\texttt{reduce}\xspace}
+\newcommand{\mapreduce}{\texttt{mapreduce}\xspace}
+\newcommand{\fold}{\texttt{fold}\xspace}
+\newcommand{\itertwo}{\texttt{iter2}\xspace}
+\newcommand{\maptwo}{\texttt{map2}\xspace}
+\newcommand{\reducetwo}{\texttt{reduce2}\xspace}
+\newcommand{\mapreducetwo}{\texttt{mapreduce2}\xspace}
+\newcommand{\foldtwo}{\texttt{fold2}\xspace}
+\newcommand{\unit}{\texttt{unit}\xspace}
+\newcommand{\visitors}{\texttt{visitors}\xspace}
+\newcommand{\derivingvisitors}{\texttt{[@@deriving visitors \{ ...\ \}]}\xspace}
+\newcommand{\runtime}[1]{\oc|VisitorsRuntime.#1|}
+
+\newcommand{\tyconvisitor}[1]{\texttt{visit\_#1}}
+\newcommand{\dataconvisitor}[1]{\texttt{visit\_#1}}
+\newcommand{\tyconfail}[1]{\texttt{fail\_#1}}
+\newcommand{\dataconascendingmethod}[1]{\texttt{build\_#1}}
+\newcommand{\tyconascendingmethod}[1]{\texttt{build\_#1}}
+
+\newcommand{\refconvention}{\sref{sec:intro:parameterized:poly}, \sref{sec:intro:nonlocal},
+\fref{fig:convention}}
+
+% Options.
+\newcommand{\ancestors}{\texttt{ancestors}\xspace}
+\newcommand{\concrete}{\texttt{concrete}\xspace}
+\newcommand{\irregular}{\texttt{irregular}\xspace}
+\newcommand{\name}{\texttt{name}\xspace}
+\newcommand{\public}{\texttt{public}\xspace}
+\newcommand{\variety}{\texttt{variety}\xspace}
+\newcommand{\data}{\texttt{data}\xspace}
+\newcommand{\nude}{\texttt{nude}\xspace}
+\newcommand{\polymorphic}{\texttt{polymorphic}\xspace}
+\newcommand{\visitprefix}{\texttt{visit\_prefix}\xspace}
+\newcommand{\buildprefix}{\texttt{build\_prefix}\xspace}
+\newcommand{\failprefix}{\texttt{fail\_prefix}\xspace}
diff --git a/doc/manual.pdf b/doc/manual.pdf
new file mode 100644
index 0000000..26c55d7
--- /dev/null
+++ b/doc/manual.pdf
Binary files differ
diff --git a/doc/manual.tex b/doc/manual.tex
new file mode 100644
index 0000000..60b4e53
--- /dev/null
+++ b/doc/manual.tex
@@ -0,0 +1,2410 @@
+\documentclass[11pt,a4paper,twoside]{article}
+\usepackage[left=25mm,right=25mm,top=25mm,bottom=25mm,marginparwidth=50pt]{geometry}
+\setlength\abovecaptionskip{0pt} % Reduce space above figure captions.
+\usepackage{lmodern} % This gives us a bold monospace font.
+\renewcommand{\rmdefault}{ptm} % Times.
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{enumitem}
+\usepackage[bookmarks=true,bookmarksopen=true,colorlinks=true,%
+ linkcolor=blue,citecolor=blue,urlcolor=blue]{hyperref}
+\usepackage{marginnote}
+\usepackage{listings}
+\input{listings-ocaml}
+\lstset{language=ocaml}
+\usepackage{moreverb}
+\usepackage{tabularx}
+\usepackage{xcolor}
+\usepackage{mdframed}
+\usepackage{xspace}
+\input{macros}
+% Style.
+\renewcommand{\emph}[1]{\textbf{#1}}
+\input{version}
+
+% ------------------------------------------------------------------------------
+% Headings.
+
+\title{Visitors\\\normalsize version \visitorsversion}
+\date{}
+\begin{document}
+\author{François Pottier\\ Inria Paris\\ \email{francois.pottier@inria.fr}}
+\maketitle
+
+% ------------------------------------------------------------------------------
+
+\clearpage
+\tableofcontents
+\clearpage
+
+% ------------------------------------------------------------------------------
+
+\begin{flushright}
+ Les visites font toujours plaisir, si ce n'est en arrivant, du moins en
+ partant. \\ --- \textit{Jean de La Bruyère}
+\end{flushright}
+
+\vspace{8mm}
+
+% ------------------------------------------------------------------------------
+% ------------------------------------------------------------------------------
+
+\section{Introduction}
+\label{sec:intro}
+
+% ------------------------------------------------------------------------------
+
+\subsection{What is a visitor?}
+
+A visitor class for a data structure is a class whose methods implement a
+traversal of this data structure. By default, the visitor methods do not have
+interesting behavior: they just cause control to go down into the data
+structure and come back up, without performing any actual computation.
+Nevertheless, by defining subclasses where one method or a few methods are
+overridden, nontrivial behavior can be obtained. Therefore, visitors allow
+many operations on this data structure to be defined with little effort.
+
+Visitor classes come in several varieties. An \iter visitor traverses a data
+structure and returns no result. It can nevertheless have side effects,
+including updating a piece of mutable state, raising an exception, and
+performing input/output. A \map visitor traverses a data structure and returns
+another data structure: typically, a copy of its argument that has been
+transformed in some way. An \mapendo visitor is a variant of a \map visitor
+that preserves physical sharing when possible. A \reduce visitor traverses a
+data structure and returns a value that somehow summarizes it: computing the
+size of a data structure is a typical example. A \mapreduce visitor performs
+the tasks of a \map visitor and a \reduce visitor at the same time,
+possibly allowing symbiosis between them. All of these can be viewed as
+special cases of the \fold visitor, which performs a bottom-up computation
+over a data structure. The class \fold is equipped with virtual methods
+% (the ``\tyconascendingmethod{}'' methods)
+that can be overridden (in a subclass) so as to specify what computation is
+desired.
+
+Visitors also come in several arities. The visitors mentioned above have arity
+one: they traverse one data structure. However, it is sometimes necessary to
+simultaneously traverse two data structures of identical shape. For this
+purpose, there are visitors of arity two: here, they are known as \itertwo,
+\maptwo, \reducetwo, \mapreducetwo, and \foldtwo visitors.
+
+% \mapendotwo does not exist.
+
+% ------------------------------------------------------------------------------
+
+\subsection{What does this package offer?}
+
+Visitors have extremely regular structure. As a result, whereas implementing
+them by hand is boring and error-prone, generating them automatically is often
+possible. The \visitors package extends the syntax of OCaml%
+%
+\footnote{Technically, \visitors is a plugin for \ppxderiving, which itself is
+ a preprocessor extension for the OCaml compiler.}
+%
+so as to make it easy for the programmer to request the automatic generation
+of visitor classes. Visitor classes for many forms of user-defined data types
+can be generated and, if necessary, combined (via multiple inheritance) with
+hand-written visitor classes, making the framework quite powerful.
+
+% ------------------------------------------------------------------------------
+% ------------------------------------------------------------------------------
+
+\section{Walkthrough}
+
+% ------------------------------------------------------------------------------
+
+\subsection{Setup}
+\label{sec:intro:setup}
+
+\enlargethispage{\baselineskip}
+
+In order to install the \visitors package, an \opam user should issue the
+following commands:
+\begin{lstlisting}[keywords={}]
+ opam update
+ opam install visitors
+\end{lstlisting}
+To use the package, an \ocamlbuild user should add the
+following line in her project's \texttt{\_tags} file:
+\begin{lstlisting}[keywords={}]
+ true: package(visitors.ppx)
+\end{lstlisting}
+while a user of \dune should add the following incantation
+to her project's \texttt{dune} file,
+inside a \texttt{library} or \texttt{executable} stanza:
+\begin{lstlisting}[keywords={}]
+ (preprocess (pps visitors.ppx))
+\end{lstlisting}
+%% A user of \merlin should add the following lines in her project's
+%% \texttt{.merlin} file:
+%% \begin{lstlisting}[keywords={}]
+%% PKG visitors.ppx
+%% \end{lstlisting}
+To use the \visitors package in OCaml's interactive ``toplevel'' environment,
+launch \texttt{ocaml} and type the following commands:
+\begin{lstlisting}
+ #use "topfind";;
+ #require "visitors.ppx";;
+\end{lstlisting}
+
+% ------------------------------------------------------------------------------
+
+\begin{figure}[t]
+% In an OCaml source file, a type definition can be annotated with
+% \derivingvisitors:
+\orig{expr00}
+% This causes the following code to be (invisibly) generated:
+\vspace{-\baselineskip}
+\processed{expr00}
+\caption{A visitor of the \iter variety}
+\label{fig:expr00}
+\end{figure}
+
+\subsection{Defining an \iter visitor}
+\label{sec:intro:iter:def}
+
+Suppose we need to manipulate arithmetic expressions built out of integer
+literals and binary additions. The abstract syntax of these expressions can be
+described by an algebraic data type \oc|expr|, shown in the first part of
+\fref{fig:expr00}.
+%
+By annotating this type definition with \derivingvisitors, we request the
+automated generation of a visitor for expressions. The annotation
+\derivingvisitors must carry at least one parameter, \variety, which indicates
+what variety of visitor is desired.
+
+The code of the visitor class, which is automatically generated and in normal
+use remains invisible, is shown in the second part of \fref{fig:expr00}. The
+name of this class is by default the value of the \variety parameter. It can
+be changed, if desired, by explicitly supplying a \name parameter.
+
+A visitor takes the form of an OCaml class, whose methods are named after the
+types and data constructors that appear in the type definition. In
+\fref{fig:expr00}, for instance, the method \tyconvisitor{expr} is named after
+the type \oc|expr|, while the methods \dataconvisitor{EConst} and
+\dataconvisitor{EAdd} are named after the data constructors \oc|EConst| and
+\oc|EAdd|.
+
+Different varieties of visitors differ in the computation that is performed
+``on the way up'', after the recursive calls have finished, therefore differ
+in the return types of the visitor methods. \iter is the simplest variety. An
+\iter visitor performs no computation on the way up, so its methods have
+return type \oc|unit|.
+
+In an \iter visitor, the generated visitor methods do nothing. In
+\fref{fig:expr00}, for instance, the method \tyconvisitor{expr} inspects its
+argument \oc|this| and recursively invokes either \dataconvisitor{EConst} or
+\dataconvisitor{EAdd}, as appropriate. The method \dataconvisitor{EConst} does
+nothing.\footnote{More precisely, it calls the method \tyconvisitor{int},
+ which is inherited from the class \runtime{iter}, and does
+ nothing. This call to \tyconvisitor{int} can be avoided, if desired, by using
+ \oc|(int[@opaque])| instead of \oc|int|; see \sref{sec:opaque}.} The method
+\dataconvisitor{EAdd} performs two recursive calls to \tyconvisitor{expr},
+which does nothing, so \dataconvisitor{EAdd} itself does nothing.
+
+Every method is parameterized with an environment \oc|env|, which is carried
+down into every recursive call and is otherwise unused. The type of this
+environment is undetermined: it is up to the (user-defined) subclasses of the
+visitor class to decide what the type of \oc|env| should be and (possibly)
+where and how this environment should be enriched.
+
+% One could note that the visitor class is parameterized over 'self,
+% but it is perhaps a bit early for such a remark.
+
+The fields of a data constructor or record are traversed left to right, in the
+order they are declared. In a list-like data structure, the field that holds a
+pointer to the list tail should be declared last, so as to ensure that the
+traversal requires constant stack space.
+
+% ------------------------------------------------------------------------------
+
+\begin{figure}[t]
+\codefollowup{expr00}
+\origfirstline{expr04}{3}
+\caption{Counting the number of addition nodes in an expression}
+\label{fig:expr04}
+\end{figure}
+
+\subsection{Using an \iter visitor}
+\label{sec:intro:iter:usage}
+
+Naturally, traversing a data structure without actually computing anything is
+not a very sensible thing to do. Things become interesting when at least one
+visitor method is overridden so as to give rise to nontrivial behavior.
+Suppose, for instance, that we wish to count the number of addition nodes in
+an expression. This can be done as shown in \fref{fig:expr04}. We create an
+object~\oc|v| that is both a counter (that is, an object equipped with a
+mutable field~\oc|count|) and a visitor, and we override its method
+\dataconvisitor{EAdd} so that the counter is incremented every time this
+method is invoked. There remains to run the visitor, by invoking its
+\tyconvisitor{expr} method, and to return the final value of the counter. The
+environment, in this example, is unused; we let it have type \unit.
+
+This may seem a rather complicated way of counting the addition nodes in an
+expression. Of course, one could give a direct recursive definition of the
+function \oc|count|, in a few lines of code, without using a visitor at all.
+The point of employing a visitor, as done in Figures~\ref{fig:expr00}
+and~\ref{fig:expr04}, is that no changes to the code are required when the
+type of expressions is extended with new cases.
+
+% ------------------------------------------------------------------------------
+
+\subsection{What is the type of a visitor?}
+\label{sec:intro:type}
+
+In this document, most of the time, we prefer to show the code of a visitor
+class and omit its type. There are two reasons for this. First, this type is
+often verbose, as the class has many methods, and complex, as several type
+variables are often involved. Second, although we can explain the type of a
+generated visitor on a case-by-case basis, we cannot in the general case
+predict the type of a generated visitor.
+The reason is, the type of a generated visitor depends upon the
+types of the classes that are inherited via the \ancestors parameter
+(\sref{sec:ancestors}). Because a \texttt{ppx} syntax extension transforms
+untyped syntax trees to untyped syntax trees, the \visitors syntax extension
+does not have access to this information.
+
+For this reason, the \visitors syntax extension cannot generate any type
+declarations. Thus, the annotation \derivingvisitors can be used only in an
+\texttt{\%.ml} file, not in an \texttt{\%.mli} file. When it is used in an
+\texttt{\%.ml} file, the corresponding \texttt{\%.mli} file should either be
+omitted altogether or be written by hand.
+
+\input{types}
+
+Nevertheless, the type of the generated code can be inspected, if desired, by
+requesting the OCaml compiler to infer and display it. For this purpose, one
+can use a command of the following form:
+\begin{quote}
+\verb|ocamlbuild -use-ocamlfind <other-flags> %.inferred.mli|
+\end{quote}
+% TEMPORARY explain how to it using Dune
+
+\fref{fig:inferred} shows the type that is inferred via such a command for the
+\iter visitor of \fref{fig:expr00}. This type is rather verbose, for two
+reasons. First, an explicit type equation, introduced by the \oc|constraint|
+keyword, relates the type parameter \oc|'self| with an OCaml object type that
+lists the public methods with their types. Second, the class \iter has many more
+methods than one might think. This is because it inherits a large number of
+private methods from the class \runtime{iter}. In the present case, all of
+these methods except \tyconvisitor{int} are in fact unused.
+
+Fortunately, this complicated type can be manually simplified. This is done in
+\fref{fig:simplified}. Two main simplifications have been performed. First, we
+have omitted all private methods. Indeed, the most important property of
+private methods in OCaml is precisely the fact that it is permitted to hide
+their existence. Second, we have omitted the type constraint that bears on
+the type variable \oc|'self|, as it is in fact redundant: it is implicit in OCaml
+that the type of ``self'' must be an object type that lists the public methods.
+The bizarre-looking ``\oc|'monomorphic.|'' annotations indicate that the methods have
+monomorphic types. (This notational trick is explained in \sref{sec:oo:monomorphic}.)
+This means that the type variable~\oc|'env| is not quantified at the level of each
+method\footnote{That would be undesirable, as it would force each method to
+treat the environment as an argument of unknown type!}, but at the level of the class.
+This means that the three methods must agree on the type of the environment, and
+that this type is presently undetermined, but can be determined in a subclass.
+
+The class type shown in \fref{fig:simplified} cannot be further simplified.
+The methods \tyconvisitor{EConst} and \tyconvisitor{EAdd} cannot be hidden, as
+they are public. That said, if one wished to hide them, one could add the parameter %
+\oc|public = ["visit_expr"]| to the annotation \derivingvisitors in \fref{fig:expr00}.
+These two methods would then be declared private in the generated code,
+so it would be permitted to hide their existence.
+
+Although we have claimed earlier that one cannot in the general case predict
+the type of a generated visitor method, or even predict whether a generated
+method will be well-typed, it is possible to define a convention which in many
+cases can be adhered to. This convention is presented later on
+(\refconvention).
+
+% ------------------------------------------------------------------------------
+
+\begin{figure}[t]
+\orig{expr01}
+\vspace{-\baselineskip}
+\processed{expr01}
+\caption{A visitor of the \map variety}
+\label{fig:expr01}
+\end{figure}
+
+\subsection{\map visitors}
+\label{sec:intro:map}
+
+An \iter visitor returns no result. Although, as illustrated previously
+(\sref{sec:intro:iter:usage}), it can use private mutable state to accumulate
+information, there are applications for which such a visitor is not suitable.
+One class of such applications is tree transformations. To transform an
+expression into an expression, one should use a visitor of another variety,
+namely \map.
+
+A \map visitor is shown in \fref{fig:expr01}. In comparison with the \iter
+visitor of \fref{fig:expr00}, the generated code is identical, except that,
+instead of returning the unit value \oc|()|, the method
+\dataconvisitor{EConst} reconstructs an \oc|EConst| expression, while the
+method \dataconvisitor{EAdd} reconstructs an \oc|EAdd| expression.
+
+A \map visitor behaves (by default) as an identity function: it constructs a
+copy of the data structure that it visits. If the data structure is immutable,
+this is rather pointless: in order to obtain nontrivial behavior, at least one
+method should be overridden. If the data structure is mutable, though, even
+the default behavior is potentially of interest: it constructs a deep copy of
+its argument.
+
+% ------------------------------------------------------------------------------
+
+\begin{figure}[p]
+\orig{expr00endo}
+\vspace{-\baselineskip}
+\processed{expr00endo}
+\caption{A visitor of the \mapendo variety}
+\label{fig:expr00endo}
+\end{figure}
+
+\subsection{\mapendo visitors}
+\label{sec:intro:endo}
+
+\mapendo visitors are a slight variation of \map visitors. Whereas a \map
+visitor systematically allocates a copy of the memory block that it receives
+as an argument, an \mapendo visitor (\fref{fig:expr00endo}) first tests if the
+newly allocated block would have exactly the same contents as the original
+block, and if so, re-uses the original block instead.
+% Didier attributes this idea to Gérard Huet,
+% at least in the case of a dictionary insertion operation,
+% where Gérard would raise an exception so as to go back to
+% the toplevel and avoid re-allocating a path.
+%
+This trick allows saving memory: for instance, when a performing a
+substitution operation on a term, the subterms that are unaffected
+by the substitution are not copied.
+
+One potential disadvantage of \mapendo visitors, in comparison with \map
+visitors, is that these runtime tests have a runtime cost. A more serious
+disadvantage is that \mapendo visitors have less general types: in an \mapendo
+visitor, the argument type and return type of every method must coincide,
+whence the name ``\mapendo''.
+%
+(An endomorphism is a function of a set into itself.)
+%
+\map visitors are not subject to this restriction: for an illustration, see
+\sref{sec:advanced:hashconsed} and \fref{fig:expr14}.
+
+In principle, \mapendo visitors should be created only for immutable data
+structures. Although the tool can produce an \mapendo visitor for a mutable
+data structure, this is discouraged, as it may lead to unexpected behavior.
+
+% ------------------------------------------------------------------------------
+
+\begin{figure}[p]
+\orig{expr15}
+\vspace{-\baselineskip}
+\processed{expr15}
+\caption{A visitor of the \reduce variety}
+\label{fig:expr15}
+\end{figure}
+
+\begin{figure}[t]
+\codefollowup{expr15}
+\origfirstline{expr15b}{3}
+\caption{Computing the size of an expression using a \reduce visitor}
+\label{fig:reduce}
+\end{figure}
+
+\subsection{\reduce visitors}
+\label{sec:intro:reduce}
+
+Whereas an \iter visitor returns no result and a \map visitor returns a data
+structure, a \reduce visitor returns a ``summary'' of a data structure, so to
+speak. The summary of a term is computed by combining the summaries of its
+subterms. This requires summaries to inhabit a monoid, that is, a type
+equipped with a binary operation \oc|plus| and its neutral element \oc|zero|.
+
+\fref{fig:expr15} shows a \reduce visitor for arithmetic expressions. In
+\dataconvisitor{EAdd}, the summaries produced by the two recursive calls are
+combined using a call to \oc|self#plus|. In \dataconvisitor{EConst}, there are
+no recursive calls, so there is nothing to combine: the result is
+\oc|self#zero|.
+
+The virtual methods \oc|zero| and \oc|plus| are declared in the class
+\runtime{reduce}, which is automatically inherited. The type of the
+monoid elements, at this point, is undetermined: it is up to the
+(user-defined) subclasses of the class \reduce to decide what this type should
+be and what the monoid operations should be.
+
+As an example application, \fref{fig:reduce} shows how to compute the size of
+an expression using a \reduce visitor. We inherit the class \reduce. We also
+inherit the class \runtime{addition_monoid}, which defines the
+methods \oc|zero| and \oc|plus| as the integer \oc|0| and integer addition,
+respectively. There remains to override the method \tyconvisitor{expr} so as
+to indicate that every node contributes 1 to the size of an expression.
+
+Incidentally, this code is written in such a manner that a single visitor
+object is created initially and serves in every call to the function
+\oc|size|. This style can be used when the visitor object is immutable and
+when the function that one wishes to define is monomorphic. When it cannot be
+used, one begins with \oc|let size (e : expr) : int = ...| and ends with %
+\oc|v # visit_expr () e|. That style causes a new visitor object to be created
+every time \oc|size| is called.
+% On pourrait ré-utiliser le même objet à chaque fois en remettant son champ à
+% zéro... Mais ce serait sale et pas ré-entrant.
+
+The size of an expression can also be computed using an \iter visitor equipped
+with mutable state, in the style of \fref{fig:expr04}. It is mostly a matter
+of style whether such a computation should be performed using \iter or
+\reduce.
+% TEMPORARY comparer les perfs, pour voir
+
+An \iter visitor is in fact a special case of a \reduce visitor, instantiated
+with the \oc|unit| monoid. Thus, in principle, one could forget \iter and
+always work with \reduce. Nevertheless, it is preferable to work with \iter
+when it is applicable, for reasons of clarity and efficiency.
+% e.g. an \iter visitor can traverse a list-like data structure in constant
+% stack space; a \reduce visitor cannot, because it does not have an accu.
+
+% One might wonder whether a reduce visitor should have an accumulator...
+% ...but then it would be left-to-right-from-the-start, instead of bottom-up.
+% I am not sure what we want. Maybe we do not need reduce visitors at all!
+
+% ------------------------------------------------------------------------------
+
+\begin{figure}[p]
+\orig{expr_info_mapreduce}
+\vspace{-\baselineskip}
+\processed{expr_info_mapreduce}
+\caption{A visitor of the \mapreduce variety}
+\label{fig:mapreduce}
+\end{figure}
+
+\begin{figure}[p]
+\codefollowup{mapreduce}
+\origfirstline{expr_info_mapreduce_use}{3}
+\caption{Decorating every subexpression with its size}
+\label{fig:expr_info_mapreduce_use}
+\end{figure}
+
+\subsection{\mapreduce visitors}
+\label{sec:intro:mapreduce}
+
+A \mapreduce visitor performs the tasks of a \map visitor and a \reduce
+visitor at once. An example appears in \fref{fig:mapreduce}. Every visitor
+method returns a pair of a transformed term and a summary. In other words,
+it returns a pair of the results that would be returned by a \map visitor
+method and by a \reduce visitor method.
+
+Like a \reduce visitor, a \mapreduce visitor performs a bottom-up computation.
+Like a \map visitor, it constructs a new tree. By default, these two tasks are
+independent of one another. However, by overriding one or more methods, it is
+easy to establish a connection between them: typically, one wishes to exploit
+the information that was computed about a subtree in the construction of the
+corresponding new subtree. As an example, \fref{fig:expr_info_mapreduce_use}
+shows how to transform an arithmetic expression into an arithmetic expression
+where every subexpression is annotated with its size. (This example uses a
+parameterized type of decorated expressions, which is explained in
+\sref{sec:intro:parameterized:mono}. We suggest reading the explanations there
+first.) The transformation is carried out in one pass and in linear time. As
+in \fref{fig:reduce}, we use the addition monoid to compute integer sizes.
+This time, however, the visitor methods return not just a size, but a pair of
+a new expression and a size. The method \tyconvisitor{expr} is overridden so
+as to store the size of the subexpression, \oc|size|, in the \oc|info| field
+of the new expression. Because the overridden method \tyconvisitor{expr} does
+not call \tyconvisitor{'info}, the latter method is never called: we provide a
+dummy definition of it.
+
+Other example applications of \mapreduce visitors include:
+\begin{itemize}[nosep]
+\item decorating every subterm of a $\lambda$-term with the set of its free
+ variables;
+\item decorating every internal node of abstract syntax tree with a region in
+ the source code (assuming that every leaf carries such a region already).
+\end{itemize}
+
+% ------------------------------------------------------------------------------
+
+\begin{figure}[p]
+\orig{expr00fold}
+\vspace{-\baselineskip}
+\processed{expr00fold}
+\caption{A visitor of the \fold variety}
+\label{fig:expr00fold}
+\end{figure}
+
+\begin{figure}[p]
+\orig{fold}
+\caption{Converting towards unrelated types using a \fold visitor}
+\label{fig:fold}
+\end{figure}
+
+\subsection{\fold visitors}
+\label{sec:intro:fold}
+
+The varities of visitors presented up to this point differ in the computation
+that they perform on the way up, after the recursive calls. As we have seen,
+\iter visitors perform no computation at all; \map and \mapendo visitors
+reconstruct a term; \reduce visitors perform a series of monoid operations.
+Each variety follows a baked-in pattern, which has been programmed ahead of
+time, and cannot be changed. What if a different form of computation, which
+has not been envisioned by the author of the \visitors syntax extension, is
+needed?
+
+This is where \fold visitors come in. A \fold visitor declares virtual methods
+that are called on the way up and can be overridden by the user (in a
+subclass) so as to implement the desired computation. \fref{fig:expr00fold}
+shows a \fold visitor. Two virtual methods, \dataconascendingmethod{EConst}
+and \dataconascendingmethod{EAdd}, are declared. They are invoked by
+\tyconvisitor{EConst} and \tyconvisitor{EAdd}, respectively.
+
+In a \fold visitor, the return type of the visitor methods is not fixed ahead
+of time. It is up to the (user-defined) subclasses of the visitor class to
+decide what this type should be.
+
+As an example application, \fref{fig:fold} shows how a \fold visitor can be
+used to convert the visited data structure to an entirely different format. In
+this example, the type \oc|person| is a record type, whose fields are
+\oc|firstname| and \oc|surname|. The type \oc|crowd| is isomorphic to a list
+of persons, but, for some reason, it is declared as an algebraic data type
+equipped with its own data constructors, \oc|Nobody| and \oc|Someone|. Suppose
+we wish to convert a \oc|crowd| to a list of pairs of strings. We can do so by
+creating a visitor object that inherits the class \fold and provides concrete
+implementations of the methods \tyconascendingmethod{person},
+\dataconascendingmethod{Nobody}, and \dataconascendingmethod{Someone}.
+Our implementation of \tyconascendingmethod{person} simply allocates
+a pair, while our implementations of
+\dataconascendingmethod{Nobody} and \dataconascendingmethod{Someone}
+respectively build an empty list and a nonempty list.
+Thus, the return type of the methods \tyconascendingmethod{person}
+and \tyconvisitor{person} is \oc|string * string|,
+while the return type of the methods \dataconascendingmethod{Nobody},
+\dataconascendingmethod{Someone}, and \dataconvisitor{crowd} is
+\oc|(string * string) list|. In a \fold visitor, not all methods
+need have the same return type!
+
+If we had chosen to return \oc|f ^ s| instead of \oc|(f, s)| in
+\tyconascendingmethod{person}, then a crowd would be converted to
+a \oc|string list|. A \fold visitor offers great flexibility.
+
+All previous varieties of visitors are special cases of \fold visitors. The
+specialized varieties of visitors are more convenient to use, when they can be
+used, because they do not require the user to provide \tyconascendingmethod{}
+methods. Yet, \fold visitors are in principle more versatile.%
+%
+\footnote{This would be true in an untyped setting, but is not quite true in OCaml,
+due to restrictions imposed by OCaml's type discipline (\sref{sec:map_from_fold}).}
+
+% ppx_tools/genlifter is analogous, with a few differences:
+% - it is a command line tool, not as ppx extension;
+% - it has only one return type 'res for all methods;
+% - the visitor methods receive (as extra arguments)
+% the names of the types, data constructors, and record fields
+% that are being visited.
+% - and there are fewer visitor methods, basically one per type,
+% plus one primitive type, plus this#record, this#constr.
+
+% TEMPORARY show how to do a fold in the presence of primitive types, e.g., list
+% writing ancestors = ["VisitorsRuntime.map"] may be necessary
+
+% ------------------------------------------------------------------------------
+
+\begin{figure}[p]
+\orig{expr02}
+\vspace{-\baselineskip}
+\processed{expr02}
+\caption{A visitor of the \itertwo variety}
+\label{fig:expr02}
+\end{figure}
+
+\begin{comment}
+\begin{figure}[p]
+\orig{expr03}
+\vspace{-\baselineskip}
+\processed{expr03}
+\caption{A visitor of the \maptwo variety}
+\label{fig:expr03}
+\end{figure}
+\end{comment}
+
+\subsection{Visitors of arity two}
+\label{sec:intro:aritytwo}
+
+The visitors introduced so far traverse one tree at a time. There are
+situations where one wishes to simultaneously traverse two trees, which one
+expects have the same structure. For this purpose, one can use a visitor of
+arity 2. Every variety except \mapendo is available at arity 2.
+
+As an illustration, \fref{fig:expr02} shows an \itertwo visitor. There, the
+method \tyconvisitor{expr} expects an environment and two expressions. These
+expressions must have identical structure: indeed, if \tyconvisitor{expr}
+finds that they exhibit different tags at the root, say \oc|EConst| versus
+\oc|EAdd|, then it invokes the method \tyconfail{expr}, whose default
+implementation calls the function \runtime{fail}. This function
+throws the exception \runtime{StructuralMismatch}.
+
+In \fref{fig:expr02}, we have added the optional parameter
+%
+\oc|concrete = true|
+%
+to indicate that the generated class should not be virtual. (By default,
+every generated class is declared \oc|virtual|.) We do this because, in
+the illustration that follows, we wish to instantiate this class.
+
+\begin{figure}[p]
+\codefollowup{expr02}
+\origfirstline{expr05}{3}
+\caption{Determining whether two expressions are syntactically equal}
+\label{fig:expr05}
+\end{figure}
+
+\begin{figure}[p]
+\codefollowup{expr02}
+\origfirstline{expr05lexico}{3}
+\caption{Determining which way two expressions are ordered}
+\label{fig:expr05lexico}
+\end{figure}
+
+As an illustration, in \fref{fig:expr05}, we use an \itertwo visitor to write
+a function that tests whether two expressions are syntactically equal. This is
+just a matter of performing a synchronous traversal of the two expressions and
+detecting a \oc|StructuralMismatch| exception: if this exception is raised,
+one must return \oc|false|, otherwise one must return \oc|true|. We rely on
+the fact that the method \tyconvisitor{int}, which is inherited from the class
+\runtime{iter2}, fails when its two integer arguments are
+unequal.
+
+The convenience functions \runtime{wrap} and
+\runtime{wrap2} run a user-supplied function (of arity 1 or 2,
+respectively) within an exception handler and return a Boolean result, which
+is \oc|true| if no exception was raised. Here, we run the function
+%
+\oc|new iter2 # visit_expr ()|, whose type is \oc|expr -> expr -> unit|,
+in the scope of such a handler.
+
+Naturally, to test whether two expressions are syntactically equal, one could
+also use the primitive equality operator \oc|=|. Alternatively, one could
+exploit \ppxderiving and annotate the type definition with
+%
+\oc|[@@deriving eq]|. Visitors offer greater flexibility: for instance, if our
+arithmetic expressions contained variables and binders, we could easily define
+an operation that tests whether two expressions are $\alpha$-equivalent.
+
+As a second illustration, in \fref{fig:expr05lexico}, we use an \itertwo
+visitor to write a lexicographic ordering function for expressions. Again,
+this involves a synchronous traversal of the two expressions. When a mismatch
+is detected, however, one must not raise a \oc|StructuralMismatch| exception:
+instead, one must raise an exception that carries one bit of information,
+namely, which of the two expressions is strictly ``smaller'' in the ordering.
+The exception \oc|Different| is introduced for this purpose; it carries an
+integer return code, which by convention is either -1 or +1. Two visitor methods
+must be overridden, namely \tyconvisitor{int}, which is in charge of detecting
+a mismatch between two integer constants, and \tyconfail{expr}, which is invoked
+when a mismatch between (the head constructors of) two expressions is detected.
+The auxiliary function \oc|tag| returns an integer code for the head constructor
+of an expression. It must be hand-written. One could in principle write such a
+function once and for all by using the undocumented operations in OCaml's
+\href{https://caml.inria.fr/pub/docs/manual-ocaml/libref/Obj.html}{\oc|Obj|}
+module, but that is discouraged.
+
+% Il faut au minimum distinguer les constructeurs constants des autres,
+% en utilisant is_int. Il y a peut-être d'autres pièges. De plus, on ne
+% peut pas (je crois?) garantir que l'ordre des constructeurs sera bien
+% celui de la déclaration de types, parce que les constructeurs constants
+% et les autres sont codés indépendamment.
+
+% ------------------------------------------------------------------------------
+
+\begin{figure}[t]
+\orig{expr06}
+\caption{Visitors for a family of types}
+\label{fig:expr06}
+\end{figure}
+
+\subsection{Visitors for a family of types}
+\label{sec:intro:family}
+
+Visitors can be generated not just for one type definition, but for a family
+of type definitions. In \fref{fig:expr06}, we propose a definition of
+arithmetic expressions that involves three algebraic data types, namely
+\oc|unop|, \oc|binop|, and \oc|expr|. We request the generation of two
+visitors, namely an \iter visitor and a \map visitor. This causes the
+generation of just two classes, named \iter and \map, respectively. Each of
+these classes has visitor methods for every type (namely \tyconvisitor{unop},
+\tyconvisitor{binop}, \tyconvisitor{expr}) and for every data constructor
+(namely \dataconvisitor{UnaryMinus}, \dataconvisitor{BinaryMinus}, and so on).
+
+Note that, for the \derivingvisitors annotation to apply to the entire family,
+as opposed to just the type \oc|expr|, the types \oc|unop|, \oc|binop|, and
+\oc|expr| in \fref{fig:expr06} are declared simultaneously: that is, their
+declarations are separated with the keyword \oc|and|.
+
+% ------------------------------------------------------------------------------
+
+\subsection{Visitors for parameterized types}
+\label{sec:intro:parameterized}
+
+% ------------------------------------------------------------------------------
+
+Visitors can be generated for parameterized types, too. However, there are two
+ways in which this can be done. Here is why.
+
+To visit a data type where some type variable~\oc|'a| occurs, one must know
+how to visit a value of type~\oc|'a|.
+%
+% That is not quite true, in reality: perhaps there is no component of
+% type~\oc|'a|, perhaps because \oc|'a| is a phantom type parameter or a GADT index,
+% or perhaps because \oc|'a| occurs only under a type constructor that performs
+% special treatment and does not recursively descend its own components.
+%
+There are two ways in which this information can be provided. One way is to
+assume that there is a \emph{virtual visitor method} \oc|visit_'a| in charge
+of visiting a value of type~\oc|'a|. Another way is to pass a \emph{visitor
+ function} \oc|visit_'a| as an argument to every visitor method.
+
+% J'allais écrire que dans un cadre non typé, ces deux approches ont la
+% même expressivité. Mais c'est faux: seule la seconde approche permet
+% de gérer les types de données non réguliers (qui existent aussi dans
+% un cadre non typé, même s'ils ne sont pas explicitement décrits par
+% une déclaration).
+
+These two approaches differ in their expressive power. The
+virtual-visitor-method approach implies that the visitor methods must have
+monomorphic types: roughly speaking, the type variable~\oc|'a|
+% (or variants of it)
+appears free in the type of every visitor method.
+The visitor-function approach implies that the visitor methods can have
+polymorphic types: roughly speaking, each method independently
+can be polymorphic in \oc|'a|.
+For this reason, we refer to these two approaches as the \emph{monomorphic}
+approach and the \emph{polymorphic} approach, respectively.
+
+The monomorphic approach offers the advantage that the type of every method is
+inferred by OCaml. Indeed, in this mode, the generated code need not contain
+any type annotations. This allows correct, most general (monomorphic) types to
+be obtained even in the case where certain hand-written visitor methods
+(provided via the \ancestors parameter) have unconventional types.
+%
+% The downside of this approach is that it does not allow taking several
+% distinct instances of a parameterized type. In particular, it is restricted
+% to regular algebraic data types (\sref{sec:regularity}).
+
+The polymorphic approach offers the advantage that visitor methods can receive
+polymorphic types. If the type \oc|container| is parameterized with a type
+variable~\oc|'a|, then the method \tyconvisitor{container} can be assigned a
+type that is universally quantified in~\oc|'a|, of the following form:
+%
+\begin{mdframed}[backgroundcolor=green!10]
+\begin{lstlisting}
+method visit_container:
+ 'env 'a .
+ ('env -> 'a -> ...) ->
+ 'env -> 'a container -> ...
+\end{lstlisting}
+\end{mdframed}
+%
+The types of the \tyconvisitor{list} methods, shown later on
+(\sref{sec:intro:nonlocal}, \fref{fig:convention}), follow this pattern.
+%
+Because \tyconvisitor{container} is polymorphic, taking multiple instances of
+the type \oc|container|, such as \oc|apple| \oc|container| and \oc|orange|
+\oc|container|, and attempting to generate visitor methods for these types,
+poses no difficulty. This works even if the definition of \oc|'a container|
+mentions other instances of this type, such as \oc|('a * 'a)| \oc|container|.
+In other words, in the polymorphic approach, irregular algebraic data types
+(\sref{sec:regularity}) are supported.
+
+One downside of the polymorphic approach is that, because polymorphic types
+cannot be inferred by OCaml, the \visitors syntax extension must generate
+polymorphic type annotations. Therefore, it must be able to predict
+the type of every visitor method.
+%
+% Actually, not the full type, but at least the polymorphic skeleton.
+%
+This requires that any visitor methods inherited via \ancestors adhere to a
+certain convention (\refconvention).
+
+In summary, both the monomorphic approach and the polymorphic approach are
+currently supported (\sref{sec:intro:parameterized:mono},
+\sref{sec:intro:parameterized:poly}). The parameter \polymorphic allows
+choosing between them. As a rule of thumb, we suggest setting
+%
+\oc|polymorphic = true|, as this produces visitors that compose better.
+
+% TEMPORARY give an explanation why monomorphic mode can be useful?
+
+% In my ICFP paper, I believe monomorphic mode is necessary to deal with ['bn]
+% and ['env]. Indeed, we cannot expect [visit_abs] to be polymorphic in ['bn]
+% and ['env], as it needs to be told how to [extend] an environment with a
+% bound name.
+
+% Other examples?
+
+% ------------------------------------------------------------------------------
+
+\begin{figure}[p]
+\orig{expr_info}
+\vspace{-\baselineskip}
+\processed{expr_info}
+\caption{A ``monomorphic-method'' visitor for a parameterized type of decorated expressions}
+\label{fig:expr_info}
+\end{figure}
+
+\begin{figure}[p]
+\codefollowup{expr_info}
+\origfirstline{expr_info_use}{3}
+\caption{Working with different types of decorations}
+\label{fig:expr_info_use}
+\end{figure}
+
+\subsubsection{Monomorphic visitor methods for parameterized types}
+\label{sec:intro:parameterized:mono}
+
+We begin with an example of the \emph{monomorphic} mode. This mode can be
+explicitly requested by writing \oc|polymorphic = false| as part of the
+\derivingvisitors annotation. It is the default mode.
+
+In \fref{fig:expr_info}, we define a variant of arithmetic
+expressions where every tree node is decorated with a value of type
+\oc|'info|. We request the generation of a \map visitor, whose code is shown
+in the second part of \fref{fig:expr_info}. The generated code has exactly the
+same structure as in the previous sections. The only new feature is that the
+class \map now has a virtual method, \tyconvisitor{'info}. The general rule
+is, for each type parameter, there is one virtual method, named after it.
+
+The visitor methods are \emph{not} declared polymorphic in a type
+variable~\oc|'info|, or in two type variables \oc|'info1|~and~\oc|'info2|, as
+one might perhaps expect. In fact, they must not be declared polymorphic:
+indeed, the user who implements \tyconvisitor{'info} in a subclass of \map may
+wish to provide an implementation that expects and/or produces specific types
+of information.
+
+As a result, a visitor \emph{object} is monomorphic: its method
+\tyconvisitor{'info} must have type \oc|info1 ->| \oc|info2| for certain
+specific types \oc|info1| and \oc|info2|. Fortunately, because it is
+parameterized over \oc|'self|,\footnote{We explain in \sref{sec:oo:self} why
+ all visitor classes are parameterized over \oc|'self|.} the visitor
+\emph{class} is polymorphic: two distinct visitor objects can have distinct
+types.
+
+Although every \emph{automatically generated} method
+is monomorphic, a visitor class can nevertheless \emph{inherit} polymorphic
+methods from a parent class, whose name is specified via the \ancestors parameter
+(\sref{sec:ancestors}). For instance, the \tyconvisitor{list} methods provided by
+the classes \runtime{iter}, \runtime{map}, and so on, are
+polymorphic in the types of the list elements. (See \sref{sec:intro:nonlocal}
+for more information on the treatment of preexisting types.)
+
+\fref{fig:expr_info_use} presents two example uses of the class \map defined in
+\fref{fig:expr_info}. In the first example, we define a function \oc|strip|, of
+type \oc|'info expr -> unit expr|, which strips off the decorations in an
+arithmetic expression, replacing them with unit values. In the second example,
+we define a function \oc|number|, of type \oc|'info expr -> int expr|, which
+decorates each node in an arithmetic expression with a unique integer number.%
+\footnote{Because the \oc|info| field appears before the \oc|node| field in
+ the definition of the type \oc|expr|, and because fields are visited
+ left-to-right, we get a prefix numbering scheme. By exchanging these fields,
+ we would get postfix numbering.} %
+
+% ------------------------------------------------------------------------------
+
+\subsubsection{Polymorphic visitor methods for parameterized types}
+\label{sec:intro:parameterized:poly}
+
+\begin{figure}[p]
+\orig{expr_info_polymorphic}
+\vspace{-\baselineskip}
+\processed{expr_info_polymorphic}
+\caption{A ``polymorphic-method'' visitor for a parameterized type of decorated expressions}
+\label{fig:expr_info_polymorphic}
+\end{figure}
+
+\begin{figure}[p]
+\codefollowup{expr_info_polymorphic}
+\origfirstline{expr_info_polymorphic_use}{3}
+\caption{Working with different types of decorations}
+\label{fig:expr_info_polymorphic_use}
+\end{figure}
+
+We continue with an example of the \emph{polymorphic} mode. This mode can be
+explicitly requested by writing \oc|polymorphic = true| as part of the
+\derivingvisitors annotation. It is available for all varieties of visitors
+except \fold and \foldtwo. The reason why it seems difficult to come up with
+a satisfactory polymorphic type for \fold visitor methods is explained later
+on (\sref{sec:map_from_fold}).
+
+In \fref{fig:expr_info_polymorphic}, we again have arithmetic expressions
+where every tree node is decorated with a value of type \oc|'info|. We again
+request a \map visitor but, this time, we specify \oc|polymorphic = true|.
+%
+In order to make the generated code shorter, we specify \oc|data = false|
+(\sref{sec:params}), which causes the methods \dataconvisitor{EConst} and
+\dataconvisitor{EAdd} to disappear. (They are inlined at their call sites.)
+
+The generated code is the same as in the previous section,
+% except the methods \dataconvisitor{EConst} and \dataconvisitor{EAdd} have
+% disappeared, as explained above, and
+except that \tyconvisitor{'info} is not a method any more. Instead, it is
+a function, which is passed as an argument to every visitor method.
+
+% Because \tyconvisitor{'info} is a function, as opposed to a virtual method,
+The class \map does not have any virtual methods. It can thus be declared as
+concrete class: to this end, we specify
+%
+\oc|concrete = true| (\sref{sec:params}). Without this indication, it would be
+declared \oc|virtual|.
+
+Because \tyconvisitor{'info} is an argument of every visitor method,
+every visitor method can be declared polymorphic in the type variables~\oc|'env|,
+\oc|'info_0| and \oc|'info_1|,
+where the function \tyconvisitor{'info} has type \oc|'env -> 'info_0 -> 'info_1|.
+%
+The fact that we would like every method to have a polymorphic type cannot
+be inferred by OCaml. For this reason, the generated code contains explicit
+polymorphic type annotations.
+
+\fref{fig:expr_info_polymorphic_use} presents two example uses of the class
+\map defined in \fref{fig:expr_info_polymorphic}. As in
+\fref{fig:expr_info_use}, we define two functions \oc|strip| and \oc|number|.
+A striking feature of this code is that a single visitor object~\oc|v| is now
+allocated, once and for all, and is used in every subsequent call to \oc|strip|
+and \oc|number|. The two \tyconvisitor{'info} functions are also defined once
+and for all.%
+%
+\footnote{Although we have nested these functions inside the definitions of
+ \oc|strip| and \oc|number|, they are closed, so they could be hoisted out to
+ the top level, if desired.}
+
+In the definition of \oc|number|, we choose to store the current count in a
+reference, \oc|count|, and to let \oc|count| play the role of the
+``environment''. Thus, we initially pass \oc|count| to \tyconvisitor{expr},
+and \tyconvisitor{'info} receives \oc|count| as its ``environment'' argument.
+
+%%
+
+The polymorphic type annotations that are automatically generated
+(\fref{fig:expr_info_polymorphic}) follow a certain fixed convention. If the
+user throws in hand-written visitor methods via the \ancestors parameter, then
+those hand-written methods must adhere to the same convention (or the
+generated code would be ill-typed). This convention is illustrated in the next
+section (\sref{sec:intro:nonlocal}) with the example of the
+\tyconvisitor{list} methods.
+
+A type variable is not allowed to occur under an \oc|[@opaque]| annotation
+(\sref{sec:opaque}). Indeed, annotating a type variable~\oc|'a| with
+\oc|[@opaque]| would cause special-purpose visit code to be generated, whose
+type is not as polymorphic as required by the above convention.
+
+%%
+
+% We might wish to document that the type variable names \oc|'s| and \oc|'env|
+% are reserved.
+
+% ------------------------------------------------------------------------------
+
+% At the moment, the following feature is considered experimental and
+% undocumented:
+
+\begin{comment}
+
+\subsubsection{Mixing the monomorphic and polymorphic modes}
+\label{sec:intro:parameterized:fine}
+
+It is possible to mix the monomorphic and polymorphic modes
+(\sref{sec:intro:parameterized:mono}, \sref{sec:intro:parameterized:poly}) in
+a single generated visitor class. Suppose we wish to generate a visitor class
+for the type \oc|('a, 'b) dictionary|. Suppose, for some reason, that we would
+like \tyconvisitor{'a} to be a virtual visitor method and \tyconvisitor{'b} to
+be a visitor function, which is passed as an argument to
+\tyconvisitor{dictionary}. This can be achieved by declaring
+%
+\oc|polymorphic = ["'b"]| as part of the \derivingvisitors annotation.
+
+% The user can control whether the visitor methods are polymorphic in \oc|'env|.
+% This is done by including (or not including) \oc|'env| in the list.
+% (The type variable \oc|'env| is reserved.)
+
+\end{comment}
+
+% ------------------------------------------------------------------------------
+
+\begin{figure}[t]
+\orig{expr11}
+\vspace{-\baselineskip}
+\processed{expr11}
+\caption{Using preexisting (parameterized) types, such as \oc|int| and \oc|list|}
+\label{fig:expr11}
+\end{figure}
+
+\input{convention}
+
+\subsection{Dealing with references to preexisting types}
+\label{sec:intro:nonlocal}
+
+A type definition can contain references to the types that are being defined,
+also known as \emph{local} types. For instance, in \fref{fig:expr00}, the
+definition of \oc|EAdd| contains two references to a local type, namely
+\oc|expr|.
+
+A type definition can also contain references to preexisting types, also
+known as \emph{nonlocal} types. For instance, in \fref{fig:expr00}, the
+definition of \oc|EConst| contains a reference to a nonlocal type, namely
+\oc|int|, which happens to be one of OCaml's primitive types. In
+\fref{fig:expr11}, the definition of \oc|EAdd| contains a reference to a
+parameterized nonlocal type, namely \oc|list|, which happens to be defined in
+OCaml's standard library.
+
+The treatment of local types has been illustrated in the previous sections. In
+short, for every local type, a visitor method is called, and is defined:
+for instance, for the local type \oc|expr|, we define the (concrete) method
+\tyconvisitor{expr}.
+
+The treatment of nonlocal types is the same, except the visitor method is not
+defined, nor declared. That is, it is called, but is neither defined (as a
+concrete method) or declared (as a virtual method). Therefore, its definition
+must be provided by an ancestor class.
+
+For most of OCaml primitive or built-in types, support is provided by the
+module \oc|VisitorsRuntime|. This module contains several classes named
+\oc|iter|, \oc|map|, and so on; each of them supplies methods named
+\tyconvisitor{int}, \tyconvisitor{list}, and so on.%
+%
+\footnote{As an exception to this rule, the classes \runtime{fold}
+ and \runtime{fold2} do not supply any methods, because we do not
+ wish to prematurely fix the types of the visitor methods. Please consult
+ \runtimeFile{VisitorsRuntime.ml} to check which methods exist and what they
+ do.} %
+%
+As is evident in Figures~\ref{fig:expr00}, \ref{fig:expr01}, and so on, the
+generated visitor automatically inherits from the appropriate class in
+\oc|VisitorsRuntime|, so it receives default implementations of the methods
+\tyconvisitor{int}, \tyconvisitor{list}, and so on.
+
+The visitor methods for parameterized data types (\oc|array|, \oc|Lazy.t|,
+\oc|list|, \oc|option|, \oc|ref|, \oc|result|) are polymorphic, so it is not a
+problem if both lists of apples and lists of oranges need to be traversed.
+The types of these methods follow a strict \emph{convention},
+illustrated in \fref{fig:convention} with the example of \tyconvisitor{list}.
+
+The \tyconvisitor{list} methods in the classes \runtime{iter}, \runtime{map},
+and so on, have been hand-written, but could equally well have been generated,
+with \oc|polymorphic = true|: their types would be the same.
+%
+% The code would not be the same. At the moment, we are using List.fold_left
+% instead of a natural fold.
+%
+This illustrates the fact that, with \oc|polymorphic = true|,
+\emph{visitors are compositional}.
+%
+% With \oc|polymorphic = false|, visitors are compositional, too,
+% but only for non-parameterized types.
+%
+That is, if the definition of the type \oc|'b bar| refers to the type \oc|'a foo|,
+then one can \emph{separately} generate a visitor class for \oc|'a foo|
+and generate a visitor class for \oc|'b bar|, which inherits the previous class.
+% There is no need to generate a single visitor class for \oc|'a foo| and
+% \oc|'b bar| at once.
+
+At a primitive type, it is advisable to carefully consider what
+behavior is desired. On the one hand, perhaps the inherited method
+\tyconvisitor{int} need not be invoked in the first place; this behavior can
+be obtained by using \oc|(int[@opaque])| instead of \oc|int|. (See
+\sref{sec:opaque} for details.) This is done, for instance, in
+\fref{fig:expr15}, where one can check that no call to \tyconvisitor{int} is
+generated. On the other hand, when one decides to use an inherited method, one
+should make sure that one understands its behavior. The methods
+\tyconvisitor{array} and \tyconvisitor{ref} in the class
+\runtime{map}, for instance, perform a copy of a mutable memory
+block: one should be aware that such a copy is taking place. If this behavior
+is undesirable, it can be overridden.
+
+It is possible to inherit as many classes as one wishes, beyond those defined
+in \oc|VisitorsRuntime|. This is done via the \ancestors parameter
+(\sref{sec:ancestors}). It is also possible to \emph{not} inherit any methods
+from \oc|VisitorsRuntime|. This is done via the \nude parameter
+(\sref{sec:ancestors}).
+
+% ------------------------------------------------------------------------------
+
+\subsection{Generating visitors for preexisting types}
+\label{sec:import}
+
+Because the \derivingvisitors annotation must be attached to the type
+definition, it may seem as if it is impossible to generate a visitor for a
+type whose definition is out of reach. Suppose, for instance, that the type
+\oc|expr| of arithmetic expressions is defined in a module \oc|Expr|, which,
+for some reason, we cannot modify. Can we generate a visitor for this type?
+
+Fortunately, the answer is positive. The basic trick, documented in the
+\href{https://github.com/whitequark/ppx_deriving/#working-with-existing-types}
+{\texttt{ppx\_deriving} \textsc{readme}},
+consists in defining a new type \oc|expr| of arithmetic expressions and to
+explicitly declare that it is equal to the preexisting type \oc|Expr.expr|,
+as follows.
+
+\orig{expr_redef}
+
+As can be seen above, the new definition of \oc|expr| can be annotated with
+\derivingvisitors, yielding a visitor for the new type \oc|expr|, which by
+definition, is equal to the preexisting type \oc|Expr.expr|. Thus, this
+visitor class be used to traverse expressions of type \oc|Expr.expr|.
+
+This approach works, but requires repeating the definition of the type \oc|expr|.
+This duplication can be eliminated thanks to the \ppximport syntax extension,
+as follows:
+
+\orig{expr_import}
+
+This expands to the code shown previously.
+(To use \ppximport and \visitors simultaneously,
+if you are using \dune,
+include
+\verb+(preprocess (staged_pps ppx_import visitors.ppx))+
+in your \texttt{dune} file.)
+% assuming you are using \ocamlbuild and \ocamlfind, just add the line
+% \texttt{true: package(ppx\_import)} to your \texttt{\_tags} file.)
+%
+As icing on
+the cake, \ppximport allows decorating the type definition, on the fly, with
+new attributes. In the following examples, we replace all occurrences of
+\oc|int| with \oc|int[@opaque]| (\sref{sec:opaque}), so as to ensure that the
+generated visitor does not invoke the method \tyconvisitor{int}:
+
+\orig{expr_import_opaque}
+
+% ------------------------------------------------------------------------------
+% ------------------------------------------------------------------------------
+
+\section{Advanced examples}
+\label{sec:advanced}
+
+% ------------------------------------------------------------------------------
+
+\begin{figure}[p]
+\orig{expr12}
+\vspace{-\baselineskip}
+\processed{expr12}
+\caption{An open type of arithmetic expressions} % and a visitor for it
+\label{fig:expr12}
+\end{figure}
+
+\begin{figure}[p]
+\codefollowup{expr12}
+\origfirstline{expr13}{3}
+\caption{A closed type of arithmetic expressions}
+\label{fig:expr13}
+\end{figure}
+
+\begin{figure}[p]
+\codefollowup{expr12}
+\origfirstline{expr08}{3}
+\caption{A closed type of hash-consed arithmetic expressions}
+\label{fig:expr08}
+\end{figure}
+
+\subsection{Visitors for open and closed data types}
+\label{sec:advanced:openclosed}
+
+The algebraic data types of arithmetic expressions shown in the previous
+section (\sref{sec:intro}) are \emph{closed}. That is, the type \oc|expr|
+is recursive: an expression of type \oc|expr| has subexpressions of type
+\oc|expr|.
+
+It is often desirable, for greater flexibility, to first define an \emph{open}
+type of arithmetic expressions. Such a type, say \oc|oexpr|, is parameterized
+over a type variable~\oc|'expr|. It is not recursive: an expression of type
+\oc|'expr oexpr| has subexpressions of type \oc|'expr|. It is shown in
+\fref{fig:expr12}. Naturally, we may request the generation of visitors for
+the type \oc|oexpr|. In \fref{fig:expr12}, we generate a class of \map
+visitors, which we name \oc|omap|. (This is an example of using an explicit
+\name parameter.) As explained earlier (\sref{sec:intro:parameterized:mono}),
+because the type \oc|oexpr| is parameterized over the type variable
+\oc|'expr|, the visitor class has a virtual method, \tyconvisitor{'expr}.
+%
+In this example, we use the monomorphic mode (\sref{sec:intro:parameterized:mono}),
+but could just as well use the polymorphic mode (\sref{sec:intro:parameterized:poly}):
+this is left as an exercise for the reader.
+
+A closed (recursive) type of expressions, \oc|expr|, can then be defined in
+terms of \oc|expr|. This is done in \fref{fig:expr13}. In type-theoretical
+terms, one would like to define \oc|expr| as the fixed point of the functor
+\oc|oexpr|~\cite{milewski-13}.
+%
+That is, roughly speaking, one would like to define \oc|type expr = expr oexpr|.
+This is not accepted by OCaml, though;%
+%
+\footnote{It would be accepted by OCaml with the command line switch
+ \texttt{-rectypes}, which instructs the typechecker to tolerate
+ equirecursive types. However, this is not a good idea, as it causes
+ the typechecker to suddenly accept many meaningless programs and infer
+ bizarre types for them.}
+%
+we work around this limitation by making \oc|expr| an algebraic data type
+whose single data constructor is named~\oc|E|.%
+%
+\footnote{We mark this algebraic data type \oc|[@@unboxed]|, which
+ % as of OCaml 4.04
+ guarantees that there is no runtime cost associated with the
+ data constructor~\oc|E|. Although \oc|expr| and \oc|expr oexpr| are
+ considered distinct types by the OCaml typechecker, they have the same
+ runtime representation.}
+
+Let us now construct a visitor class for the type \oc|expr|. It is easy to
+do so, by hand, in a few lines of code.%
+%
+% \footnote{We could request the generation of a visitor class via a
+% \oc|[@@deriving]| annotation. However, the type \oc|oexpr| would then be
+% viewed as nonlocal; therefore, in the generated code, the method
+% \tyconvisitor{oexpr} would be applied to \oc|self#visit_expr|, a
+% parameter which it does not expect.}
+%
+% Also, we would have to inherit from \oc|omap|, but that would cause us
+% to inherit twice from \runtime{map}, causing warnings.
+%
+We define a class \oc|map|, a subclass of \oc|omap|, and provide a concrete
+implementation of the virtual method \tyconvisitor{'expr}. In the definition
+of the type \oc|expr|, the type variable \oc|'expr| is instantiated with
+\oc|expr|, so the method \tyconvisitor{'expr} expects an argument of type
+\oc|expr| and must return a result of type \oc|expr|. We deconstruct the
+argument using the pattern \oc|E e|. Therefore, the variable \oc|e| has type
+\oc|expr oexpr| and is a suitable argument to the method \tyconvisitor{oexpr}.
+After this call, we perform the same step in reverse: the result of the call
+has type \oc|expr oexpr|, so we wrap it in an application of the data
+constructor~\oc|E| and obtain a result of type \oc|expr|.
+
+The visitor class \oc|map| can now be used to implement transformations of
+arithmetic expressions, that is, functions of type \oc|expr -> expr|. As an
+example, let us implement a transformation whose effect is to double every
+integer constant in an arithmetic expression. This is done in
+\fref{fig:expr13double}. As expected, it suffices to construct a visitor
+object that inherits \oc|map| and overrides the method
+\dataconvisitor{EConst}.
+
+% ------------------------------------------------------------------------------
+
+\begin{figure}[p]
+\codefollowupgeneral{Figures~\ref{fig:expr12} and \ref{fig:expr13}}
+\origfirstline{expr13double}{4}
+\caption{A transformation of ordinary arithmetic expressions}
+\label{fig:expr13double}
+\end{figure}
+
+\begin{figure}[p]
+\codefollowupgeneral{Figures~\ref{fig:expr12} and \ref{fig:expr08}}
+\origfirstline{expr08double}{4}
+\caption{A transformation of hash-consed arithmetic expressions}
+\label{fig:expr08double}
+\end{figure}
+
+\begin{figure}[p]
+\codefollowupgeneral{Figures~\ref{fig:expr12}, \ref{fig:expr13}, and~\ref{fig:expr08}}
+\origfirstline{expr14}{6}
+\caption{Conversions between ordinary and hash-consed arithmetic expressions}
+\label{fig:expr14}
+\end{figure}
+
+\subsection{Visitors for hash-consed abstract syntax trees}
+\label{sec:advanced:hashconsed}
+
+On top of the open data type \oc|oexpr| of the previous section
+(\sref{sec:advanced:openclosed}), one can define not just the closed data type
+\oc|expr| of ordinary arithmetic expressions, but also other closed data types
+of expressions where every node is annotated with information.
+
+As an example, let us define a type \oc|hexpr| of hash-consed (that is,
+maximally-shared) arithmetic expressions. We use Filliâtre and Conchon's
+library~\cite{filliatre-conchon-06}, which can be found in \opam under the
+name \hashcons.
+
+The definition of the type \oc|hexpr| appears in \fref{fig:expr08}. It is
+analogous to the definition of the type \oc|expr| (\fref{fig:expr13}), with an
+added twist: instead of taking the fixed point of the functor \oc|_ oexpr|, we
+take the fixed point of the functor \oc|_ oexpr hash_consed|. By looking up
+the definition of the type \oc|hash_consed| in \hashconsRepoFile{hashcons.mli},
+one finds that this means that every node in an arithmetic expression carries
+certain information (namely a unique tag and a hash) that are used to enforce
+maximal sharing.
+
+Enforcing maximal sharing requires maintaining a mutable table where all
+arithmetic expressions ever constructed are stored. (This is in fact a weak
+hash table.) We initialize such a table by calling the function
+\oc|Hashcons.create|. This table is then populated by the function \oc|h|, a smart
+constructor.
+% of type \oc|hexpr oexpr -> hexpr|.
+This function takes a candidate expression of type \oc|hexpr oexpr| and
+returns an expression of type \oc|hexpr|, which is either allocated anew
+or found in the table (should an identical expression already exist).
+
+We can now construct a visitor class for the type \oc|hexpr|. As in the previous
+section (\sref{sec:advanced:openclosed}), we do so by hand in a few lines of code.
+%
+% Our reasons for writing this code by hand are the same as in the previous
+% section. Furthermore, we note that the code of the visitor refers to the
+% function~\oc|h|, thus depends on \oc|table|. The definition of \oc|table|
+% itself must come after the definition of the type \oc|hexpr|, since the
+% type of \oc|table| is \oc|hexpr oexpr Hashcons.t|. For this reason, we
+% cannot use [@@deriving] to generate the visitor just after the type
+% definition.
+%
+% That said, since the visitor depends on \oc|h| and not directly on \oc|table|,
+% we could cut the dependency by going through the store. Create a reference to
+% a function of type \oc|hexpr oexpr -> hexpr|. Initialize it with a dummy
+% function. Generate the visitor. Then, create the table, define \oc|h| and
+% update the reference. Ugh.
+%
+The overall structure of this code is the same as in \fref{fig:expr13}. The
+only difference is that the method \tyconvisitor{'expr} must now traverse
+two levels of type structure, corresponding to \oc|_ oexpr hash_consed|.
+It deconstructs this structure by using the pattern \oc|H { node = e ; _ }|,%
+%
+\footnote{The \oc|node| field is part of the record type \oc|hash_consed|;
+see \hashconsRepoFile{hashcons.mli}.}
+%
+and reconstructs it by applying the smart constructor~\oc|h|.
+
+A function \oc|double| can be defined for hash-consed arithmetic expressions
+in exactly the same manner as we defined \oc|double| for ordinary arithmetic
+expressions: compare \fref{fig:expr13double} and \fref{fig:expr08double}.
+%
+% In fact, although we did not attempt to share the code of the method
+% \dataconvisitor{EConst} between these two figures, one could do so if
+% desired, by exploiting multiple inheritance.
+%
+
+The visitor class \oc|omap| for open arithmetic expressions
+(\fref{fig:expr12}) can be exploited to define conversions
+between different types of arithmetic expressions.
+This is illustrated in \fref{fig:expr14}.
+There, the function \oc|import| converts an ordinary expression
+to a hash-consed expression, thereby imposing maximal sharing.
+Conversely, the function \oc|export| converts a hash-consed
+expression into an ordinary expression, thereby abandoning
+all sharing (and possibly causing an exponential explosion).
+The implementation of these functions is simple: it is just
+a matter of overriding \tyconvisitor{'expr} so as to deconstruct
+one kind of expression and reconstruct the other kind.
+
+% ------------------------------------------------------------------------------
+
+\subsection{From visitors to iterators}
+\label{sec:iterators}
+
+It is possible to use a visitor to implement an iterator, that is, an object
+that traverses a container data structure and produces its elements on demand.
+The story is told in a blog post~\cite{iterators}.
+
+% ------------------------------------------------------------------------------
+% ------------------------------------------------------------------------------
+
+\section{Little-known aspects of OCaml objects}
+\label{sec:oo}
+
+In this section, we document a few relatively little-known aspects of OCaml's
+class and object system that play an essential role in our visitors.
+
+% ------------------------------------------------------------------------------
+
+\subsection{Type inference for concrete and virtual methods}
+\label{sec:oo:infer}
+
+It is well-known that OCaml can infer the type of a concrete method. In the
+following simple example, it infers that the field \oc|x| has type \oc|int|
+and that (therefore) the methods \oc|get| and \oc|set| must have types
+\oc|int| and \oc|int -> unit|, respectively:
+%
+\orig{OOinfer}
+
+It is perhaps lesser known that \emph{OCaml can also infer the type of a
+ virtual method}, based on the manner in which this method is used. In the
+following variant of the previous example, it infers that the method
+\oc|check| must have type \oc|int -> int|, as it receives an integer argument
+and produces a result that is stored in the field \oc|x|.
+%
+\orig{OOinfervirtual}
+
+The type annotation \oc|_| that appears in the declaration of the method
+\oc|check| stands for an unconstrained type variable. It lets the OCaml
+typechecker infer a most general monomorphic type for this method.
+A~polymorphic type cannot be inferred. If we wished for the method \oc|check|
+to have type \oc|'a . 'a -> 'a|, then we would have to explicitly annotate the
+declaration with this polymorphic type.
+
+% ------------------------------------------------------------------------------
+
+\subsection{Virtues of self-parameterized classes}
+\label{sec:oo:self}
+
+Popular belief holds that inferring a method's type fails if ``some type
+variables are unbound in this type''. For instance, in the following variant
+of the previous example, OCaml infers that the method \oc|check| has type
+\oc|'a -> int|, where the type variable \oc|'a| is unconstrained:
+%
+\orig{OOinfererror}
+
+At that point, it fails with a type error message:
+%
+\begin{mdframed}[backgroundcolor=red!10]
+\begin{lstlisting}[keywords={}]
+Error: Some type variables are unbound in this type:
+ class virtual int_cell :
+ object
+ val mutable x : int
+ method virtual check : 'a -> int
+ method get : int
+ method set : 'a -> unit
+ end
+The method check has type 'a -> int where 'a is unbound
+\end{lstlisting}
+\end{mdframed}
+
+In this case, the OCaml manual says, ``the class should be parametric'', and
+``the type parameters must be [subject] somewhere in the class body to a type
+constraint''. In the above example, one might choose to parameterize the class
+over a type variable~\oc|'a| and to add a type annotation that requires
+\oc|'a| to be the domain of the virtual method \oc|check|:
+%
+\orig{OOinferfixed}
+
+This eliminates the type error: this code is well-typed. One problem with this
+approach, though, is that further changes to the code might require
+introducing further type parameters. Suppose for instance that, instead of
+initializing the field~\oc|x| with the value \oc|0|, we wish to parameterize
+the class over an initial value~\oc|init|. We modify the code as follows:
+%
+\orig{OOinfererroragain}
+
+Unfortunately, this modification makes the code ill-typed again:
+%
+\begin{mdframed}[backgroundcolor=red!10]
+\begin{lstlisting}[keywords={}]
+Error: Some type variables are unbound in this type:
+ class virtual ['a] cell :
+ 'b ->
+ object
+ val mutable x : 'b
+ method virtual check : 'a -> 'b
+ method get : 'b
+ method set : 'a -> unit
+ end
+The method check has type 'a -> 'b where 'b is unbound
+\end{lstlisting}
+\end{mdframed}
+
+A natural reaction to this type error message might be to parameterize the
+class over both \oc|'a| and \oc|'b|, as follows:
+%
+\orig{OOinferfixedagain}
+
+This eliminates the type error: this code is well-typed. However, it seems
+unfortunate that one cannot depend on the typechecker to infer the types of
+all methods. Instead, it seems that one must introduce an unpredictable number
+of type parameters, as well as an unpredictable amount of explicit type
+annotations, for the code to be accepted.
+
+Fortunately, there is a solution to this problem.
+
+Let us first note that, in the above example, even though both the argument
+type and result type of the method \oc|check| are undetermined, \emph{it is
+ not necessary to introduce two type parameters} \oc|'a| and~\oc|'b|. Indeed,
+one type parameter suffices, provided this parameter determines both the
+argument type and result type of \oc|check|. To illustrate this, let us
+parameterize the class over a type variable \oc|'check|, and provide a type
+annotation that equates \oc|'check| with the type of the method \oc|check|:
+%
+\orig{OOinferfixedagaincheck}
+
+This code is well-typed, too. Its inferred type is as follows:
+%
+\begin{mdframed}[backgroundcolor=green!10]
+\begin{lstlisting}
+class virtual ['check] cell :
+ 'b ->
+ object
+ constraint 'check = 'a -> 'b (* a type equation *)
+ val mutable x : 'b
+ method virtual check : 'check
+ method get : 'b
+ method set : 'a -> unit
+ end
+\end{lstlisting}
+\end{mdframed}
+
+Because the typechecker infers and records the type equation %
+\oc|'check = 'a -> 'b|, instantiating the type variable~\oc|'check| with a
+concrete type suffices to determine the values of both~\oc|'a| and~\oc|'b|.
+For instance, if~\oc|'check| is instantiated with \oc|float -> int|, then
+\oc|'a| must be \oc|float| and \oc|'b| must be \oc|int|. For this reason,
+there is no need to parameterize the class over \oc|'a| and~\oc|'b|.
+Parameterizing it over \oc|'check| suffices.
+
+This remark alone does not quite solve our problem yet. It still seems as if,
+for a class definition to be accepted, one must introduce an unpredictable
+number of type parameters, as well as an unpredictable amount of explicit type
+annotations and/or type equations.
+
+Fortunately, there is a general way out of this problem. In fact, \emph{one
+ type parameter always suffices}. The trick is to constrain this type
+parameter to be the type of ``self''. Indeed, in OCaml, the type of ``self''
+is an OCaml object type that lists the names and types of all (public)
+methods. Therefore, fixing the type of ``self'' is enough to determine the
+type of every method.
+
+% A curious remark: even though the private methods do not appear in the type
+% of self, OCaml still allows their types to contain unconstrained type
+% variables. For instance, the following is allowed, with and without
+% self-parameterization:
+%
+% class virtual foo = object
+% method private virtual f: _
+% end
+%
+% class virtual ['self] foo = object (_ : 'self)
+% method private virtual f: _
+% end
+
+We modify the example as follows. We parameterize the class over a single type
+variable, named \oc|'self|, which we constrain to be the type of ``self'', via
+the type annotation \oc|self : 'self|.
+%
+\orig{OOinferself}
+
+Even though, this time, we have not given the type of the method \oc|check|,
+this code is well-typed. \emph{In~a self-parameterized OCaml class, a
+ monomorphic type can be inferred for every method}, be it concrete or
+virtual. In other words, in~a self-parameterized class, the OCaml typechecker
+never complains that ``some type variables are unbound''.
+
+In the \visitors package, this remark solves several problems. First, we never
+need to wonder how many type parameters a class should have, and what they
+should be: the answer is always one, namely \oc|'self|. Second, we never need
+to annotate a method with its type: every virtual method can be annotated with
+the wildcard \oc|_|. These properties are of utmost importance, as we cannot
+in general predict the types of the generated methods.
+
+Since self-parameterized classes seem so great, one may wonder whether, in
+everyday life, it would be a good idea to parameterize every class over
+\oc|'self| in this manner. The answer is, it probably would not. Such an
+approach leads to verbose class types, as the type of ``self'' contains a list
+of all (public) methods. It also gives rise to recursive object types, of the
+form \oc|'self c as 'self|, where \oc|c| is a class.
+
+% ------------------------------------------------------------------------------
+
+\subsection{Simplifying the type of a self-parameterized class}
+\label{sec:oo:monomorphic}
+
+We have used in \sref{sec:intro:type} a few rules that allow an inferred class
+type to be manually simplified. In going from \fref{fig:inferred} to
+\fref{fig:simplified}, we have used the well-known property that private
+methods can be omitted in a class type. We have also exploited the perhaps
+lesser-known fact that, in a self-parameterized class, the constraint that
+bears on the type parameter \oc|'self| can be omitted, as it is implicit in
+OCaml that the type of ``self'' must be an object type that lists the public
+methods.
+
+There remains to explain the surprising use of the ``\oc|'monomorphic.|'' prefix
+in \fref{fig:simplified}. On the face of it, this is a universal
+quantification over a type variable, named \oc|'monomorphic|, which does
+\emph{not} appear in the type of the method. From a purely logical standpoint,
+such a universal quantification should be superfluous. Yet, here, it is
+required, due to the following peculiarity of OCaml~\cite{ocaml7465}:
+\begin{quote}
+ In a class type,
+ if the type of a method exhibits a free variable~\oc|'a|,
+ if this method type has no explicit universal quantifiers,
+ and if the type variable~\oc|'a| does not appear in an explicit type constraint,
+ then, by convention,
+ OCaml considers that the method type is universally quantified in \oc|'a|.
+ % Personal communication with Jacques Garrigue.
+ % https://caml.inria.fr/mantis/view.php?id=7465
+\end{quote}
+We must work around this syntactic convention: in \fref{fig:inferred}, for
+instance, the method \tyconvisitor{expr} has monomorphic type %
+\oc|'env -> expr -> unit|, where the type variable \oc|'env| is connected with
+\oc|'self| via an implicit constraint and (like \oc|'self|) is quantified at
+the level of the class. This method does \emph{not} have polymorphic type %
+\oc|'env. 'env -> expr -> unit|. The logically redundant quantification over
+\oc|'monomorphic| serves as a syntactic mark that we really intend the type
+variable~\oc|'env| to appear free in the method type.
+
+% ------------------------------------------------------------------------------
+
+\subsection{Monomorphic methods, polymorphic classes}
+
+Even if a method is monomorphic, the class that contains this method can be
+polymorphic. In the following example, the \oc|identity| method is annotated
+with a monomorphic type, which implies that, if \oc|o| is an object of
+class~\oc|c|, then the method \oc|o#identity| cannot be applied both to apples
+and to oranges. However, the class~\oc|c| is polymorphic, which means that two
+distinct instances of this class can be used (separately) with apples and with
+oranges.
+\begin{origenv}
+\lstinputlisting{polyclass.ml}
+\end{origenv}
+This (well-known) property of classes is exploited in the \visitors package.
+Although (in monomorphic mode, \sref{sec:intro:parameterized:mono}) every
+generated visitor method is monomorphic, the visitor classes are
+polymorphic, so (distinct) visitor objects can be used at many different
+types.
+
+% ------------------------------------------------------------------------------
+
+% This subsection is mostly obsolete now that we have [polymorphic] mode,
+% so I am removing it.
+
+\begin{comment}
+
+\subsection{Customization from above and from below}
+
+In the object-oriented world, a traditional way of ensuring that a piece of
+code has customizable behavior is to write it in the form of a class with many
+(concrete or virtual) methods. These methods can later be overridden in a
+subclass: this is ``customization from below''.
+
+When the class is automatically generated, as is the case of our visitor
+classes, another approach to customization is to let the user choose which
+classes should be inherited: this is done via the \ancestors parameter
+(\sref{sec:params}). This is ``customization from above''. It is a somewhat
+more unusual customization mechanism.
+
+As the (concrete and virtual) methods that we generate must be monomorphic,
+customization from below is restricted, in our situation, to providing
+monomorphic code fragments. Fortunately, no such restriction bears on
+customization from above: a parent class can provide (hand-written)
+polymorphic methods.
+
+For this reason, customization from above plays a key role in our setting. For
+instance, the methods \oc|visit_array|, \oc|visit_list|, and so on, which must
+be polymorphic, must be hand-written, and must be inherited from a parent
+class. The asymmetry between hand-written methods (which may be polymorphic)
+and generated methods (which must be monomorphic) is admittedly unfortunate,
+but this is the best that we offer, at present.
+
+\end{comment}
+
+% ------------------------------------------------------------------------------
+
+\subsection{Where the expressiveness of OCaml's type system falls short}
+\label{sec:map_from_fold}
+
+\begin{figure}[p]
+\orig{map_from_fold}
+\caption{An unsatisfactory definition of \oc|map| as a subclass of \oc|fold|}
+\label{fig:map_from_fold}
+\end{figure}
+
+\begin{figure}[p]
+\begin{mdframed}[backgroundcolor=green!10]
+\lstinputlisting{map_from_fold.mli}
+\end{mdframed}
+\caption{The type of the class \oc|map_from_fold| (\fref{fig:map_from_fold})}
+\label{fig:map_from_fold:type}
+\end{figure}
+
+We have noted earlier (\sref{sec:intro:fold}) that, among the varieties of
+visitors that we have presented, \fold visitors are in principle the most
+general. This raises the question: is it possible to define \map and \reduce
+as subclasses of \fold, equipped with appropriate \tyconascendingmethod{}
+methods?
+
+Doing so would be more economical: that is, it would significantly reduce the
+redundancy between the classes \map, \reduce, and \fold. When these classes
+are automatically generated, code duplication is not so much of a problem.
+However, there are situations where (parts of) visitor classes must be
+hand-written, and where duplication becomes painful.
+
+Furthermore, defining \map and \reduce as subclasses of \fold would give rise
+to new patterns of customization. It would become possible to define a
+subclass of \map or \reduce and override just one \tyconascendingmethod{}
+method so as to obtain custom behavior.%
+%
+\footnote{At present, this must be done by overriding a
+ \tyconvisitor{} method, thereby causing more code duplication than
+ necessary.}
+
+In an untyped setting, the question can be answered positively: \map and
+\reduce can be defined in terms of \fold. Unfortunately, in the setting
+of OCaml's type system, the answer is negative: although \reduce can be
+defined in terms of \fold, \map cannot.
+% (or cannot always).
+
+The situation is illustrated in \fref{fig:map_from_fold}. As an example, we
+define visitor methods, by hand, for the type \oc|'a option|.
+
+The methods \tyconvisitor{option} in the classes \reduce and \map are
+identical to those found in the classes \runtime{reduce} and \runtime{map}. We
+note that the method \tyconvisitor{option} in the class \reduce is polymorphic
+in \oc|'a|, whereas \tyconvisitor{option} in the class \map is polymorphic
+in~\oc|'a| and~\oc|'b|.
+
+There is some similarity between these methods, which is why we define a class
+\fold, whose method \tyconvisitor{option} contains calls to the virtual
+methods \dataconascendingmethod{None} and \dataconascendingmethod{Some}. We
+assign to this method the most general type that is expressible in OCaml's
+type system. It is polymorphic in \oc|'a|. The type variable~\oc|'r|, which
+represents the result of the function~\oc|f|, and the type variable~\oc|'s|,
+which represents the result of the methods \tyconvisitor{option},
+\dataconascendingmethod{None}, and \dataconascendingmethod{Some},
+cannot be universally quantified at the level of a method,
+since they appear in the types of several methods.
+They must be (implicitly) quantified at the level of the class.
+
+Is this definition of \fold satisfactory? To test this, let us now attempt to
+propose new definitions of \reduce and \map as subclasses of \fold. We define
+two more classes, \oc|reduce_from_fold| and \oc|map_from_fold|, which both
+inherit \oc|fold| and provide suitable definitions of the methods
+\dataconascendingmethod{None} and \dataconascendingmethod{Some}.
+
+In \oc|reduce_from_fold|, everything works fine. The type parameters \oc|'r|
+and \oc|'s| in \fold are both instantiated with \oc|'z|. As a result, the
+method \tyconvisitor{option} in the class \oc|reduce_from_fold| has type
+%
+\oc|'a. ('c -> 'a -> 'z) -> 'c -> 'a option -> 'z|,
+%
+just as in the class \reduce.
+
+In \oc|map_from_fold|, a problem arises. The code is well-typed, but its type
+is less general than desired. The OCaml typechecker infers that the type
+parameters \oc|'r| and \oc|'s| in \fold must be respectively instantiated with
+\oc|'b| and \oc|'b option|, where the type variable \oc|'b| must be quantified
+at the level of the class. Therefore, the type of \oc|map_from_fold| is as
+shown in \fref{fig:map_from_fold:type}. This type is \emph{not} polymorphic
+in~\oc|'b|, thus strictly less general than the type of the method
+\tyconvisitor{option} in the class \map (\fref{fig:map_from_fold}).
+
+What would it take to repair this problem? Apparently, the type of the method
+\tyconvisitor{option} in the class \fold is not general enough. Whereas the
+type variables \oc|'r| and \oc|'s| currently have kind \oc|*|, it seems that
+they should have kind \oc|* -> *|. The type of the class \fold should be as
+follows:
+%
+\begin{mdframed}[backgroundcolor=green!10]
+\begin{lstlisting}
+class ['self] fold : object ('self)
+ method private visit_option: 'a 'b .
+ ('env -> 'a -> 'r['b]) -> 'env -> 'a option -> 's['b]
+ method private virtual build_None: 'b . 'env -> 's['b]
+ method private virtual build_Some: 'b . 'env -> 'r['b] -> 's['b]
+end
+\end{lstlisting}
+\end{mdframed}
+
+This is not valid OCaml: we write \oc|'r[b]| for the type-level application of
+\oc|'r| to \oc|'b|. The type of each method is universally quantified in
+\oc|'b|, as desired. The type of \tyconvisitor{option} seems to have the
+desired generality. By instantiating both~\oc|'r| and~\oc|'s| with the
+type-level function \oc|fun 'b -> 'z|, we obtain the type of
+\tyconvisitor{option} in the class \reduce. By instantiating \oc|'r| and
+\oc|'s| with the type-level functions
+%
+\oc|fun 'b -> 'b| and \oc|fun 'b -> 'b option|, respectively, we obtain the
+type of \tyconvisitor{option} in the class \map.
+
+This suggests that higher kinds, type-level functions, and type-level
+$\beta$-reduction might be valuable features, not just in functional
+programming languages, but also in an object-oriented programming setting.
+
+% ------------------------------------------------------------------------------
+% ------------------------------------------------------------------------------
+
+\section{Reference}
+
+% ------------------------------------------------------------------------------
+% Parameters.
+
+\begin{figure}[p]
+\renewcommand{\arraystretch}{1.5}
+\begin{tabular}{@{}r@{\qquad}l@{\quad}p{.64\textwidth}@{}}
+ \ancestors & (list of strings) &
+ A list of classes that the generated class should inherit.
+ This is an optional parameter; its default value is the empty list.
+ The class \runtime{<variety>} is implicitly prepended to this list
+ unless \nude is \texttt{true}.
+ Every ancestor class must have exactly \emph{one} type parameter,
+ which is typically (but not necessarily) the type of ``self''.
+\\
+ \buildprefix & (string) &
+ The prefix that is used in the name of the build methods in \fold and
+ \foldtwo visitors (\sref{sec:intro:fold}).
+ This is an optional parameter, whose default value is ``\texttt{build\_}''.
+\\
+ \concrete & (Boolean) &
+ If \texttt{true}, the generated class is declared
+ concrete; otherwise, it is declared virtual.
+ This is an optional parameter; its default value is \texttt{false}.
+\\
+ \data & (Boolean) &
+ If \texttt{true}, one visitor method is generated for every data constructor (\sref{sec:structure}).
+ If \texttt{false}, this method is not generated (it is inlined instead).
+ This is an optional parameter; its default value is \texttt{true}.
+\\
+ \failprefix & (string) &
+ The prefix that is used in the name of the failure methods in
+ visitors of arity two (\sref{sec:intro:aritytwo}).
+ This is an optional parameter, whose default value is ``\texttt{fail\_}''.
+\\
+ \irregular & (Boolean) &
+ If \texttt{true}, the regularity check (\sref{sec:regularity}) is disabled;
+ otherwise, it is enabled.
+ This is an optional parameter; its default value is \texttt{false}.
+\\
+ \name & (string) &
+ The name of the generated class.
+ This is an optional parameter; its default value is \oc|<variety>|.
+\\
+ \nude & (Boolean) &
+ If \texttt{true}, the class \runtime{<variety>} is \emph{not} implicitly prepended to
+ the list \ancestors.
+ This is an optional parameter; its default value is \texttt{false}.
+\\
+ \polymorphic & (Boolean) &
+ If \texttt{true}, type variables are handled by virtual visitor methods,
+ and generated methods are monomorphic
+ (\sref{sec:intro:parameterized:mono});
+ if \texttt{false}, type variables are handled by visitor functions,
+ and generated methods are polymorphic
+ (\sref{sec:intro:parameterized:poly}).
+ This is an optional parameter, whose default value is \texttt{false}.
+\\
+ \public & (list of strings) &
+ This is an optional parameter.
+ If absent, then every method in the generated class is declared public.
+ If present, then every method in the generated class is declared
+ private, except those whose name appears in the list: those are declared public.
+\\
+ \variety & (string) &
+ The variety of visitor that should be generated.
+ The supported varieties are
+ \iter (\sref{sec:intro:iter:def}),
+ \map (\sref{sec:intro:map}) and
+ \mapendo (\sref{sec:intro:endo}),
+ \reduce (\sref{sec:intro:reduce}),
+ \mapreduce (\sref{sec:intro:mapreduce}),
+ \fold (\sref{sec:intro:fold}),
+ \itertwo,
+ \maptwo,
+ \reducetwo,
+ \mapreducetwo,
+ \foldtwo (\sref{sec:intro:aritytwo}).
+\\
+ \visitprefix & (string) &
+ The prefix that is used in the name of visitor methods.
+ This is an optional parameter, whose default value is ``\texttt{visit\_}''.
+ Be aware that, if this prefix is changed, then the classes provided by the
+ library \texttt{VisitorsRuntime} become useless: in that case, one might wish to
+ also specify \verb+nude = true+, so as to not inherit these classes.
+\end{tabular}
+\vspace{2.5mm}
+\hrule
+\vspace{2.5mm}
+\caption{Parameters of \derivingvisitors}
+\label{fig:params}
+\end{figure}
+
+\subsection{Parameters}
+\label{sec:params}
+\label{sec:ancestors}
+
+The parameters that can be passed as part of the \derivingvisitors annotation,
+inside the curly braces, are described in \fref{fig:params}.
+
+% ------------------------------------------------------------------------------
+
+\subsection{How to examine the generated code}
+
+The generated code is conceptually inserted into the user's source code just
+after the type definition that is decorated with \derivingvisitors.
+
+It can be useful to inspect the generated code, so as to understand how it
+works, what are the arguments and result of each method, and so on. This can
+be especially useful when the generated code is ill-typed (which can happen,
+for instance, when arbitrary user code is inherited via the \ancestors
+parameter).
+
+The file \repoFile{Makefile.preprocess} offers a recipe that builds a file
+named \verb|%.processed.ml| out of the source file \verb|%.ml|. This file contains
+just the generated code. The recipe relies on \oc|sed|, \oc|perl|, and
+\oc|ocp-indent| to extract and beautify the code. This file is installed
+with the \visitors package; it can be found at the computed path
+\verb+`ocamlfind query visitors`/Makefile.preprocess+. In a \texttt{Makefile},
+use the following directive:
+\begin{verbatim}
+ include $(shell ocamlfind query visitors)/Makefile.preprocess
+\end{verbatim}
+
+% ------------------------------------------------------------------------------
+
+\subsection{Structure of the generated code}
+\label{sec:structure}
+
+The \derivingvisitors annotation applies to a type definition. A type
+definition may define several types, and these types may be parameterized. A
+local type is one that is defined as part of this type definition, whereas a
+nonlocal type is one that preexists (\sref{sec:intro:nonlocal}).
+
+The generated code consists of \emph{a single class}, whose name is \oc|<variety>|,
+that is, the value of the \variety parameter (\sref{sec:params}). This class
+has \emph{one type parameter}, namely \oc|'self|, the type of ``self''
+(\sref{sec:oo:self}). It has no fields. It \emph{inherits} from the class
+\runtime{<variety>} (unless the parameter \nude is \texttt{true}, \sref{sec:params})
+and from the classes listed via the \ancestors parameter (\sref{sec:params}),
+in that order. To find out which methods exist in the class
+\runtime{<variety>}, please consult \runtimeFile{VisitorsRuntime.ml}.
+
+In the following, the index~\oc|i| ranges from 0 (included) to \oc|<arity>|
+(excluded), where \oc|<arity>| is the arity of the generated visitor (thus,
+either 1 or 2).
+
+The following \emph{concrete methods} are \emph{defined}:
+%
+\begin{itemize}
+\item for every local type \oc|??? foo|, a visitor method.
+
+ \begin{tabular}{@{\qquad}rp{35mm}@{\quad}p{7cm}}
+ method name: & \tyconvisitor{foo} \\
+ arguments: & \tyconvisitor{'a}, \ldots & a visitor function for each type param.\ of \oc|foo| \\
+ & & (only if \oc|polymorphic = true|) \\
+ & \oc|env| & an environment of type \oc|'env| \\
+ & \oc|this_0|, \oc|this_1|, \ldots & for each \oc|i|, a value of type \oc|??? foo| \\
+ invoked: & on the way down \\
+ example: & \fref{fig:expr00}
+ \end{tabular}
+
+\item for every data constructor \oc|Foo| of a local sum type \oc|??? foo|, a visitor method.
+
+ \begin{tabular}{@{\qquad}rp{35mm}@{\quad}p{7cm}}
+ method name: & \dataconvisitor{Foo} \\
+ arguments: & \tyconvisitor{'a}, \ldots & a visitor function for each type param.\ of \oc|foo| \\
+ & & (only if \oc|polymorphic = true|) \\
+ & \oc|env| & an environment of type \oc|'env| \\
+ & \oc|this| & a data structure of type \oc|??? foo| \\
+ & & (only in an \mapendo visitor) \\
+ & \oc|c0_0|, \oc|c0_1|, \ldots & for each \oc|i|, the first component of a \oc|Foo| value \\
+ & \oc|c1_0|, \oc|c1_1|, \ldots & for each \oc|i|, the next component of a \oc|Foo| value \\
+ & \ldots & \ldots and so on \\
+ invoked: & on the way down \\
+ example: & \fref{fig:expr00}
+ \end{tabular}
+
+ If the parameter \data is \texttt{false}, then
+ this method is \emph{not} generated (\sref{sec:params}).
+ It is inlined instead. The behavior is the same, but cannot be overridden on
+ a per-data-constructor basis.
+
+\item if the visitor has arity two (\sref{sec:intro:aritytwo}),
+ for every local type \oc|foo|,
+ a failure method.
+
+ \begin{tabular}{@{\qquad}rp{35mm}@{\quad}p{7cm}}
+ method name: & \tyconfail{foo} \\
+ arguments: & \oc|env| & an environment of type \oc|'env| \\
+ & \oc|this_0|, \oc|this_1|, \ldots & for each \oc|i|, a value of type \oc|??? foo| \\
+ invoked: & \multicolumn{2}{l}{when two distinct data constructors \oc|Foo| and \oc|Bar| are found} \\
+ example: & \fref{fig:expr02}
+ \end{tabular}
+
+\end{itemize}
+%
+
+The following \emph{virtual methods} are \emph{declared}:
+%
+\begin{itemize}
+\item for every type parameter \oc|'foo| of a local type,
+ a visitor method. (Only if \oc|polymorphic = true|.)
+
+ \begin{tabular}{@{\qquad}rp{35mm}@{\quad}p{7cm}}
+ method name: & \tyconvisitor{'foo} \\
+ arguments: & \oc|env| & an environment of type \oc|'env| \\
+ & \oc|this_0|, \oc|this_1|, \ldots & for each \oc|i|, a value of type \oc|'foo| \\
+ invoked: & on the way down \\
+ example: & \fref{fig:expr_info}
+ \end{tabular}
+
+\item if this is a \reduce visitor (\sref{sec:intro:reduce})
+ or a \mapreduce visitor (\sref{sec:intro:mapreduce}),
+ the monoid methods.
+
+ \begin{tabular}{@{\qquad}rp{35mm}@{\quad}p{7cm}}
+ method name: & \oc|zero| \\
+ arguments: & none \\
+ result: & a summary \\
+ example: & \fref{fig:expr15}
+ \end{tabular}
+
+ \begin{tabular}{@{\qquad}rp{35mm}@{\quad}p{7cm}}
+ method name: & \oc|plus| \\
+ arguments: & two summaries \\
+ result: & a summary \\
+ example: & \fref{fig:expr15}
+ \end{tabular}
+
+\item if this is a \fold visitor (\sref{sec:intro:fold}),
+ for every local record type \oc|foo|,
+ a build method.
+
+ \begin{tabular}{@{\qquad}rp{35mm}@{\quad}p{7cm}}
+ method name: & \tyconascendingmethod{foo} \\
+ arguments: & \oc|env| & an environment of type \oc|'env| \\
+ & \oc|r_0| & the result of the first recursive call \\
+ & \oc|r_1| & the result of the next recursive call \\
+ & & \ldots and so on \\
+ invoked: & on the way up \\
+ example: & none in this document
+ \end{tabular}
+
+\item if this is a \fold visitor (\sref{sec:intro:fold}),
+ for every data constructor \oc|Foo| of a local sum type,
+ a build method.
+
+ \begin{tabular}{@{\qquad}rp{35mm}@{\quad}p{7cm}}
+ method name: & \dataconascendingmethod{Foo} \\
+ arguments: & \oc|env| & an environment of type \oc|'env| \\
+ & \oc|r_0| & the result of the first recursive call \\
+ & \oc|r_1| & the result of the next recursive call \\
+ & & \ldots and so on \\
+ invoked: & on the way up \\
+ example: & \fref{fig:expr00fold}
+ \end{tabular}
+
+\end{itemize}
+
+The following methods are \emph{called}, therefore are expected to exist.
+These methods are neither defined nor declared: their definition or
+declaration must be inherited from a parent class. These methods can have a
+polymorphic type.
+%
+\begin{itemize}
+\item for every nonlocal type \oc|??? foo|, a visitor method.
+
+ \begin{tabular}{@{\qquad}rp{35mm}@{\quad}p{7cm}}
+ method name: & \tyconvisitor{foo} \\
+ arguments: & \oc|visit_0|, \ldots & for each actual type parameter in \oc|??? foo|, \\
+ & & a visitor function for this type \\
+ & \oc|env| & an environment of type \oc|'env| \\
+ & \oc|this_0|, \oc|this_1|, \ldots & for each \oc|i|, a value of type \oc|??? foo| \\
+ invoked: & on the way down \\
+ example: & \fref{fig:expr11}
+ \end{tabular}
+
+\end{itemize}
+
+All of the above methods are parameterized with an environment \oc|env|, which
+is propagated in a top-down manner, that is, into the recursive calls. The
+environment is not returned out of the recursive calls, therefore not
+propagated bottom-up or left-to-right. The type of this environment is
+undetermined: it is a type variable.
+% (which is implicitly related with \oc|'self|)
+There is no a priori constraint that the type of the environment should be
+the same in every method: it is possible for unrelated visitor methods to
+expect environments of unrelated types.
+
+The result types of the visitor methods, build methods, and failure methods
+depend on the parameter \variety (\sref{sec:params}). In an \iter visitor,
+every method has result type \oc|unit|. In a \map or \mapendo visitor, the
+visitor method associated with the type \oc|foo| has result type \oc|??? foo|.%
+%
+\footnote{The question marks \oc|???| stand for the type parameters of \oc|foo|,
+which can be a parameterized type. In a \map visitor, the type parameters that
+appear in the method's argument type and in the method's result type can differ.
+In an \mapendo visitor, they must be the same.}
+%
+In a \reduce visitor, every method has result type \oc|'s|, if \oc|'s| is the
+monoid, that is, if the methods \oc|zero| and \oc|plus| respectively have type \oc|'s|
+and \oc|'s -> 's -> 's|.
+%
+In a \mapreduce visitor, the visitor method associated with the type \oc|foo|
+has result type \oc|??? foo * 's|, if \oc|'s| is the monoid.
+%
+In a \fold visitor, it is up to the user to decide what the result types of
+the visitor methods should be (subject to certain consistency constraints,
+naturally). In particular, two visitor methods \tyconvisitor{foo} and
+\tyconvisitor{bar} can have distinct result types; this is illustrated
+in \fref{fig:fold}.
+
+% ------------------------------------------------------------------------------
+
+\subsection{Supported forms of types}
+
+The following forms of type definitions are supported:
+\begin{itemize}
+\item Definitions of \emph{type abbreviations} (also known as type synonyms).
+\item Definitions of \emph{record types}. \\ Mutable fields are supported.
+\item Definitions of \emph{sum types} (also known as variant types and as algebraic
+ data types). \\ Data constructors whose arguments form an ``inline record'' are
+ supported.
+\end{itemize}
+
+Definitions of abstract types and of extensible sum types are not supported.
+
+\label{sec:regularity}
+% The regularity restriction.
+
+Definitions of \emph{parameterized types} are supported. In monomorphic mode
+(\sref{sec:intro:parameterized:mono}), only \emph{\hbox{regular}}
+parameterized types are permitted, whereas in polymorphic mode
+(\sref{sec:intro:parameterized:poly}), arbitrary parameterized types are
+permitted.
+%
+A parameterized type is regular if, within its own definition, it is applied
+only to its formal parameters. For instance, the well-known definition of
+lists is regular:
+
+\begin{origenv}
+\begin{lstlisting}
+type 'a list =
+| []
+| (::) of 'a * 'a list
+\end{lstlisting}
+\end{origenv}
+%
+whereas the following definition of a random access
+list~\cite[\S10.1.2]{okasaki-book-99} is not:
+%
+\begin{origenv}
+\begin{lstlisting}
+type 'a seq =
+| Nil
+| Zero of ('a * 'a) seq
+| One of 'a * ('a * 'a) seq
+\end{lstlisting}
+\end{origenv}
+
+Irregular data types are also known as
+``nonuniform''~\cite[\S10.1]{okasaki-book-99} or ``nested'' data
+types~\cite{bird-meertens-98}.
+
+% The regularity check performed by the \visitors package in monomorphic mode
+% can be disabled via the \irregular parameter (\sref{sec:params}).
+
+Existential types and generalized algebraic data types (GADTs) are currently
+not supported.
+
+% Visiting an existential type seems problematic anyway, since we do not know
+% how to descend into a value of unknkown type. Perhaps we could generate a
+% default visitor method which treats the value as opaque, and allow the user
+% to override this behavior if desired.
+
+% Visiting a GADT seems possible if the type parameters are used purely as
+% indices (i.e., they are phantom parameters). In that case, we actually do
+% not need visitor functions for the type parameters.
+
+In the right-hand side of a type definition, the following forms of types are
+supported:
+\begin{itemize}
+\item Type constructors, possibly applied to a number of types, such as
+ \oc|foo| and \oc|('a * 'b) bar|.
+\item Type variables, such as \oc|'foo|.
+\item Tuple types, such as \oc|int * expr|.
+\end{itemize}
+The unsupported forms of types include
+anonymous type variables (\oc|_|),
+function types (\oc|int -> unit|),
+object types (\oc|<get: int>| and \oc|#point|),
+recursive types (\oc|int -> 'a as 'a|),
+polymorphic variant types (\oc+[ `A| `B ]+),
+universal types (\oc|'a. 'a -> 'a|),
+and
+packaged module types (\oc|(module S)|).
+If these forms appear in a type definition,
+they must be marked \oc|@opaque| (\sref{sec:opaque}).
+
+In theory, at each arity, the tuple type constructor could be viewed as a
+parameterized nonlocal type constructor. At arity 2, for instance, the pair
+type \oc|'a * 'b| could be treated as a nonlocal type \oc|('a, 'b) tuple2|.
+Then, to traverse a value of this type, one would invoke a method
+\tyconvisitor{tuple2}, which necessarily would be inherited from a parent
+class. That would be somewhat inconvenient, as these (polymorphic) methods
+would have to be manually written, at each arity. Instead, special treatment
+for tuple types is built-in. There are no visitor methods or build methods for
+tuples; instead, ad hoc code is generated. This means that the behavior of a
+visitor at a tuple type is fixed: it cannot be overridden in a subclass. The
+behavior of a \fold visitor at a tuple type is to rebuild a tuple, just like a
+\map visitor would do.
+
+% ------------------------------------------------------------------------------
+
+\subsection{Opaque components}
+\label{sec:opaque}
+
+One sometimes wishes for a component of a data structure \emph{not} to be
+visited, either for efficiency reasons, or because this component is of an
+unsupported type. This can be requested by annotating the type of this
+component with the attribute \oc|[@opaque]|. This is done, for instance, if
+\fref{fig:expr15}, where the integer argument of the data constructor
+\oc|EConst| is marked opaque. (Note the parentheses, which are required.) The
+effect of this annotation is that this component is not visited: in the method
+\dataconvisitor{EConst}, instead of a call to \oc|self#visit_int|, we find a
+call to \oc|self#zero|, as this is a \reduce visitor.
+
+Generating a visitor of arity two for a data structure with \oc|@opaque|
+components requires some care. The methods \tyconvisitor{int} defined in the
+classes \runtime{iter2}, \runtime{map2}, and so on, raise a
+\oc|StructuralMismatch| exception when their two integer arguments differ. If
+\oc|int| is replaced with \oc|(int[@opaque])|, then these methods are not
+invoked, so no exception is raised. It is up to the user to decide which
+behavior is desired. Furthermore, it should be noted that \maptwo and \foldtwo
+visitors follow an arbitrary convention at \oc|@opaque| components: they
+return the first of their two arguments. Again, it is up to the user to decide
+whether this behavior is appropriate.
+
+In \polymorphic mode (\sref{sec:intro:parameterized:poly}), a type variable
+must not occur under an \oc|[@opaque]| annotation.
+
+If desired, instead of \oc|[@opaque]|, one can use the more verbose forms
+\oc|[@visitors.opaque]| and \oc|[@deriving.visitors.opaque]|.
+
+% ------------------------------------------------------------------------------
+
+\subsection{Alternate method names}
+\label{sec:name}
+
+The methods associated with the type \oc|foo| are normally named after this
+type: this includes the visitor method \tyconvisitor{foo}, the build method
+\tyconascendingmethod{foo},
+% (in \oc|fold| visitors)
+and the failure method \tyconfail{foo}.
+% (when the arity is 2)
+This base name can be altered via an attribute. If \oc|foo| is a local type,
+then a \oc|[@@name]| attribute must be attached to the declaration of this
+type. If \oc|foo| is a nonlocal type, then a \oc|[@name]| attribute must be
+attached to every reference to this type. For instance, in the following
+example,
+the visitor method associated with the type \oc|cloud| is named
+\oc|visit_nuage| instead of \oc|visit_cloud|:
+%
+\begin{origenv}
+\begin{lstlisting}
+type cloud =
+ | Point of (float[@name "real"]) * (float[@name "real"])
+ | Clouds of cloud list
+ [@@name "nuage"]
+ [@@deriving visitors { variety = "map"; ancestors = ["base"] }]
+\end{lstlisting}
+\end{origenv}
+%
+Furthermore, the visitor method associated with the type \oc|float|
+(which is not generated, and should be inherited from the class \oc|base|)
+is assumed to be named \oc|visit_real| instead of \oc|visit_float|.
+
+The methods associated with the data constructor \oc|Foo| are normally named
+after it: this includes the visitor method \dataconvisitor{Foo} and the build
+method \dataconascendingmethod{Foo}.
+%
+This base name can be altered via a \oc|[@name]| attribute, which must be
+attached to the data constructor. For instance, in the following example,
+the visitor methods associated with the data constructors \oc|[]| and \oc|::|
+are named \dataconvisitor{nil} and \dataconvisitor{cons}:
+% instead of \dataconvisitor{[]} and \dataconvisitor{::},
+% which would be invalid names:
+%
+\begin{origenv}
+\begin{lstlisting}
+type 'a mylist = 'a list =
+ | [] [@name "nil"]
+ | (::) of 'a * 'a mylist [@name "cons"]
+ [@@deriving visitors { variety = "map" }]
+\end{lstlisting}
+\end{origenv}
+%
+If desired, instead of \oc|[@name]|, one can use
+\oc|[@visitors.name]| or \oc|[@deriving.visitors.name]|.
+
+% ------------------------------------------------------------------------------
+
+\subsection{Alternate construction code in \map visitors}
+\label{sec:build}
+
+By default, a \map visitor for an algebraic data type constructs a new data
+structure, by applying a data constructor or by allocating a new record.
+Sometimes, though, it is illegal to do so: this is the case, for instance, if
+the type has been declared \oc|private|.
+%
+% Sometimes, the default behavior is well-typed, but is not the desired
+% behavior. In that case, it can be customized by overriding a method. Using
+% [@build] offers a little extra conciseness and efficiency in that case, but
+% this need not be advertised.
+%
+% Another solution would be to just write the visitor by hand for a private
+% type, but that would require more work from the user.
+%
+In such a situation, an alternate constructor can be provided via a
+\oc|[@build]| attribute (which must be attached to a data constructor) or via a
+\oc|[@@build]| attribute (which must be attached to a record type declaration).
+%
+Such an attribute carries an OCaml expression, which should represent a
+constructor function.
+
+For instance, suppose that the module \oc|Point| has the following signature:
+\begin{mdframed}[backgroundcolor=green!10]
+\lstinputlisting{point.mli}
+\end{mdframed}
+
+Suppose that, outside of this module, one wishes to generate a \map visitor
+for the type \oc|Point.point|. One would like to do this in the style that was
+presented earlier (\sref{sec:import}), but a naïve attempt fails: the
+generated visitor is illegal, because allocating a record of type
+\oc|Point.point| is forbidden. To circumvent this problem, one should
+indicate, via a \oc|[@@build]| attribute, that the constructor function
+\oc|Point.make| should be used:
+%
+\begin{origenv}
+\begin{lstlisting}
+type point = Point.point = private { x: int; y: int }
+ [@@build Point.make]
+ [@@deriving visitors { variety = "map" }]
+\end{lstlisting}
+\end{origenv}
+%
+
+The OCaml expression carried by a \oc|[@build]| attribute can refer to the
+local variable \oc|self|, which represents the visitor object, and to the
+local variable \oc|env|, which represents the environment received by the
+visitor method.
+
+\oc|[@build]| attributes influence not only \map visitors,
+but also \mapendo and \mapreduce visitors.
+
+Instead of \oc|[@build]|, one can use
+\oc|[@visitors.build]| or \oc|[@deriving.visitors.build]|.
+
+% Be careful not to misspell the attribute name,
+% as the attribute would then be silently ignored.
+
+% ------------------------------------------------------------------------------
+
+\bibliographystyle{plain}
+\bibliography{english,local}
+
+\end{document}
+
+% TEMPORARY to do:
+
+explain how to use visitors to obtain
+ an equality function {fig:expr05}
+ an ordering function {fig:expr05lexico}
+ a hash function ?? -- use a reduce visitor
+
+add a use case that shows an environment in use
+ e.g. expressions with let bindings,
+ and if a variable is bound to a constant, replace it with its value
+
+document the speed overhead compared to a native recursive function
+
+document the lazy-initializer trick, if used
+
+référence:
+ avoid shadowing the following names: VisitorsRuntime, Lazy, Pervasives
+
+related work, for OCaml:
+ ppx_deriving (generates monolithic code) (fixed number of templates)
+ ppx_deriving_morphism
+ janestreet/ppx_traverse
+ Hongbo Zhang has `deriving at a distance' in Fan
+ https://github.com/bobzhang/fan
+ http://zhanghongbo.me/fan/
+ http://zhanghongbo.me/fan/_downloads/metaprogramming_for_ocaml.pdf
+ alphaCaml
+
+related work, for other programming languages:
+ Bound (Edward Kmett)
+ Unbound (Weirich)
+ RedPerl
+ Francisco Ferreira et Brigitte Pientka, ESOP 2017 (Babybel)
+
+related work, for proof assistants:
+ Steven Keuchel
+ Autosubst (voir Kaiser et al., CPP 2017)
+ voir Guillaume Allais (CPP 2017, Agda et Haskell) et Goguen & McKinna
diff --git a/doc/plain.bst b/doc/plain.bst
new file mode 100644
index 0000000..2071152
--- /dev/null
+++ b/doc/plain.bst
@@ -0,0 +1,1106 @@
+% BibTeX standard bibliography style `plain'
+ % version 0.99a for BibTeX versions 0.99a or later, LaTeX version 2.09.
+ % Copyright (C) 1985, all rights reserved.
+ % Copying of this file is authorized only if either
+ % (1) you make absolutely no changes to your copy, including name, or
+ % (2) if you do make changes, you name it something other than
+ % btxbst.doc, plain.bst, unsrt.bst, alpha.bst, and abbrv.bst.
+ % This restriction helps ensure that all standard styles are identical.
+ % The file btxbst.doc has the documentation for this style.
+
+% Modified by Francois.Pottier@inria.fr with support for url field.
+
+ENTRY
+ { address
+ author
+ booktitle
+ chapter
+ edition
+ editor
+ howpublished
+ institution
+ journal
+ key
+ month
+ note
+ number
+ organization
+ pages
+ publisher
+ school
+ series
+ title
+ type
+ url
+ volume
+ year
+ }
+ {}
+ { label }
+
+INTEGERS { output.state before.all mid.sentence after.sentence after.block }
+
+FUNCTION {init.state.consts}
+{ #0 'before.all :=
+ #1 'mid.sentence :=
+ #2 'after.sentence :=
+ #3 'after.block :=
+}
+
+STRINGS { s t }
+
+FUNCTION {output.nonnull}
+{ 's :=
+ output.state mid.sentence =
+ { ", " * write$ }
+ { output.state after.block =
+ { add.period$ write$
+ newline$
+ "\newblock " write$
+ }
+ { output.state before.all =
+ 'write$
+ { add.period$ " " * write$ }
+ if$
+ }
+ if$
+ mid.sentence 'output.state :=
+ }
+ if$
+ s
+}
+
+FUNCTION {output}
+{ duplicate$ empty$
+ 'pop$
+ 'output.nonnull
+ if$
+}
+
+FUNCTION {output.check}
+{ 't :=
+ duplicate$ empty$
+ { pop$ "empty " t * " in " * cite$ * warning$ }
+ 'output.nonnull
+ if$
+}
+
+FUNCTION {output.bibitem}
+{ newline$
+ "\bibitem{" write$
+ cite$ write$
+ "}" write$
+ newline$
+ ""
+ before.all 'output.state :=
+}
+
+FUNCTION {fin.entry}
+{ add.period$
+ write$
+ newline$
+}
+
+FUNCTION {new.block}
+{ output.state before.all =
+ 'skip$
+ { after.block 'output.state := }
+ if$
+}
+
+FUNCTION {new.sentence}
+{ output.state after.block =
+ 'skip$
+ { output.state before.all =
+ 'skip$
+ { after.sentence 'output.state := }
+ if$
+ }
+ if$
+}
+
+FUNCTION {not}
+{ { #0 }
+ { #1 }
+ if$
+}
+
+FUNCTION {and}
+{ 'skip$
+ { pop$ #0 }
+ if$
+}
+
+FUNCTION {or}
+{ { pop$ #1 }
+ 'skip$
+ if$
+}
+
+FUNCTION {new.block.checka}
+{ empty$
+ 'skip$
+ 'new.block
+ if$
+}
+
+FUNCTION {new.block.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.block
+ if$
+}
+
+FUNCTION {new.sentence.checka}
+{ empty$
+ 'skip$
+ 'new.sentence
+ if$
+}
+
+FUNCTION {new.sentence.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.sentence
+ if$
+}
+
+FUNCTION {field.or.null}
+{ duplicate$ empty$
+ { pop$ "" }
+ 'skip$
+ if$
+}
+
+FUNCTION {emphasize}
+{ duplicate$ empty$
+ { pop$ "" }
+ { "{\em " swap$ * "}" * }
+ if$
+}
+
+INTEGERS { nameptr namesleft numnames }
+
+FUNCTION {format.names}
+{ 's :=
+ #1 'nameptr :=
+ s num.names$ 'numnames :=
+ numnames 'namesleft :=
+ { namesleft #0 > }
+ { s nameptr "{ff~}{vv~}{ll}{, jj}" format.name$ 't :=
+ nameptr #1 >
+ { namesleft #1 >
+ { ", " * t * }
+ { numnames #2 >
+ { "," * }
+ 'skip$
+ if$
+ t "others" =
+ { " et~al." * }
+ { " and " * t * }
+ if$
+ }
+ if$
+ }
+ 't
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+}
+
+FUNCTION {format.authors}
+{ author empty$
+ { "" }
+ { author format.names }
+ if$
+}
+
+FUNCTION {format.editors}
+{ editor empty$
+ { "" }
+ { editor format.names
+ editor num.names$ #1 >
+ { ", editors" * }
+ { ", editor" * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.title}
+{ title empty$
+ { "" }
+ { url empty$
+ { title "t" change.case$ }
+ { "\href{" url "}{" title "t" change.case$ "}" * * * * }
+ if$ }
+ if$
+}
+
+FUNCTION {n.dashify}
+{ 't :=
+ ""
+ { t empty$ not }
+ { t #1 #1 substring$ "-" =
+ { t #1 #2 substring$ "--" = not
+ { "--" *
+ t #2 global.max$ substring$ 't :=
+ }
+ { { t #1 #1 substring$ "-" = }
+ { "-" *
+ t #2 global.max$ substring$ 't :=
+ }
+ while$
+ }
+ if$
+ }
+ { t #1 #1 substring$ *
+ t #2 global.max$ substring$ 't :=
+ }
+ if$
+ }
+ while$
+}
+
+FUNCTION {format.date}
+{ year empty$
+ { month empty$
+ { "" }
+ { "there's a month but no year in " cite$ * warning$
+ month
+ }
+ if$
+ }
+ { month empty$
+ 'year
+ { month " " * year * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.btitle}
+{ url empty$
+ { title emphasize }
+ { "\href{" url "}{" title emphasize "}" * * * * }
+ if$
+}
+
+FUNCTION {tie.or.space.connect}
+{ duplicate$ text.length$ #3 <
+ { "~" }
+ { " " }
+ if$
+ swap$ * *
+}
+
+FUNCTION {either.or.check}
+{ empty$
+ 'pop$
+ { "can't use both " swap$ * " fields in " * cite$ * warning$ }
+ if$
+}
+
+FUNCTION {format.bvolume}
+{ volume empty$
+ { "" }
+ { "volume" volume tie.or.space.connect
+ series empty$
+ 'skip$
+ { " of " * series emphasize * }
+ if$
+ "volume and number" number either.or.check
+ }
+ if$
+}
+
+FUNCTION {format.number.series}
+{ volume empty$
+ { number empty$
+ { series field.or.null }
+ { output.state mid.sentence =
+ { "number" }
+ { "Number" }
+ if$
+ number tie.or.space.connect
+ series empty$
+ { "there's a number but no series in " cite$ * warning$ }
+ { " in " * series * }
+ if$
+ }
+ if$
+ }
+ { "" }
+ if$
+}
+
+FUNCTION {format.edition}
+{ edition empty$
+ { "" }
+ { output.state mid.sentence =
+ { edition "l" change.case$ " edition" * }
+ { edition "t" change.case$ " edition" * }
+ if$
+ }
+ if$
+}
+
+INTEGERS { multiresult }
+
+FUNCTION {multi.page.check}
+{ 't :=
+ #0 'multiresult :=
+ { multiresult not
+ t empty$ not
+ and
+ }
+ { t #1 #1 substring$
+ duplicate$ "-" =
+ swap$ duplicate$ "," =
+ swap$ "+" =
+ or or
+ { #1 'multiresult := }
+ { t #2 global.max$ substring$ 't := }
+ if$
+ }
+ while$
+ multiresult
+}
+
+FUNCTION {format.pages}
+{ pages empty$
+ { "" }
+ { pages multi.page.check
+ { "pages" pages n.dashify tie.or.space.connect }
+ { "page" pages tie.or.space.connect }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.vol.num.pages}
+{ volume field.or.null
+ number empty$
+ 'skip$
+ { "(" number * ")" * *
+ volume empty$
+ { "there's a number but no volume in " cite$ * warning$ }
+ 'skip$
+ if$
+ }
+ if$
+ pages empty$
+ 'skip$
+ { duplicate$ empty$
+ { pop$ format.pages }
+ { ":" * pages n.dashify * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.chapter.pages}
+{ chapter empty$
+ 'format.pages
+ { type empty$
+ { "chapter" }
+ { type "l" change.case$ }
+ if$
+ chapter tie.or.space.connect
+ pages empty$
+ 'skip$
+ { ", " * format.pages * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.in.ed.booktitle}
+{ booktitle empty$
+ { "" }
+ { editor empty$
+ { "In " booktitle emphasize * }
+ { "In " format.editors * ", " * booktitle emphasize * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {empty.misc.check}
+{ author empty$ title empty$ howpublished empty$
+ month empty$ year empty$ note empty$
+ and and and and and
+ key empty$ not and
+ { "all relevant fields are empty in " cite$ * warning$ }
+ 'skip$
+ if$
+}
+
+FUNCTION {format.thesis.type}
+{ type empty$
+ 'skip$
+ { pop$
+ type "t" change.case$
+ }
+ if$
+}
+
+FUNCTION {format.tr.number}
+{ type empty$
+ { "Technical Report" }
+ 'type
+ if$
+ number empty$
+ { "t" change.case$ }
+ { number tie.or.space.connect }
+ if$
+}
+
+FUNCTION {format.article.crossref}
+{ key empty$
+ { journal empty$
+ { "need key or journal for " cite$ * " to crossref " * crossref *
+ warning$
+ ""
+ }
+ { "In {\em " journal * "\/}" * }
+ if$
+ }
+ { "In " key * }
+ if$
+ " \cite{" * crossref * "}" *
+}
+
+FUNCTION {format.crossref.editor}
+{ editor #1 "{vv~}{ll}" format.name$
+ editor num.names$ duplicate$
+ #2 >
+ { pop$ " et~al." * }
+ { #2 <
+ 'skip$
+ { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+ { " et~al." * }
+ { " and " * editor #2 "{vv~}{ll}" format.name$ * }
+ if$
+ }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.book.crossref}
+{ volume empty$
+ { "empty volume in " cite$ * "'s crossref of " * crossref * warning$
+ "In "
+ }
+ { "Volume" volume tie.or.space.connect
+ " of " *
+ }
+ if$
+ editor empty$
+ editor field.or.null author field.or.null =
+ or
+ { key empty$
+ { series empty$
+ { "need editor, key, or series for " cite$ * " to crossref " *
+ crossref * warning$
+ "" *
+ }
+ { "{\em " * series * "\/}" * }
+ if$
+ }
+ { key * }
+ if$
+ }
+ { format.crossref.editor * }
+ if$
+ " \cite{" * crossref * "}" *
+}
+
+FUNCTION {format.incoll.inproc.crossref}
+{ editor empty$
+ editor field.or.null author field.or.null =
+ or
+ { key empty$
+ { booktitle empty$
+ { "need editor, key, or booktitle for " cite$ * " to crossref " *
+ crossref * warning$
+ ""
+ }
+ { "In {\em " booktitle * "\/}" * }
+ if$
+ }
+ { "In " key * }
+ if$
+ }
+ { "In " format.crossref.editor * }
+ if$
+ " \cite{" * crossref * "}" *
+}
+
+FUNCTION {article}
+{ output.bibitem
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ crossref missing$
+ { journal emphasize "journal" output.check
+ format.vol.num.pages output
+ format.date "year" output.check
+ }
+ { format.article.crossref output.nonnull
+ format.pages output
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {book}
+{ output.bibitem
+ author empty$
+ { format.editors "author and editor" output.check }
+ { format.authors output.nonnull
+ crossref missing$
+ { "author and editor" editor either.or.check }
+ 'skip$
+ if$
+ }
+ if$
+ new.block
+ format.btitle "title" output.check
+ crossref missing$
+ { format.bvolume output
+ new.block
+ format.number.series output
+ new.sentence
+ publisher "publisher" output.check
+ address output
+ }
+ { new.block
+ format.book.crossref output.nonnull
+ }
+ if$
+ format.edition output
+ format.date "year" output.check
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {booklet}
+{ output.bibitem
+ format.authors output
+ new.block
+ format.title "title" output.check
+ howpublished address new.block.checkb
+ howpublished output
+ address output
+ format.date output
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {inbook}
+{ output.bibitem
+ author empty$
+ { format.editors "author and editor" output.check }
+ { format.authors output.nonnull
+ crossref missing$
+ { "author and editor" editor either.or.check }
+ 'skip$
+ if$
+ }
+ if$
+ new.block
+ format.btitle "title" output.check
+ crossref missing$
+ { format.bvolume output
+ format.chapter.pages "chapter and pages" output.check
+ new.block
+ format.number.series output
+ new.sentence
+ publisher "publisher" output.check
+ address output
+ }
+ { format.chapter.pages "chapter and pages" output.check
+ new.block
+ format.book.crossref output.nonnull
+ }
+ if$
+ format.edition output
+ format.date "year" output.check
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {incollection}
+{ output.bibitem
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ crossref missing$
+ { format.in.ed.booktitle "booktitle" output.check
+ format.bvolume output
+ format.number.series output
+ format.chapter.pages output
+ new.sentence
+ publisher "publisher" output.check
+ address output
+ format.edition output
+ format.date "year" output.check
+ }
+ { format.incoll.inproc.crossref output.nonnull
+ format.chapter.pages output
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {inproceedings}
+{ output.bibitem
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ crossref missing$
+ { format.in.ed.booktitle "booktitle" output.check
+ format.bvolume output
+ format.number.series output
+ format.pages output
+ address empty$
+ { organization publisher new.sentence.checkb
+ organization output
+ publisher output
+ format.date "year" output.check
+ }
+ { address output.nonnull
+ format.date "year" output.check
+ new.sentence
+ organization output
+ publisher output
+ }
+ if$
+ }
+ { format.incoll.inproc.crossref output.nonnull
+ format.pages output
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {conference} { inproceedings }
+
+FUNCTION {manual}
+{ output.bibitem
+ author empty$
+ { organization empty$
+ 'skip$
+ { organization output.nonnull
+ address output
+ }
+ if$
+ }
+ { format.authors output.nonnull }
+ if$
+ new.block
+ format.btitle "title" output.check
+ author empty$
+ { organization empty$
+ { address new.block.checka
+ address output
+ }
+ 'skip$
+ if$
+ }
+ { organization address new.block.checkb
+ organization output
+ address output
+ }
+ if$
+ format.edition output
+ format.date output
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {mastersthesis}
+{ output.bibitem
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ "Master's thesis" format.thesis.type output.nonnull
+ school "school" output.check
+ address output
+ format.date "year" output.check
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {misc}
+{ output.bibitem
+ format.authors output
+ title howpublished new.block.checkb
+ format.title output
+ howpublished new.block.checka
+ howpublished output
+ format.date output
+ new.block
+ note output
+ fin.entry
+ empty.misc.check
+}
+
+FUNCTION {phdthesis}
+{ output.bibitem
+ format.authors "author" output.check
+ new.block
+ format.btitle "title" output.check
+ new.block
+ "PhD thesis" format.thesis.type output.nonnull
+ school "school" output.check
+ address output
+ format.date "year" output.check
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {proceedings}
+{ output.bibitem
+ editor empty$
+ { organization output }
+ { format.editors output.nonnull }
+ if$
+ new.block
+ format.btitle "title" output.check
+ format.bvolume output
+ format.number.series output
+ address empty$
+ { editor empty$
+ { publisher new.sentence.checka }
+ { organization publisher new.sentence.checkb
+ organization output
+ }
+ if$
+ publisher output
+ format.date "year" output.check
+ }
+ { address output.nonnull
+ format.date "year" output.check
+ new.sentence
+ editor empty$
+ 'skip$
+ { organization output }
+ if$
+ publisher output
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {techreport}
+{ output.bibitem
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ format.tr.number output.nonnull
+ institution "institution" output.check
+ address output
+ format.date "year" output.check
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {unpublished}
+{ output.bibitem
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ note "note" output.check
+ format.date output
+ fin.entry
+}
+
+FUNCTION {default.type} { misc }
+
+MACRO {jan} {"January"}
+
+MACRO {feb} {"February"}
+
+MACRO {mar} {"March"}
+
+MACRO {apr} {"April"}
+
+MACRO {may} {"May"}
+
+MACRO {jun} {"June"}
+
+MACRO {jul} {"July"}
+
+MACRO {aug} {"August"}
+
+MACRO {sep} {"September"}
+
+MACRO {oct} {"October"}
+
+MACRO {nov} {"November"}
+
+MACRO {dec} {"December"}
+
+MACRO {acmcs} {"ACM Computing Surveys"}
+
+MACRO {acta} {"Acta Informatica"}
+
+MACRO {cacm} {"Communications of the ACM"}
+
+MACRO {ibmjrd} {"IBM Journal of Research and Development"}
+
+MACRO {ibmsj} {"IBM Systems Journal"}
+
+MACRO {ieeese} {"IEEE Transactions on Software Engineering"}
+
+MACRO {ieeetc} {"IEEE Transactions on Computers"}
+
+MACRO {ieeetcad}
+ {"IEEE Transactions on Computer-Aided Design of Integrated Circuits"}
+
+MACRO {ipl} {"Information Processing Letters"}
+
+MACRO {jacm} {"Journal of the ACM"}
+
+MACRO {jcss} {"Journal of Computer and System Sciences"}
+
+MACRO {scp} {"Science of Computer Programming"}
+
+MACRO {sicomp} {"SIAM Journal on Computing"}
+
+MACRO {tocs} {"ACM Transactions on Computer Systems"}
+
+MACRO {tods} {"ACM Transactions on Database Systems"}
+
+MACRO {tog} {"ACM Transactions on Graphics"}
+
+MACRO {toms} {"ACM Transactions on Mathematical Software"}
+
+MACRO {toois} {"ACM Transactions on Office Information Systems"}
+
+MACRO {toplas} {"ACM Transactions on Programming Languages and Systems"}
+
+MACRO {tcs} {"Theoretical Computer Science"}
+
+READ
+
+FUNCTION {sortify}
+{ purify$
+ "l" change.case$
+}
+
+INTEGERS { len }
+
+FUNCTION {chop.word}
+{ 's :=
+ 'len :=
+ s #1 len substring$ =
+ { s len #1 + global.max$ substring$ }
+ 's
+ if$
+}
+
+FUNCTION {sort.format.names}
+{ 's :=
+ #1 'nameptr :=
+ ""
+ s num.names$ 'numnames :=
+ numnames 'namesleft :=
+ { namesleft #0 > }
+ { nameptr #1 >
+ { " " * }
+ 'skip$
+ if$
+ s nameptr "{vv{ } }{ll{ }}{ ff{ }}{ jj{ }}" format.name$ 't :=
+ nameptr numnames = t "others" = and
+ { "et al" * }
+ { t sortify * }
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+}
+
+FUNCTION {sort.format.title}
+{ 't :=
+ "A " #2
+ "An " #3
+ "The " #4 t chop.word
+ chop.word
+ chop.word
+ sortify
+ #1 global.max$ substring$
+}
+
+FUNCTION {author.sort}
+{ author empty$
+ { key empty$
+ { "to sort, need author or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+
+FUNCTION {author.editor.sort}
+{ author empty$
+ { editor empty$
+ { key empty$
+ { "to sort, need author, editor, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+
+FUNCTION {author.organization.sort}
+{ author empty$
+ { organization empty$
+ { key empty$
+ { "to sort, need author, organization, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { "The " #4 organization chop.word sortify }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+
+FUNCTION {editor.organization.sort}
+{ editor empty$
+ { organization empty$
+ { key empty$
+ { "to sort, need editor, organization, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { "The " #4 organization chop.word sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+}
+
+FUNCTION {presort}
+{ type$ "book" =
+ type$ "inbook" =
+ or
+ 'author.editor.sort
+ { type$ "proceedings" =
+ 'editor.organization.sort
+ { type$ "manual" =
+ 'author.organization.sort
+ 'author.sort
+ if$
+ }
+ if$
+ }
+ if$
+ " "
+ *
+ year field.or.null sortify
+ *
+ " "
+ *
+ title field.or.null
+ sort.format.title
+ *
+ #1 entry.max$ substring$
+ 'sort.key$ :=
+}
+
+ITERATE {presort}
+
+SORT
+
+STRINGS { longest.label }
+
+INTEGERS { number.label longest.label.width }
+
+FUNCTION {initialize.longest.label}
+{ "" 'longest.label :=
+ #1 'number.label :=
+ #0 'longest.label.width :=
+}
+
+FUNCTION {longest.label.pass}
+{ number.label int.to.str$ 'label :=
+ number.label #1 + 'number.label :=
+ label width$ longest.label.width >
+ { label 'longest.label :=
+ label width$ 'longest.label.width :=
+ }
+ 'skip$
+ if$
+}
+
+EXECUTE {initialize.longest.label}
+
+ITERATE {longest.label.pass}
+
+FUNCTION {begin.bib}
+{ preamble$ empty$
+ 'skip$
+ { preamble$ write$ newline$ }
+ if$
+ "\begin{thebibliography}{" longest.label * "}" * write$ newline$
+}
+
+EXECUTE {begin.bib}
+
+EXECUTE {init.state.consts}
+
+ITERATE {call.type$}
+
+FUNCTION {end.bib}
+{ newline$
+ "\end{thebibliography}" write$ newline$
+}
+
+EXECUTE {end.bib}
diff --git a/doc/types.tex b/doc/types.tex
new file mode 100644
index 0000000..8a66dcc
--- /dev/null
+++ b/doc/types.tex
@@ -0,0 +1,38 @@
+\begin{figure}[t]
+\begin{mdframed}[backgroundcolor=green!10]
+\begin{lstlisting}
+class virtual ['self] iter : object ('self)
+ constraint 'self =
+ < visit_EAdd : 'env -> expr -> expr -> unit;
+ visit_EConst : 'env -> int -> unit;
+ visit_expr : 'env -> expr -> unit;
+ .. >
+ method visit_EAdd : 'env -> expr -> expr -> unit
+ method visit_EConst : 'env -> int -> unit
+ method visit_expr : 'env -> expr -> unit
+ (* These methods are inherited from [VisitorsRuntime.iter]: *)
+ method private visit_array :
+ 'env 'a. ('env -> 'a -> unit) -> 'env -> 'a array -> unit
+ method private visit_bool : 'env. 'env -> bool -> unit
+ method private visit_bytes : 'env. 'env -> bytes -> unit
+ (* ... and many more ... *)
+end
+\end{lstlisting}
+\end{mdframed}
+\caption{An inferred type for the \iter visitor of \fref{fig:expr00}}
+\label{fig:inferred}
+\end{figure}
+
+\begin{figure}[t]
+\begin{mdframed}[backgroundcolor=green!10]
+\begin{lstlisting}
+class virtual ['self] iter : object ('self)
+ method visit_EAdd : 'monomorphic. 'env -> expr -> expr -> unit
+ method visit_EConst : 'monomorphic. 'env -> int -> unit
+ method visit_expr : 'monomorphic. 'env -> expr -> unit
+end
+\end{lstlisting}
+\end{mdframed}
+\caption{A simplified type for the \iter visitor of \fref{fig:expr00}}
+\label{fig:simplified}
+\end{figure}
diff --git a/doc/version.tex b/doc/version.tex
new file mode 100644
index 0000000..32d6e86
--- /dev/null
+++ b/doc/version.tex
@@ -0,0 +1 @@
+\gdef\visitorsversion{20210608}
diff --git a/dune b/dune
new file mode 100644
index 0000000..e0d7b7d
--- /dev/null
+++ b/dune
@@ -0,0 +1,5 @@
+(install
+ (files Makefile.preprocess)
+ (section lib)
+ (package visitors)
+)
diff --git a/dune-project b/dune-project
new file mode 100644
index 0000000..5b5e1ff
--- /dev/null
+++ b/dune-project
@@ -0,0 +1,12 @@
+(lang dune 2.0)
+(name visitors)
+(version 20210608)
+(package
+ (name visitors)
+)
+(package
+ (name visitors.runtime)
+)
+(package
+ (name visitors.ppx)
+)
diff --git a/runtime/Makefile b/runtime/Makefile
new file mode 100644
index 0000000..441cb57
--- /dev/null
+++ b/runtime/Makefile
@@ -0,0 +1,3 @@
+.PHONY: all
+all:
+ @ make -C .. $@
diff --git a/runtime/VisitorsRuntime.ml b/runtime/VisitorsRuntime.ml
new file mode 100644
index 0000000..04d2ba5
--- /dev/null
+++ b/runtime/VisitorsRuntime.ml
@@ -0,0 +1,1139 @@
+(* This file provides useful / reasonable visitor methods for many of the
+ built-in types of OCaml. *)
+
+(* The classes defined in this file are automatically inherited by
+ auto-generated visitors. If this is not desired, this behavior can be
+ turned off at generation time by specifying [nude = true]. *)
+
+(* Some of the code in this file can be (or has been) auto-generated by
+ the [visitors] package itself: see [test/VisitorsRuntimeBootstrap].
+ To avoid a complicated process and to facilitate code review, we
+ keep this code under manual control in this file. *)
+
+(* -------------------------------------------------------------------------- *)
+
+(* For compatibility with OCaml 4.02, we take the type [('a, 'b) result] from
+ the package [result]. This type appeared in the standard library in OCaml
+ 4.03. *)
+
+open Result
+
+(* -------------------------------------------------------------------------- *)
+
+(* [array_equal eq xs1 xs2] tests whether the arrays [xs1] and [xs2] have the
+ same components. The arrays must have the same length. The components are
+ compared using [eq]. *)
+
+let rec array_equal eq i n xs1 xs2 =
+ i = n ||
+ let x1 = Array.unsafe_get xs1 i
+ and x2 = Array.unsafe_get xs2 i in
+ eq x1 x2 && array_equal eq (i + 1) n xs1 xs2
+
+let array_equal eq xs1 xs2 =
+ let n = Array.length xs1 in
+ assert (Array.length xs2 = n);
+ array_equal eq 0 n xs1 xs2
+
+(* -------------------------------------------------------------------------- *)
+
+(* An exception used at arity 2 and above. *)
+
+exception StructuralMismatch
+
+let fail () =
+ raise StructuralMismatch
+
+let wrap f t =
+ try
+ f t;
+ true
+ with StructuralMismatch ->
+ false
+
+let wrap2 f t1 t2 =
+ try
+ f t1 t2;
+ true
+ with StructuralMismatch ->
+ false
+
+(* -------------------------------------------------------------------------- *)
+
+(* A virtual base class for monoids. *)
+
+class virtual ['s] monoid = object
+ method private virtual zero: 's
+ method private virtual plus: 's -> 's -> 's
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* Common monoids. *)
+
+class ['s] addition_monoid = object
+ inherit ['s] monoid
+ method private zero = 0
+ method private plus = (+)
+end
+
+class ['s] unit_monoid = object
+ inherit ['s] monoid
+ method private zero = ()
+ method private plus () () = ()
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* Visitor methods for the primitive types. *)
+
+(* Must the methods below be declared polymorphic in ['env]? The fact is, they
+ ARE polymorphic in ['env], because they do not extend it or look it up.
+
+ By declaring them polymorphic, we gain in generality: e.g., [visit_list]
+ can be called by two visitor methods which happen to have different types
+ of environments. (This happens in alphaLib, where visitor methods for terms
+ and patterns manipulate different types of environments.)
+
+ However, by declaring them polymorphic, we also lose some generality, as we
+ PREVENT users from overriding these methods with code that extends or looks
+ up the environment.
+
+ Here, it seems reasonable to take both the gain and the loss, and declare
+ these methods polymorphic.
+
+ We could give the user a choice by providing multiple base classes, but that
+ would messy. Note that, when using [@@deriving visitors { ... }], the user
+ does have a choice whether the generated methods should be polymorphic in
+ ['env]. *)
+
+(* -------------------------------------------------------------------------- *)
+
+(* [iter] *)
+
+class ['self] iter = object (self)
+
+ method private visit_array: 'env 'a .
+ ('env -> 'a -> unit) -> 'env -> 'a array -> unit
+ = fun f env xs ->
+ (* For speed, we inline [Array.iter]. Chances are, we save a closure
+ allocation, as using [Array.iter] would require us to build [f env]. *)
+ for i = 0 to Array.length xs - 1 do
+ f env (Array.unsafe_get xs i)
+ done
+
+ method private visit_bool: 'env .
+ 'env -> bool -> unit
+ = fun _ _ -> ()
+
+ method private visit_bytes: 'env .
+ 'env -> bytes -> unit
+ = fun _ _ -> ()
+
+ method private visit_char: 'env .
+ 'env -> char -> unit
+ = fun _ _ -> ()
+
+ method private visit_float: 'env .
+ 'env -> float -> unit
+ = fun _ _ -> ()
+
+ method private visit_int: 'env .
+ 'env -> int -> unit
+ = fun _ _ -> ()
+
+ method private visit_int32: 'env .
+ 'env -> int32 -> unit
+ = fun _ _ -> ()
+
+ method private visit_int64: 'env .
+ 'env -> int64 -> unit
+ = fun _ _ -> ()
+
+ method private visit_lazy_t: 'env 'a .
+ ('env -> 'a -> unit) -> 'env -> 'a Lazy.t -> unit
+ = fun f env (lazy x) ->
+ f env x
+
+ method private visit_list: 'env 'a .
+ ('env -> 'a -> unit) -> 'env -> 'a list -> unit
+ = fun f env xs ->
+ match xs with
+ | [] ->
+ ()
+ | x :: xs ->
+ f env x;
+ self # visit_list f env xs
+
+ method private visit_nativeint: 'env .
+ 'env -> nativeint -> unit
+ = fun _ _ -> ()
+
+ method private visit_option: 'env 'a .
+ ('env -> 'a -> unit) -> 'env -> 'a option -> unit
+ = fun f env ox ->
+ match ox with
+ | None ->
+ ()
+ | Some x ->
+ f env x
+
+ method private visit_ref: 'env 'a .
+ ('env -> 'a -> unit) -> 'env -> 'a ref -> unit
+ = fun f env rx ->
+ f env !rx
+
+ method private visit_result: 'env 'a 'e.
+ ('env -> 'a -> unit) ->
+ ('env -> 'e -> unit) ->
+ 'env -> ('a, 'e) result -> unit
+ = fun f g env r ->
+ match r with
+ | Ok a -> f env a
+ | Error b -> g env b
+
+ method private visit_string: 'env .
+ 'env -> string -> unit
+ = fun _ _ -> ()
+
+ method private visit_unit: 'env .
+ 'env -> unit -> unit
+ = fun _ _ -> ()
+
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* [map] *)
+
+class ['self] map = object (self)
+
+ method private visit_array: 'env 'a 'b .
+ ('env -> 'a -> 'b) -> 'env -> 'a array -> 'b array
+ = fun f env xs ->
+ Array.map (f env) xs
+ (* We could in principle inline [Array.map] so as to avoid allocating
+ the closure [f env]. That would be a bit painful, though. Anyway,
+ in [flambda] mode, the compiler might be able to do that for us. *)
+
+ method private visit_bool: 'env .
+ 'env -> bool -> bool
+ = fun _ x -> x
+
+ method private visit_bytes: 'env .
+ 'env -> bytes -> bytes
+ = fun _ x -> x
+
+ method private visit_char: 'env .
+ 'env -> char -> char
+ = fun _ x -> x
+
+ method private visit_float: 'env .
+ 'env -> float -> float
+ = fun _ x -> x
+
+ method private visit_int: 'env .
+ 'env -> int -> int
+ = fun _ x -> x
+
+ method private visit_int32: 'env .
+ 'env -> int32 -> int32
+ = fun _ x -> x
+
+ method private visit_int64: 'env .
+ 'env -> int64 -> int64
+ = fun _ x -> x
+
+ method private visit_lazy_t: 'env 'a 'b .
+ ('env -> 'a -> 'b) -> 'env -> 'a Lazy.t -> 'b Lazy.t
+ = fun f env thx ->
+ (* We seem to have two options: either force the suspension now
+ and rebuild a trivial suspension, or build now a suspension
+ that will perform the traversal when forced. We choose the
+ latter, which seems more interesting. If this is not the
+ desired behavior, it can of course be overridden. *)
+ lazy (f env (Lazy.force thx))
+
+ method private visit_list: 'env 'a 'b .
+ ('env -> 'a -> 'b) -> 'env -> 'a list -> 'b list
+ = fun f env xs ->
+ match xs with
+ | [] ->
+ []
+ | x :: xs ->
+ let x = f env x in
+ x :: self # visit_list f env xs
+
+ method private visit_nativeint: 'env .
+ 'env -> nativeint -> nativeint
+ = fun _ x -> x
+
+ method private visit_option: 'env 'a 'b .
+ ('env -> 'a -> 'b) -> 'env -> 'a option -> 'b option
+ = fun f env ox ->
+ match ox with
+ | None ->
+ None
+ | Some x ->
+ Some (f env x)
+
+ method private visit_ref: 'env 'a 'b .
+ ('env -> 'a -> 'b) -> 'env -> 'a ref -> 'b ref
+ = fun f env rx ->
+ ref (f env !rx)
+
+ method private visit_result: 'env 'a 'b 'e 'f .
+ ('env -> 'a -> 'b) ->
+ ('env -> 'e -> 'f) ->
+ 'env -> ('a, 'e) result -> ('b, 'f) result
+ = fun f g env r ->
+ match r with
+ | Ok a -> Ok (f env a)
+ | Error b -> Error (g env b)
+
+ method private visit_string: 'env .
+ 'env -> string -> string
+ = fun _ x -> x
+
+ method private visit_unit: 'env .
+ 'env -> unit -> unit
+ = fun _ x -> x
+
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* [endo] *)
+
+class ['self] endo = object (self)
+
+ (* We might wish to inherit from [map] and override only those methods where
+ a physical equality check is needed. Yet, we cannot do that, because some
+ methods, like [visit_list], have more restrictive types in this class than
+ in the class [map]. *)
+
+ (* It may seem fishy to use an [endo] visitor at type [array], but one never
+ knows -- maybe the user wants this. Maybe she is using an array as an
+ immutable data structure. *)
+
+ method private visit_array: 'env 'a .
+ ('env -> 'a -> 'a) -> 'env -> 'a array -> 'a array
+ = fun f env xs ->
+ let xs' = Array.map (f env) xs in
+ if array_equal (==) xs xs' then xs else xs'
+
+ method private visit_bool: 'env .
+ 'env -> bool -> bool
+ = fun _ x -> x
+
+ method private visit_bytes: 'env .
+ 'env -> bytes -> bytes
+ = fun _ x -> x
+
+ method private visit_char:'env .
+ 'env -> char -> char
+ = fun _ x -> x
+
+ method private visit_float: 'env .
+ 'env -> float -> float
+ = fun _ x -> x
+
+ method private visit_int: 'env .
+ 'env -> int -> int
+ = fun _ x -> x
+
+ method private visit_int32: 'env .
+ 'env -> int32 -> int32
+ = fun _ x -> x
+
+ method private visit_int64: 'env .
+ 'env -> int64 -> int64
+ = fun _ x -> x
+
+ method private visit_lazy_t : 'env 'a .
+ ('env -> 'a -> 'a) -> 'env -> 'a Lazy.t -> 'a Lazy.t
+ = fun f env thx ->
+ (* We could use the same code as in [map], which does not preserve sharing.
+ Or, we can force the suspension now, compute [x'], and if [x] and
+ [x'] coincide, then we can return the original suspension (now
+ forced), so as to preserve sharing. We choose the latter behavior. If
+ this is not the desired behavior, it can of course be overridden. *)
+ let x = Lazy.force thx in
+ let x' = f env x in
+ if x == x' then thx else lazy x'
+
+ method private visit_list: 'env 'a .
+ ('env -> 'a -> 'a) -> 'env -> 'a list -> 'a list
+ = fun f env this ->
+ match this with
+ | [] ->
+ []
+ | x :: xs ->
+ let x' = f env x in
+ let xs' = self # visit_list f env xs in
+ if x == x' && xs == xs' then
+ this
+ else
+ x' :: xs'
+
+ method private visit_nativeint: 'env .
+ 'env -> nativeint -> nativeint
+ = fun _ x -> x
+
+ method private visit_option: 'env 'a .
+ ('env -> 'a -> 'a) -> 'env -> 'a option -> 'a option
+ = fun f env ox ->
+ match ox with
+ | None ->
+ None
+ | Some x ->
+ let x' = f env x in
+ if x == x' then
+ ox
+ else
+ Some x'
+
+ (* It probably does not make sense to use an [endo] visitor at type
+ [ref], but one never knows -- maybe the user wants this. Anyway,
+ it is consistent with the behavior of [endo] visitors at mutable
+ record types. *)
+
+ method private visit_ref: 'env 'a .
+ ('env -> 'a -> 'a) -> 'env -> 'a ref -> 'a ref
+ = fun f env rx ->
+ let x = !rx in
+ let x' = f env x in
+ if x == x' then
+ rx
+ else
+ ref x'
+
+ method private visit_result: 'env 'a 'e .
+ ('env -> 'a -> 'a) ->
+ ('env -> 'e -> 'e) ->
+ 'env -> ('a, 'e) result -> ('a, 'e) result
+ = fun f g env r ->
+ match r with
+ | Ok a ->
+ let a' = f env a in
+ if a == a' then r else Ok a'
+ | Error b ->
+ let b' = g env b in
+ if b == b' then r else Error b'
+
+ method private visit_string: 'env .
+ 'env -> string -> string
+ = fun _ x -> x
+
+ method private visit_unit: 'env .
+ 'env -> unit -> unit
+ = fun _ x -> x
+
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* [reduce] *)
+
+(* For arrays and lists, we use [fold_left] instead of a natural (bottom-up)
+ fold. The order in which the elements are traversed is the same either way
+ (namely, left-to-right) but the manner in which the [plus] operations are
+ associated is not the same, so the [plus] operator should be associative.
+
+ We could go back to a natural fold, but we would lose tail recursion. *)
+
+class virtual ['self] reduce = object (self : 'self)
+
+ inherit ['s] monoid
+
+ method private visit_array: 'env 'a .
+ ('env -> 'a -> 's) -> 'env -> 'a array -> 's
+ = fun f env xs ->
+ Array.fold_left (fun s x -> self#plus s (f env x)) self#zero xs
+ (* We might wish to inline [Array.fold_left] and save a closure
+ allocation. That said, in flambda mode, the compiler might be
+ able to do that automatically. *)
+
+ method private visit_bool: 'env .
+ 'env -> bool -> 's
+ = fun _env _ -> self#zero
+
+ method private visit_bytes: 'env .
+ 'env -> bytes -> 's
+ = fun _env _ -> self#zero
+
+ method private visit_char: 'env .
+ 'env -> char -> 's
+ = fun _env _ -> self#zero
+
+ method private visit_float: 'env .
+ 'env -> float -> 's
+ = fun _env _ -> self#zero
+
+ method private visit_int: 'env .
+ 'env -> int -> 's
+ = fun _env _ -> self#zero
+
+ method private visit_int32: 'env .
+ 'env -> int32 -> 's
+ = fun _env _ -> self#zero
+
+ method private visit_int64: 'env .
+ 'env -> int64 -> 's
+ = fun _env _ -> self#zero
+
+ method private visit_lazy_t: 'env 'a .
+ ('env -> 'a -> 's) -> 'env -> 'a Lazy.t -> 's
+ = fun f env (lazy x) ->
+ f env x
+
+ method private visit_list: 'env 'a .
+ ('env -> 'a -> 's) -> 'env -> 'a list -> 's
+ = fun f env xs ->
+ self # list_fold_left f env self#zero xs
+ (* The above line is equivalent to the following: *)
+ (* List.fold_left (fun s x -> self#plus s (f env x)) self#zero xs *)
+ (* By using the auxiliary method [list_fold_left] instead of calling
+ the library function [List.fold_left], we save a closure allocation,
+ at least in non-flambda mode. A micro-benchmark shows no performance
+ impact, either way. *)
+
+ method private list_fold_left: 'env 'a .
+ ('env -> 'a -> 's) -> 'env -> 's -> 'a list -> 's
+ = fun f env s xs ->
+ match xs with
+ | [] ->
+ s
+ | x :: xs ->
+ let s = self#plus s (f env x) in
+ self # list_fold_left f env s xs
+
+ method private visit_nativeint: 'env .
+ 'env -> nativeint -> 's
+ = fun _env _ -> self#zero
+
+ method private visit_option: 'env 'a .
+ ('env -> 'a -> 's) -> 'env -> 'a option -> 's
+ = fun f env ox ->
+ match ox with
+ | Some x ->
+ f env x
+ | None ->
+ self#zero
+
+ method private visit_ref: 'env 'a .
+ ('env -> 'a -> 's) -> 'env -> 'a ref -> 's
+ = fun f env rx ->
+ f env !rx
+
+ method private visit_result: 'env 'a 'e .
+ ('env -> 'a -> 's) ->
+ ('env -> 'e -> 's) ->
+ 'env -> ('a, 'e) result -> 's
+ = fun f g env r ->
+ match r with
+ | Ok a ->
+ f env a
+ | Error b ->
+ g env b
+
+ method private visit_string: 'env .
+ 'env -> string -> 's
+ = fun _env _ -> self#zero
+
+ method private visit_unit: 'env .
+ 'env -> unit -> 's
+ = fun _env _ -> self#zero
+
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* [mapreduce] *)
+
+class virtual ['self] mapreduce = object (self : 'self)
+
+ inherit ['s] monoid
+
+ method private visit_array: 'env 'a 'b .
+ ('env -> 'a -> 'b * 's) -> 'env -> 'a array -> 'b array * 's
+ = fun f env xs ->
+ let s = ref self#zero in
+ let xs =
+ Array.map (fun x ->
+ let x, sx = f env x in
+ s := self#plus !s sx;
+ x
+ ) xs
+ in
+ xs, !s
+
+ method private visit_bool: 'env .
+ 'env -> bool -> bool * 's
+ = fun _ x -> x, self#zero
+
+ method private visit_bytes: 'env .
+ 'env -> bytes -> bytes * 's
+ = fun _ x -> x, self#zero
+
+ method private visit_char: 'env .
+ 'env -> char -> char * 's
+ = fun _ x -> x, self#zero
+
+ method private visit_float: 'env .
+ 'env -> float -> float * 's
+ = fun _ x -> x, self#zero
+
+ method private visit_int: 'env .
+ 'env -> int -> int * 's
+ = fun _ x -> x, self#zero
+
+ method private visit_int32: 'env .
+ 'env -> int32 -> int32 * 's
+ = fun _ x -> x, self#zero
+
+ method private visit_int64: 'env .
+ 'env -> int64 -> int64 * 's
+ = fun _ x -> x, self#zero
+
+ method private visit_lazy_t: 'env 'a 'b .
+ ('env -> 'a -> 'b * 's) -> 'env -> 'a Lazy.t -> 'b Lazy.t * 's
+ = fun f env (lazy x) ->
+ (* Because we must compute a summary now, it seems that we have to
+ force the suspension now. One should be aware that this is not
+ the same behavior as the one we chose in the class [map]. *)
+ let y, s = f env x in
+ lazy y, s
+
+ method private visit_list: 'env 'a 'b .
+ ('env -> 'a -> 'b * 's) -> 'env -> 'a list -> 'b list * 's
+ = fun f env xs ->
+ match xs with
+ | [] ->
+ [], self#zero
+ | x :: xs ->
+ let x, sx = f env x in
+ let xs, sxs = self # visit_list f env xs in
+ x :: xs, self#plus sx sxs
+ (* This is not the same strategy as in the class [reduce], where we
+ used an accumulator and a tail-recursive left fold. Here, we are
+ using a right fold. The order in which list elements are visited
+ is left-to-right in both cases, but the tree of [self#plus] ops
+ is not balanced the same way. *)
+
+ method private visit_nativeint: 'env .
+ 'env -> nativeint -> nativeint * 's
+ = fun _ x -> x, self#zero
+
+ method private visit_option: 'env 'a_0 'a_1 .
+ ('env -> 'a_0 -> 'a_1 * 's) ->
+ 'env -> 'a_0 option -> 'a_1 option * 's
+ = fun visit_'a env this ->
+ match this with
+ | None ->
+ None, self#zero
+ | Some c0 ->
+ let r0, s0 = visit_'a env c0 in
+ Some r0, s0
+
+ method private visit_ref: 'env 'a_0 'a_1 .
+ ('env -> 'a_0 -> 'a_1 * 's) ->
+ 'env -> 'a_0 ref -> 'a_1 ref * 's
+ = fun visit_'a env this ->
+ let r0, s0 = visit_'a env !this in
+ ref r0, s0
+
+ method private visit_result: 'env 'a_0 'a_1 'b_0 'b_1 .
+ ('env -> 'a_0 -> 'a_1 * 's) ->
+ ('env -> 'b_0 -> 'b_1 * 's) ->
+ 'env -> ('a_0, 'b_0) result -> ('a_1, 'b_1) result * 's
+ = fun visit_'a visit_'b env this ->
+ match this with
+ | Ok c0 ->
+ let r0, s0 = visit_'a env c0 in
+ Ok r0, s0
+ | Error c0 ->
+ let r0, s0 = visit_'b env c0 in
+ Error r0, s0
+
+ method private visit_string: 'env .
+ 'env -> string -> string * 's
+ = fun _ x -> x, self#zero
+
+ method private visit_unit: 'env .
+ 'env -> unit -> unit * 's
+ = fun _ x -> x, self#zero
+
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* [fold] *)
+
+class ['self] fold = object (_self)
+
+ (* No methods are provided, as we do not wish to fix the types of these
+ methods. It is up to the user to inherit from a class that defines
+ appropriate methods. Note that [VisitorsRuntime.map] is likely to be
+ appropriate in many situations. *)
+
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* [iter2] *)
+
+class ['self] iter2 = object (self)
+
+ method private visit_array: 'env 'a 'b .
+ ('env -> 'a -> 'b -> unit) -> 'env -> 'a array -> 'b array -> unit
+ = fun f env xs1 xs2 ->
+ (* We inline [Array.iter2]. *)
+ if Array.length xs1 = Array.length xs2 then
+ for i = 0 to Array.length xs1 - 1 do
+ f env (Array.unsafe_get xs1 i) (Array.unsafe_get xs2 i)
+ done
+ else
+ fail()
+
+ method private visit_bool: 'env .
+ 'env -> bool -> bool -> unit
+ = fun _ x1 x2 -> if x1 = x2 then () else fail()
+
+ method private visit_bytes: 'env .
+ 'env -> bytes -> bytes -> unit
+ = fun _ x1 x2 -> if x1 = x2 then () else fail()
+
+ method private visit_char: 'env .
+ 'env -> char -> char -> unit
+ = fun _ x1 x2 -> if x1 = x2 then () else fail()
+
+ method private visit_float: 'env .
+ 'env -> float -> float -> unit
+ = fun _ x1 x2 -> if x1 = x2 then () else fail()
+
+ method private visit_int: 'env .
+ 'env -> int -> int -> unit
+ = fun _ x1 x2 -> if x1 = x2 then () else fail()
+
+ method private visit_int32: 'env .
+ 'env -> int32 -> int32 -> unit
+ = fun _ x1 x2 -> if x1 = x2 then () else fail()
+
+ method private visit_int64: 'env .
+ 'env -> int64 -> int64 -> unit
+ = fun _ x1 x2 -> if x1 = x2 then () else fail()
+
+ method private visit_lazy_t: 'env 'a 'b .
+ ('env -> 'a -> 'b -> unit) -> 'env -> 'a Lazy.t -> 'b Lazy.t -> unit
+ = fun f env (lazy x1) (lazy x2) ->
+ f env x1 x2
+
+ method private visit_list: 'env 'a 'b .
+ ('env -> 'a -> 'b -> unit) -> 'env -> 'a list -> 'b list -> unit
+ = fun f env xs1 xs2 ->
+ match xs1, xs2 with
+ | [], [] ->
+ ()
+ | x1 :: xs1, x2 :: xs2 ->
+ f env x1 x2;
+ self # visit_list f env xs1 xs2
+ | _, _ ->
+ fail()
+
+ method private visit_nativeint: 'env .
+ 'env -> nativeint -> nativeint -> unit
+ = fun _ x1 x2 -> if x1 = x2 then () else fail()
+
+ method private visit_option: 'env 'a 'b .
+ ('env -> 'a -> 'b -> unit) -> 'env -> 'a option -> 'b option -> unit
+ = fun f env ox1 ox2 ->
+ match ox1, ox2 with
+ | None, None ->
+ ()
+ | Some x1, Some x2 ->
+ f env x1 x2
+ | _, _ ->
+ fail()
+
+ method private visit_ref: 'env 'a 'b .
+ ('env -> 'a -> 'b -> unit) -> 'env -> 'a ref -> 'b ref -> unit
+ = fun f env rx1 rx2 ->
+ f env !rx1 !rx2
+
+ method private visit_result: 'env 'a 'b 'e 'f .
+ ('env -> 'a -> 'b -> unit) ->
+ ('env -> 'e -> 'f -> unit) ->
+ 'env -> ('a, 'e) result -> ('b, 'f) result -> unit
+ = fun f g env r1 r2 ->
+ match r1, r2 with
+ | Ok a1, Ok a2 -> f env a1 a2
+ | Error b1, Error b2 -> g env b1 b2
+ | _, _ -> fail()
+
+ method private visit_string: 'env .
+ 'env -> string -> string -> unit
+ = fun _ x1 x2 -> if x1 = x2 then () else fail()
+
+ method private visit_unit: 'env .
+ 'env -> unit -> unit -> unit
+ = fun _ _x1 _x2 -> ()
+
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* [map2] *)
+
+class ['self] map2 = object (self)
+
+ method private visit_array: 'env 'a 'b 'c .
+ ('env -> 'a -> 'b -> 'c) -> 'env -> 'a array -> 'b array -> 'c array
+ = fun f env xs1 xs2 ->
+ if Array.length xs1 = Array.length xs2 then
+ Array.mapi (fun i x1 -> f env x1 xs2.(i)) xs1
+ (* Array.map2 (f env) xs1 xs2 *)
+ (* We avoid [Array.map2] because it does not exist in OCaml 4.02. *)
+ else
+ fail()
+
+ method private visit_bool: 'env .
+ 'env -> bool -> bool -> bool
+ = fun _ x1 x2 -> if x1 = x2 then x1 else fail()
+
+ method private visit_bytes: 'env .
+ 'env -> bytes -> bytes -> bytes
+ = fun _ x1 x2 -> if x1 = x2 then x1 else fail()
+
+ method private visit_char: 'env .
+ 'env -> char -> char -> char
+ = fun _ x1 x2 -> if x1 = x2 then x1 else fail()
+
+ method private visit_float: 'env .
+ 'env -> float -> float -> float
+ = fun _ x1 x2 -> if x1 = x2 then x1 else fail()
+
+ method private visit_int: 'env .
+ 'env -> int -> int -> int
+ = fun _ x1 x2 -> if x1 = x2 then x1 else fail()
+
+ method private visit_int32: 'env .
+ 'env -> int32 -> int32 -> int32
+ = fun _ x1 x2 -> if x1 = x2 then x1 else fail()
+
+ method private visit_int64: 'env .
+ 'env -> int64 -> int64 -> int64
+ = fun _ x1 x2 -> if x1 = x2 then x1 else fail()
+
+ method private visit_lazy_t: 'env 'a 'b 'c .
+ ('env -> 'a -> 'b -> 'c) -> 'env -> 'a Lazy.t -> 'b Lazy.t -> 'c Lazy.t
+ = fun f env thx1 thx2 ->
+ (* As in [map]. *)
+ lazy (f env (Lazy.force thx1) (Lazy.force thx2))
+
+ method private visit_list: 'env 'a 'b 'c .
+ ('env -> 'a -> 'b -> 'c) -> 'env -> 'a list -> 'b list -> 'c list
+ = fun f env xs1 xs2 ->
+ match xs1, xs2 with
+ | [], [] ->
+ []
+ | x1 :: xs1, x2 :: xs2 ->
+ let x = f env x1 x2 in
+ x :: self # visit_list f env xs1 xs2
+ | _, _ ->
+ fail()
+
+ method private visit_nativeint: 'env .
+ 'env -> nativeint -> nativeint -> nativeint
+ = fun _ x1 x2 -> if x1 = x2 then x1 else fail()
+
+ method private visit_option: 'env 'a 'b 'c .
+ ('env -> 'a -> 'b -> 'c) -> 'env -> 'a option -> 'b option -> 'c option
+ = fun f env ox1 ox2 ->
+ match ox1, ox2 with
+ | None, None ->
+ None
+ | Some x1, Some x2 ->
+ let x = f env x1 x2 in
+ Some x
+ | _, _ ->
+ fail()
+
+ method private visit_ref: 'env 'a 'b 'c .
+ ('env -> 'a -> 'b -> 'c) -> 'env -> 'a ref -> 'b ref -> 'c ref
+ = fun f env rx1 rx2 ->
+ ref (f env !rx1 !rx2)
+
+ method private visit_result: 'env 'a 'b 'c 'e 'f 'g .
+ ('env -> 'a -> 'b -> 'c) ->
+ ('env -> 'e -> 'f -> 'g) ->
+ 'env -> ('a, 'e) result -> ('b, 'f) result -> ('c, 'g) result
+ = fun f g env r1 r2 ->
+ match r1, r2 with
+ | Ok a1, Ok a2 -> Ok (f env a1 a2)
+ | Error b1, Error b2 -> Error (g env b1 b2)
+ | _, _ -> fail()
+
+ method private visit_string: 'env .
+ 'env -> string -> string -> string
+ = fun _ x1 x2 -> if x1 = x2 then x1 else fail()
+
+ method private visit_unit: 'env .
+ 'env -> unit -> unit -> unit
+ = fun _ _x1 _x2 -> ()
+
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* [reduce2] *)
+
+class virtual ['self] reduce2 = object (self : 'self)
+
+ inherit ['s] monoid
+
+ method private visit_array: 'env 'a 'b .
+ ('env -> 'a -> 'b -> 's) -> 'env -> 'a array -> 'b array -> 's
+ = fun f env xs1 xs2 ->
+ (* OCaml does not offer [Array.fold_left2], so we use [Array.iter2],
+ which we inline. *)
+ if Array.length xs1 = Array.length xs2 then
+ let s = ref self#zero in
+ for i = 0 to Array.length xs1 - 1 do
+ let x1 = Array.unsafe_get xs1 i
+ and x2 = Array.unsafe_get xs2 i in
+ s := self#plus !s (f env x1 x2)
+ done;
+ !s
+ else
+ fail()
+
+ method private visit_bool: 'env .
+ 'env -> bool -> bool -> 's
+ = fun _env x1 x2 ->
+ if x1 = x2 then self#zero else fail()
+
+ method private visit_bytes: 'env .
+ 'env -> bytes -> bytes -> 's
+ = fun _env x1 x2 ->
+ if x1 = x2 then self#zero else fail()
+
+ method private visit_char: 'env .
+ 'env -> char -> char -> 's
+ = fun _env x1 x2 ->
+ if x1 = x2 then self#zero else fail()
+
+ method private visit_float: 'env .
+ 'env -> float -> float -> 's
+ = fun _env x1 x2 ->
+ if x1 = x2 then self#zero else fail()
+
+ method private visit_int: 'env .
+ 'env -> int -> int -> 's
+ = fun _env x1 x2 ->
+ if x1 = x2 then self#zero else fail()
+
+ method private visit_int32: 'env .
+ 'env -> int32 -> int32 -> 's
+ = fun _env x1 x2 ->
+ if x1 = x2 then self#zero else fail()
+
+ method private visit_int64: 'env .
+ 'env -> int64 -> int64 -> 's
+ = fun _env x1 x2 ->
+ if x1 = x2 then self#zero else fail()
+
+ method private visit_lazy_t: 'env 'a 'b .
+ ('env -> 'a -> 'b -> 's) -> 'env -> 'a Lazy.t -> 'b Lazy.t -> 's
+ = fun f env (lazy x1) (lazy x2) ->
+ f env x1 x2
+
+ method private visit_list: 'env 'a 'b .
+ ('env -> 'a -> 'b -> 's) -> 'env -> 'a list -> 'b list -> 's
+ = fun f env xs1 xs2 ->
+ if List.length xs1 = List.length xs2 then
+ List.fold_left2 (fun s x1 x2 -> self#plus s (f env x1 x2)) self#zero xs1 xs2
+ else
+ fail()
+
+ method private visit_nativeint: 'env .
+ 'env -> nativeint -> nativeint -> 's
+ = fun _env x1 x2 ->
+ if x1 = x2 then self#zero else fail()
+
+ method private visit_option: 'env 'a 'b .
+ ('env -> 'a -> 'b -> 's) -> 'env -> 'a option -> 'b option -> 's
+ = fun f env ox1 ox2 ->
+ match ox1, ox2 with
+ | Some x1, Some x2 ->
+ f env x1 x2
+ | None, None ->
+ self#zero
+ | Some _, None
+ | None, Some _ ->
+ fail()
+
+ method private visit_ref: 'env 'a 'b .
+ ('env -> 'a -> 'b -> 's) -> 'env -> 'a ref -> 'b ref -> 's
+ = fun f env rx1 rx2 ->
+ f env !rx1 !rx2
+
+ method private visit_result: 'env 'a 'b 'e 'f .
+ ('env -> 'a -> 'b -> 's) ->
+ ('env -> 'e -> 'f -> 's) ->
+ 'env -> ('a, 'e) result -> ('b, 'f) result -> 's
+ = fun f g env r1 r2 ->
+ match r1, r2 with
+ | Ok a1, Ok a2 ->
+ f env a1 a2
+ | Error b1, Error b2 ->
+ g env b1 b2
+ | Ok _, Error _
+ | Error _, Ok _ ->
+ fail()
+
+ method private visit_string: 'env .
+ 'env -> string -> string -> 's
+ = fun _env x1 x2 ->
+ if x1 = x2 then self#zero else fail()
+
+ method private visit_unit: 'env .
+ 'env -> unit -> unit -> 's
+ = fun _env () () ->
+ self#zero
+
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* [mapreduce2] *)
+
+class virtual ['self] mapreduce2 = object (self)
+
+ inherit ['s] monoid
+
+ method private visit_array: 'env 'a 'b 'c .
+ ('env -> 'a -> 'b -> 'c * 's) -> 'env -> 'a array -> 'b array -> 'c array * 's
+ = fun f env xs1 xs2 ->
+ let n1 = Array.length xs1
+ and n2 = Array.length xs2 in
+ if n1 = n2 then
+ let s = ref self#zero in
+ let xs = Array.init n1 (fun i ->
+ let x1 = Array.unsafe_get xs1 i
+ and x2 = Array.unsafe_get xs2 i in
+ let x, sx = f env x1 x2 in
+ s := self#plus !s sx;
+ x
+ ) in
+ xs, !s
+ else
+ fail()
+
+ method private visit_bool: 'env .
+ 'env -> bool -> bool -> bool * 's
+ = fun _ x1 x2 -> if x1 = x2 then x1, self#zero else fail()
+
+ method private visit_bytes: 'env .
+ 'env -> bytes -> bytes -> bytes * 's
+ = fun _ x1 x2 -> if x1 = x2 then x1, self#zero else fail()
+
+ method private visit_char: 'env .
+ 'env -> char -> char -> char * 's
+ = fun _ x1 x2 -> if x1 = x2 then x1, self#zero else fail()
+
+ method private visit_float: 'env .
+ 'env -> float -> float -> float * 's
+ = fun _ x1 x2 -> if x1 = x2 then x1, self#zero else fail()
+
+ method private visit_int: 'env .
+ 'env -> int -> int -> int * 's
+ = fun _ x1 x2 -> if x1 = x2 then x1, self#zero else fail()
+
+ method private visit_int32: 'env .
+ 'env -> int32 -> int32 -> int32 * 's
+ = fun _ x1 x2 -> if x1 = x2 then x1, self#zero else fail()
+
+ method private visit_int64: 'env .
+ 'env -> int64 -> int64 -> int64 * 's
+ = fun _ x1 x2 -> if x1 = x2 then x1, self#zero else fail()
+
+ method private visit_lazy_t: 'env 'a 'b 'c .
+ ('env -> 'a -> 'b -> 'c * 's) -> 'env -> 'a Lazy.t -> 'b Lazy.t -> 'c Lazy.t * 's
+ = fun f env (lazy x1) (lazy x2) ->
+ (* As in [mapreduce]. *)
+ let y, s = f env x1 x2 in
+ lazy y, s
+
+ method private visit_list: 'env 'a_0 'a_1 'a_2 .
+ ('env -> 'a_0 -> 'a_1 -> 'a_2 * 's) ->
+ 'env -> 'a_0 list -> 'a_1 list -> 'a_2 list * 's
+ = fun visit_'a env this_0 this_1 ->
+ match this_0, this_1 with
+ | [], [] ->
+ [], self#zero
+ | c0_0 :: c1_0, c0_1 :: c1_1 ->
+ let r0, s0 = visit_'a env c0_0 c0_1 in
+ let r1, s1 = self#visit_list visit_'a env c1_0 c1_1 in
+ r0 :: r1, self#plus s0 s1
+ | _, _ ->
+ fail()
+
+ method private visit_nativeint: 'env .
+ 'env -> nativeint -> nativeint -> nativeint * 's
+ = fun _ x1 x2 -> if x1 = x2 then x1, self#zero else fail()
+
+ method private visit_option: 'env 'a_0 'a_1 'a_2 .
+ ('env -> 'a_0 -> 'a_1 -> 'a_2 * 's) ->
+ 'env -> 'a_0 option -> 'a_1 option -> 'a_2 option * 's
+ = fun visit_'a env this_0 this_1 ->
+ match this_0, this_1 with
+ | None, None ->
+ None, self#zero
+ | Some c0_0, Some c0_1 ->
+ let r0, s0 = visit_'a env c0_0 c0_1 in
+ Some r0, s0
+ | _, _ ->
+ fail()
+
+ method private visit_ref: 'env 'a_0 'a_1 'a_2 .
+ ('env -> 'a_0 -> 'a_1 -> 'a_2 * 's) ->
+ 'env -> 'a_0 ref -> 'a_1 ref -> 'a_2 ref * 's
+ = fun visit_'a env this_0 this_1 ->
+ let r0, s0 = visit_'a env !this_0 !this_1 in
+ ref r0, s0
+
+ method private visit_result: 'env 'a_0 'a_1 'a_2 'b_0 'b_1 'b_2 .
+ ('env -> 'a_0 -> 'a_1 -> 'a_2 * 's) ->
+ ('env -> 'b_0 -> 'b_1 -> 'b_2 * 's) ->
+ 'env -> ('a_0, 'b_0) result -> ('a_1, 'b_1) result -> ('a_2, 'b_2) result * 's
+ = fun visit_'a visit_'b env this_0 this_1 ->
+ match this_0, this_1 with
+ | Ok c0_0, Ok c0_1 ->
+ let r0, s0 = visit_'a env c0_0 c0_1 in
+ Ok r0, s0
+ | Error c0_0, Error c0_1 ->
+ let r0, s0 = visit_'b env c0_0 c0_1 in
+ Error r0, s0
+ | _, _ ->
+ fail()
+
+ method private visit_string: 'env .
+ 'env -> string -> string -> string * 's
+ = fun _ x1 x2 -> if x1 = x2 then x1, self#zero else fail()
+
+ method private visit_unit: 'env .
+ 'env -> unit -> unit -> unit * 's
+ = fun _ () () -> (), self#zero
+
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* [fold2] *)
+
+class ['self] fold2 = object (_self)
+
+ (* See the comment in the class [fold] above. *)
+
+end
diff --git a/runtime/dune b/runtime/dune
new file mode 100644
index 0000000..75112ef
--- /dev/null
+++ b/runtime/dune
@@ -0,0 +1,7 @@
+(library
+ (name VisitorsRuntime)
+ (public_name visitors.runtime)
+ (synopsis "Runtime support for the generated visitors")
+ (libraries result)
+ (wrapped false)
+)
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..75c28e9
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,3 @@
+.PHONY: all
+all:
+ @ dune build @check
diff --git a/src/Visitors.ml b/src/Visitors.ml
new file mode 100644
index 0000000..f28925f
--- /dev/null
+++ b/src/Visitors.ml
@@ -0,0 +1,1288 @@
+open VisitorsString
+open VisitorsList
+open Ppxlib
+open List
+open Asttypes
+open Parsetree
+open Ast_helper
+open Ppx_deriving.Ast_convenience
+open Ppx_deriving
+open VisitorsPlugin
+open VisitorsCompatibility
+open VisitorsAnalysis
+open VisitorsGeneration
+open VisitorsSettings
+
+(* -------------------------------------------------------------------------- *)
+
+(* Per-run global state. *)
+
+module Setup (X : SETTINGS) = struct
+
+let arity =
+ X.arity
+
+(* -------------------------------------------------------------------------- *)
+
+(* If the [public] option is absent, then every method is public. If it is
+ present, then every method is private, unless its name occurs in the list
+ [X.public]. *)
+
+let visibility m =
+ match X.public with
+ | None ->
+ Public
+ | Some ms ->
+ if List.mem m ms then Public else Private
+
+(* The following brings [generate] and [dump] into scope. *)
+
+include ClassFieldStore(struct end)
+
+let annotation (ty : core_type) : core_type option =
+ (* A type annotation is generated only in [polymorphic] mode. *)
+ if X.polymorphic then Some ty else None
+
+let generate_concrete_method m e ty =
+ generate (concrete_method (visibility m) m e (annotation ty))
+
+let generate_virtual_method m ty =
+ generate (virtual_method (visibility m) m (annotation ty))
+
+(* -------------------------------------------------------------------------- *)
+
+(* The following brings [warning] and [warnings] into scope. *)
+
+include WarningStore(struct end)
+
+(* [datacon_opacity_warning cd] emits a warning (if necessary) about the
+ following issue. One should not write "A of int[@opaque]". Instead, one
+ should write "A of (int[@opaque])". In the case of records fields, we fix
+ this silently, by moving the attribute from the record field to the type,
+ but in the case of data constructors with multiple fields, it is preferable
+ to be strict. *)
+
+let datacon_opacity_warning (cd : constructor_declaration) : unit =
+ if opacity cd.pcd_attributes = Opaque then
+ warning cd.pcd_loc
+ "%s: @opaque, attached to a data constructor, is ignored.\n\
+ It should be attached to a type. Please use parentheses."
+ plugin
+
+(* [sum_build_warning decl] emits emits a warning (if necessary) about the
+ following issue. One should not attach a [@@build] attribute to a sum type.
+ Instead, one should attach a [@build] attribute to every data constructor.
+ Note that one can attach a [@@build] attribute to a record type. *)
+
+let sum_build_warning (decl : type_declaration) : unit =
+ if build decl.ptype_attributes <> None then
+ warning decl.ptype_loc
+ "%s: @@build, attached to a sum type, is ignored.\n\
+ Instead, @build should be attached to each data constructor."
+ plugin
+
+(* -------------------------------------------------------------------------- *)
+
+(* Shared glue code for detecting and warning against name clashes. *)
+
+type 'a wrapper =
+ 'a -> 'a
+
+type tycon_visitor_method =
+ Location.t * attributes * Longident.t -> methode
+
+let protect_tycon_visitor_method : tycon_visitor_method wrapper =
+ fun tycon_visitor_method ->
+ let format : (_, _, _, _) format4 =
+ "%s: name clash: the types %s and %s\n\
+ both have visitor methods named %s.\n\
+ Please consider using [@@name] at type declaration sites\n\
+ or [@name] at type reference sites."
+ in
+ let id = print_longident in
+ protect tycon_visitor_method
+ (fun (_, _, x) (_, _, y) -> x = y)
+ (fun (_, _, x) (loc, _, y) m -> warning loc format plugin (id x) (id y) m)
+
+type datacon_descending_method =
+ constructor_declaration -> methode
+
+let protect_datacon_descending_method : datacon_descending_method wrapper =
+ fun datacon_descending_method ->
+ let format : (_, _, _, _) format4 =
+ "%s: name clash: the data constructors %s and %s\n\
+ both have visitor methods named %s.\n\
+ Please consider using [@name] at data constructor declaration sites."
+ in
+ let id cd = cd.pcd_name.txt in
+ protect datacon_descending_method
+ (fun cd1 cd2 -> cd1 == cd2)
+ (fun cd1 cd2 m -> warning cd2.pcd_loc format plugin (id cd1) (id cd2) m)
+
+(* -------------------------------------------------------------------------- *)
+
+(* We support parameterized type declarations. We require them to be regular.
+ That is, for instance, if a type ['a term] is being defined, then every
+ use of [_ term] in the definition should be ['a term]; it cannot be, say,
+ [int term] or [('a * 'a) term]. *)
+
+(* To enforce this, we check that, in every use of a local type constructor,
+ the actual type parameters coincide with the formal type parameters. *)
+
+(* This check is imposed only on [mono] type variables. For [poly] type
+ variables, irregularity is allowed. *)
+
+(* The purpose of this check is to avoid an incomprehensible type error in
+ the generated code. *)
+
+let check_regularity loc tycon (formals : tyvars) (actuals : core_types) =
+ (* Check that the numbers of parameters match. *)
+ if length formals <> length actuals then
+ raise_errorf ~loc
+ "%s: the type constructor %s expects %s,\n\
+ but is applied to %s."
+ plugin tycon
+ (number (length formals) "type parameter")
+ (number (length actuals) "type parameter");
+ (* Check that the parameters match. *)
+ if not X.irregular && not (
+ fold_left2 (fun ok formal actual ->
+ ok && (X.poly formal || actual.ptyp_desc = Ptyp_var formal)
+ ) true formals actuals
+ ) then
+ raise_errorf ~loc "%s: the type constructor %s is irregular." plugin tycon
+
+(* -------------------------------------------------------------------------- *)
+
+(* Public naming conventions. *)
+
+(* The names of the methods associated with the type [foo] are normally based
+ on (derived from) the name [foo].
+
+ This base name can be overriden by the user via an attribute. For a local
+ type, a [@@name] attribute must be attached to the type declaration. For a
+ nonlocal type, a [@name] attribute must be attached to every reference to
+ this type.
+
+ The [@name] attribute can be misused: e.g., one can mistakenly use
+ different visitor method names for different occurrences of a single type.
+ We currently do not attempt to detect this situation.
+
+ The prefix that is prepended to the base name can be controlled via the
+ settings [visit_prefix], [build_prefix], and [fail_prefix]. *)
+
+let tycon_modified_name (attrs : attributes) (tycon : tycon) : tycon =
+ maybe (name attrs) tycon
+
+(* Similarly, the base name of the methods associated with a data constructor
+ can be altered via a [@name] attribute, which must be attached to the data
+ constructor declaration. *)
+
+let datacon_modified_name (cd : constructor_declaration) : datacon =
+ maybe (name cd.pcd_attributes) cd.pcd_name.txt
+
+(* For every type constructor [tycon], there is a visitor method, also called
+ a descending method, as it is invoked when going down into the tree. *)
+
+(* The name of this method is normally [visit_foo] if the type is named [foo]
+ or [A.foo]. (A qualified name must denote a nonlocal type.) *)
+
+(* This convention can cause name clashes, as the types [foo] and [A.foo]
+ receive visitor methods by the same name. We warn if this happens.
+
+ A name clash can also be caused by incorrect use of the [@@name] or
+ [@name] attributes. We also warn if this happens. *)
+
+(* Step 1 -- the raw convention. *)
+
+let tycon_visitor_method : tycon_visitor_method =
+ fun (_, attrs, tycon) ->
+ X.visit_prefix ^ tycon_modified_name attrs (Longident.last_exn tycon)
+
+(* Step 2 -- protect against name clashes. *)
+
+let tycon_visitor_method =
+ protect_tycon_visitor_method tycon_visitor_method
+
+(* Step 3 -- define auxiliary functions that are easier to use. *)
+
+let local_tycon_visitor_method (decl : type_declaration) : methode =
+ tycon_visitor_method (decl.ptype_loc, decl.ptype_attributes, Lident decl.ptype_name.txt)
+
+let nonlocal_tycon_visitor_method (ty : core_type) : methode =
+ match ty.ptyp_desc with
+ | Ptyp_constr (tycon, _) ->
+ tycon_visitor_method (ty.ptyp_loc, ty.ptyp_attributes, tycon.txt)
+ | _ ->
+ assert false
+
+(* For every local record type constructor [tycon], there is an ascending
+ method, which is invoked on the way up, in order to re-build some data
+ structure. This method is virtual and exists only when the scheme is
+ [fold]. *)
+
+(* The name of this method is normally [build_foo] if the type is named [foo]. *)
+
+let tycon_ascending_method (decl : type_declaration) : methode =
+ X.build_prefix ^ tycon_modified_name decl.ptype_attributes decl.ptype_name.txt
+
+(* [mono] type variables have a virtual visitor method. We include a quote in
+ the method name so as to ensure the absence of collisions. *)
+
+let tyvar_visitor_method (alpha : tyvar) : methode =
+ sprintf "%s'%s" X.visit_prefix alpha
+
+(* For every data constructor [datacon], there is a descending visitor method,
+ which is invoked on the way down, when this data constructor is discovered. *)
+
+(* The name of this method is normally [visit_Foo] if the data constructor is
+ named [Foo]. *)
+
+let datacon_descending_method (cd : constructor_declaration) : methode =
+ X.visit_prefix ^ datacon_modified_name cd
+
+let datacon_descending_method =
+ protect_datacon_descending_method datacon_descending_method
+
+(* For every data constructor [datacon], there is a ascending visitor method,
+ which is invoked on the way up, in order to re-build some data structure.
+ This method is virtual and exists only when the scheme is [fold]. *)
+
+let datacon_ascending_method (cd : constructor_declaration) : methode =
+ X.build_prefix ^ datacon_modified_name cd
+
+(* At arity 2, for every sum type constructor [tycon] which has at least two
+ data constructors, there is a failure method, which is invoked when the
+ left-hand and right-hand arguments do not exhibit the same tags. *)
+
+(* The name of this method is normally [fail_foo] if the type is named [foo]. *)
+
+let failure_method (decl : type_declaration) : methode =
+ X.fail_prefix ^ tycon_modified_name decl.ptype_attributes decl.ptype_name.txt
+
+(* When [scheme] is [Reduce], we need a monoid, that is, a unit [zero] and a
+ binary operation [plus]. The names [zero] and [plus] are fixed. We assume
+ that there exist virtual methods by these names. It is up to the user to
+ provide these methods via inheritance, that is, via the [ancestors]
+ option. *)
+
+let zero =
+ "zero"
+
+let plus =
+ "plus"
+
+(* -------------------------------------------------------------------------- *)
+
+(* Private naming conventions. *)
+
+(* These conventions must be set up so as to avoid collisions within each name
+ space separately: e.g., variables, methods, type variables, and so on. *)
+
+(* We use improbable variable names, because it is possible for user code to
+ be placed in the scope of these variables. (This is the case when the user
+ provides [@build] annotations.) As a couple exceptions, the names [self]
+ and [env] are not made improbable, and we document the existence of these
+ variables, which can be used in [@build] annotations. *)
+
+(* In a class, the variable [self] refers to self.
+ The type variable [ty_self] denotes its type. *)
+
+let self : variable =
+ "self"
+
+let ty_self : core_type =
+ Typ.var "self"
+
+let pself : pattern =
+ Pat.constraint_ (pvar self) ty_self
+
+(* The variable [env] refers to the environment that is carried down into
+ recursive calls. *)
+
+let env : variable =
+ "env"
+
+(* We sometimes need two (or more) copies of a variable: one copy for each
+ index [j] ranging in the interval [0..arity). *)
+
+let copy (j : int) (x : string) : string =
+ assert (0 <= j && j < arity);
+ if arity = 1 then
+ (* No alteration required. *)
+ x
+ else
+ sprintf "%s_%d" x j
+
+(* The variables [component i j] denote tuple components. The index [i]
+ ranges over tuple components; the index [j] ranges in [0..arity). *)
+
+let component (i : int) (j : int) : variable =
+ improbable (copy j (sprintf "c%d" i))
+
+let components (i : int) : variables =
+ map (component i) (interval 0 arity)
+
+let componentss (xs : _ list) : variables list =
+ mapi (fun i _ -> components i) xs
+
+(* The variable [thing j] denotes an input value. *)
+
+let thing (j : int) : variable =
+ improbable (copy j "this")
+
+let things : variables =
+ map thing (interval 0 arity)
+
+(* The variable [this] is used only in the generation of [endo] visitors. *)
+
+let this =
+ thing 0
+
+(* The variables [field label j] denote record fields. *)
+
+let field (label : label) (j : int) : variable =
+ improbable (copy j (sprintf "f%s" label))
+
+let fields (label : label) : variables =
+ map (field label) (interval 0 arity)
+
+let fieldss (labels : label list) : variables list =
+ map fields labels
+
+(* The variables [result i] denote results of recursive calls. *)
+
+let result (i : int) : variable =
+ improbable (sprintf "r%d" i)
+
+let results (xs : _ list) : variables =
+ mapi (fun i _ -> result i) xs
+
+(* The variables [summary i] denote results of recursive calls.
+ When the scheme is [MapReduce], each recursive call produces
+ a pair; we use [result i] and [summary i] as the names of the
+ pair components. *)
+
+let summary (i : int) : variable =
+ improbable (sprintf "s%d" i)
+
+let summaries (xs : _ list) : variables =
+ mapi (fun i _ -> summary i) xs
+
+(* Reserved names of type variables. We forbid the user from using these
+ names, and do not let them be renamed by the function [variant] below. *)
+
+let reserved : tyvars =
+ [ "s"; "env" ]
+
+let reserved_ty_var (alpha : tyvar) : core_type =
+ assert (mem alpha reserved);
+ ty_var alpha
+
+(* Naming conventions for type variables in type annotations. If ['a]
+ is a type variable named by the user, we use ['a_i], where [i] is
+ in [0..arity]. Indices [i] in the interval [0..arity) are used for
+ the arguments of a visitor method. The index [arity] is used for
+ the result of a visitor method. *)
+
+(* If [scheme] is [Endo], then the argument and result must have the
+ same type, so we do not introduce a variation in the type variables. *)
+
+let variant (i : int) (alpha : tyvar) : tyvar =
+ assert (0 <= i && i <= arity);
+ if X.scheme = Endo || mem alpha reserved then
+ alpha
+ else
+ sprintf "%s_%d" alpha i
+
+let vary_type (i : int) (ty : core_type) : core_type =
+ rename_type (variant i) ty
+
+(* [ty_monoid] is the type of monoid elements. *)
+
+let ty_monoid =
+ reserved_ty_var "s"
+
+(* [ty_env] is the type of the environment. *)
+
+(* What IS the type of the environment? This is a tricky question. Two
+ possibilities arise:
+
+ 1. One might wish for every visitor method to be polymorphic in the type
+ ['env] of the environment. This makes the method more widely applicable,
+ but means that the environment effectively cannot be used by the method
+ (except by passing it on to its callees). Thus, the method cannot be
+ overridden by a custom implementation that actually uses the environment.
+
+ 2. One might wish for the environment to have monomorphic type. In that
+ case, one should note that there is a priori no reason why the type of
+ the environment should be the same in every method. So, we must be
+ careful not to use a single type variable ['env]. We must use a distinct
+ type variable every time, or (easier but equivalent) use a wildcard.
+
+ How do we let the user specify which behavior is desired? And with what
+ granularity? We choose a simple approach: we treat ['env] as polymorphic
+ if and only if this (reserved) type variable is declared polymorphic by
+ the user. *)
+
+let ty_env =
+ if X.poly "env" then
+ reserved_ty_var "env"
+ else
+ ty_any
+
+(* What is the type of a virtual visitor method [visit_'a] in charge of
+ dealing with a [mono] type variable ['a]?
+
+ One might think that it must be a monomorphic type, so we can just
+ issue a wildcard [_] and let OCaml infer this type.
+
+ Yet, if the user has requested that every method be polymorphic in
+ the type ['env] of the environment, then [visit_'a], too must be
+ polymorphic in ['env]. (Otherwise, the generated code would be ill-typed.)
+ In that case, we must generate ['env . 'env -> _].
+
+ This implies that [visit_'a] cannot use the environment.
+ So, it seems somewhat doubtful that this feature is useful.
+ Perhaps we could allow the environment to consist of two components
+ and to quantify universally over only one of them? *)
+
+let tyvar_visitor_method_type =
+ if X.poly "env" then
+ typ_poly ["env"] (ty_arrow ty_env ty_any)
+ else
+ ty_any
+
+(* [poly] type variables have a visitor function. *)
+
+let tyvar_visitor_function (alpha : tyvar) : variable =
+ tyvar_visitor_method alpha
+
+(* -------------------------------------------------------------------------- *)
+
+(* Construction of type annotations. *)
+
+(* [result_type scheme ty] is the result type of a visitor method associated
+ with the type [ty]. *)
+
+(* If [ty] is of the form [decl_type decl] -- that is, if [ty] is a local type
+ constructor -- then this is the result type of the visitor method associated
+ with [ty]. *)
+
+let rec result_type scheme (ty : core_type) : core_type =
+ match scheme with
+ | Iter ->
+ (* An [iter] visitor method returns nothing. *)
+ ty_unit
+ | Map | Endo ->
+ (* A [map] or [endo] visitor method for the type [ty] returns a
+ value of type [ty]. Note that [ty] can contain type variables. *)
+ ty
+ | Reduce ->
+ (* A [reduce] visitor method returns a monoid element. *)
+ ty_monoid
+ | MapReduce ->
+ (* A [mapreduce] visitor method returns a pair of the results produced
+ by a [map] visitor method and by a [reduce] visitor method. *)
+ Typ.tuple [ result_type Map ty; result_type Reduce ty ]
+ | Fold ->
+ (* This is where we have a problem. We would really like to allow the
+ user to specify which skeleton should be used here, as we cannot
+ guess it. We might allow it in the future. For now, we impose the
+ monomorphic skeleton [_], which is not as general as we would like,
+ since it requires the method to have monomorphic result type. *)
+ ty_any
+
+let result_type =
+ result_type X.scheme
+
+(* [decl_result_type decl] is the result type of a visitor method associated
+ with the type declaration [decl]. *)
+
+let decl_result_type decl =
+ result_type (decl_type decl)
+
+(* A visitor function takes an environment, followed with [arity] arguments,
+ and produces a result. Thus, if [argument] and [result] are types, then the
+ type of a visitor function has the following shape:
+
+ ty_env ->
+ argument_0 -> ... -> argument_{arity-1} ->
+ result_{arity}
+
+ where [ty_{i}] denotes a copy of the type [ty] whose type variables have
+ been renamed by the renaming [variant i]. *)
+
+(* We generalize the above definition to allow for multiple [arguments]. This
+ is used in the visitor methods associated with data constructors. Thus,
+ each argument in succession is extended to [arity] arguments. *)
+
+(* We specialize the above definition to the case where the result type
+ is [result_type ty]. *)
+
+let visitor_fun_type (arguments : core_types) (ty : core_type) : core_type =
+ ty_arrows
+ (ty_env :: flatten (hextend arguments arity vary_type))
+ (vary_type arity (result_type ty))
+
+(* This special case of [visitor_fun_type] is the normal form of a visitor
+ function type: there is one argument of type [ty] (extended to [arity])
+ and one result of type [result_type ty]. *)
+
+let simple_visitor_fun_type (ty : core_type) : core_type =
+ visitor_fun_type [ty] ty
+
+(* [visitor_method_type decl] is the type of the visitor method associated
+ with the type [decl]. This does not account for the visitor parameters
+ in charge of dealing with type variables. *)
+
+let visitor_method_type (decl : type_declaration) : core_type =
+ simple_visitor_fun_type (decl_type decl)
+
+(* [visitor_param_type alpha] is the type of the visitor function associated
+ with the type variable [alpha]. *)
+
+let visitor_param_type (alpha : tyvar) : core_type =
+ simple_visitor_fun_type (ty_var alpha)
+
+(* [fold_result_type ty] is the result type of the visitor code generated
+ by [visit_type ... ty], when [scheme] is [Fold]. *)
+
+let fold_result_type _ty =
+ (* This function is currently unimplemented and unused, because we
+ do not allow [polymorphic] to be [true] when [scheme] is [Fold].
+ Thus, we do not generate any type annotations for ascending methods. *)
+ ty_any
+
+(* [poly_params decl] is the subset of the formal type parameters of [decl]
+ which are marked [poly]. For each of these parameters, a visitor function
+ should be passed. *)
+
+let poly_params (decl : type_declaration) : tyvars =
+ filter X.poly (decl_params decl)
+
+(* [quantify alphas ty] quantifies an appropriate set of type variables in the
+ method type [ty]. The parameter [alphas] is usually [poly_params decl],
+ although it could in principle be a subset of it, if we can prove that
+ some visitor functions are unneeded. We introduce universal quantifiers
+ on (suitable variants of) the type variables [alphas] and also possibly
+ on the type variable ['env]. *)
+
+let quantify (alphas : tyvars) (ty : core_type) : core_type =
+ (* Find out which variants of the type variables [alphas] we should quantify
+ over. For the arguments, we need to quantify over the variants in the
+ interval [0..arity). For the result, we may need to quantify over the
+ variant [arity]. We try and avoid superfluous quantifiers, as that would
+ decrease readability. *)
+ let alphas =
+ match X.scheme with
+ | Iter
+ | Reduce ->
+ (* Just the arguments. The result contains no type variables. *)
+ flatten (hextend alphas arity variant)
+ | Map
+ | MapReduce ->
+ (* Arguments and result. *)
+ flatten (hextend alphas (arity+1) variant)
+ | Endo ->
+ (* In this special case, there is just one variant, as the argument
+ and result must have the same type. *)
+ alphas
+ | Fold ->
+ (* Polymorphism currently not supported with [Fold]. *)
+ []
+ in
+ (* Then, decide whether ['env] should be universally quantified. *)
+ let alphas =
+ if X.poly "env" then
+ "env" :: alphas
+ else
+ alphas
+ in
+ (* Done. *)
+ typ_poly alphas ty
+
+(* -------------------------------------------------------------------------- *)
+
+(* [bind rs ss] is a binding construct which, depending on the scheme, binds
+ either the variables [rs], or the variables [ss], or both, using pair
+ patterns. It is used to bind the results of recursive calls to visitor
+ methods. *)
+
+let bind (rs : variables) (ss : variables)
+ : expressions -> expression -> expression =
+ match X.scheme with
+ | Iter
+ | Map
+ | Endo
+ | Fold ->
+ letn rs
+ | Reduce ->
+ letn ss
+ | MapReduce ->
+ letnp rs ss
+
+(* -------------------------------------------------------------------------- *)
+
+(* [call m es] emits a method call of the form [self#m es]. *)
+
+let call (m : methode) (es : expressions) : expression =
+ send self m es
+
+(* -------------------------------------------------------------------------- *)
+
+(* Access to the monoid operations. *)
+
+let monoid_unit () : expression =
+ assert (X.scheme = Reduce || X.scheme = MapReduce);
+ call zero []
+
+let monoid_law () : expression =
+ assert (X.scheme = Reduce || X.scheme = MapReduce);
+ call plus []
+
+(* -------------------------------------------------------------------------- *)
+
+(* [reduce es] reduces the expressions [es], that is, it combines them, using
+ a monoid, which provides a unit and a binary operation. The reduction is
+ performed left-to-right. This could be of importance if the monoid is not
+ associative-commutative. *)
+
+let reduce es =
+ let unit = monoid_unit()
+ and law = monoid_law() in
+ fold_left1 (fun e1 e2 -> app law [e1; e2]) unit es
+
+(* -------------------------------------------------------------------------- *)
+
+(* [alias x ps] requires the pattern list [ps] to have length [arity]. If
+ [scheme] is [Endo], then it further requires [arity] to be 1. It adds a
+ binding of the variable [x], using an [as] pattern, at the top level of the
+ pattern. The result is again packaged as a pattern list of length [arity].
+ If scheme is not [Endo], then [alias x ps] is just [ps]. *)
+
+let alias (x : variable) (ps : patterns) : patterns =
+ assert (length ps = arity);
+ match X.scheme with
+ | Endo ->
+ assert (arity = 1);
+ map (fun p ->
+ Pat.alias p (Ocaml_common.Location.mknoloc x)
+ ) ps
+ | _ ->
+ ps
+
+(* If [scheme] is [Endo], then [transmit x xs] is [x :: xs]. Otherwise, it is
+ just [xs]. *)
+
+let transmit x xs =
+ match X.scheme with
+ | Endo ->
+ x :: xs
+ | _ ->
+ xs
+
+(* -------------------------------------------------------------------------- *)
+
+(* [hook m xs ty e] constructs a call of the form [self#m xs], and (as a side
+ effect) generates a method [method m xs = e]. The free variables of the
+ expression [e] must be (a subset of) [xs]. The type [ty] is the type of
+ the method. It is always computed internally, but the type annotation is
+ actually printed only in [polymorphic] mode. *)
+
+(* Thus, by default, the expression [hook m xs ty e] behaves in the same way
+ as the expression [e]. But a hook, named [m], allows this default to be
+ overridden. *)
+
+let hook (m : methode) (xs : variables) (ty : core_type) (e : expression) : expression =
+ (* Generate a method. *)
+ generate_concrete_method m (lambdas xs e) ty;
+ (* Construct a method call. *)
+ call m (evars xs)
+
+(* The additional parameter [b] makes hook insertion optional. If [b] is [true],
+ a hook is created; otherwise, no hook is created. *)
+
+let hook b m xs ty e =
+ if b then hook m xs ty e else e
+
+(* -------------------------------------------------------------------------- *)
+
+(* [vhook m xs ty] constructs a call of the form [self#m xs], and (as a side
+ effect) generates a virtual method [method m: ty]. The type [ty] is the type
+ of the method. It is always computed internally, but the type annotation is
+ actually printed only in [polymorphic] mode. *)
+
+let vhook (m : methode) (xs : variables) (ty : core_type) : expression =
+ generate_virtual_method m ty;
+ call m (evars xs)
+
+(* -------------------------------------------------------------------------- *)
+
+(* If a data constructor or record carries a [@build] attribute, then the
+ OCaml expression carried by this attribute should be used instead of the
+ default [builder] function, which rebuilds a data constructor or record.
+ This concerns [map], [endo], and [mapreduce] visitors. *)
+
+type builder =
+ variables -> expression
+
+let ifbuild (attrs : attributes) (builder : builder) : builder =
+ match build attrs with
+ | None ->
+ builder
+ | Some e ->
+ fun rs -> app e (evars rs)
+
+(* -------------------------------------------------------------------------- *)
+
+(* The following classes help build the code that forms the ascending part of
+ a visitor method, that is, the code found after the recursive calls. *)
+
+(* There are four variants of this code, used in visitor methods for data
+ constructors, in visitor methods for records, in visitor functions for
+ tuples, and in visitor functions for @opaque types. *)
+
+(* The base class, [ascend], provides as much shared behavior as possible. *)
+
+class virtual ascend (ss : variables) = object (self)
+
+ (* An [iter] visitor returns a unit value. *)
+ method ascend_Iter =
+ unit()
+
+ (* The behavior of a [map] visitor is defined in subclasses. *)
+ method virtual ascend_Map : expression
+
+ (* By default, an [endo] visitor behaves like a [map] visitor. This behavior
+ is appropriate at @opaque types. *)
+ method ascend_Endo =
+ self#ascend_Map
+
+ (* A [reduce] visitor uses [zero] and [plus] to combine the results
+ of the recursive calls, which are bound to the variables [ss]. *)
+ method ascend_Reduce =
+ reduce (evars ss)
+
+ (* A [mapreduce] visitor returns a pair of the results that would be
+ returned by a [map] visitor and by a [reduce] visitor. *)
+ method ascend_MapReduce =
+ tuple [ self#ascend_Map; self#ascend_Reduce ]
+
+ (* By default, a [fold] visitor behaves like a [map] visitor, because we
+ have no better choice. This behavior is used at tuples and at @opaque
+ types. *)
+ method ascend_Fold =
+ self#ascend_Map
+
+ (* Dispatch. *)
+ method ascend =
+ match X.scheme with
+ | Iter -> self#ascend_Iter
+ | Map -> self#ascend_Map
+ | Endo -> self#ascend_Endo
+ | Reduce -> self#ascend_Reduce
+ | MapReduce -> self#ascend_MapReduce
+ | Fold -> self#ascend_Fold
+
+end
+
+(* The subclass [ascend_opaque] defines the desired behavior at @opaque types. *)
+
+(* In an [iter] visitor, we return a unit value, as always. This means that,
+ even if [arity] is greater than 1, NO EQUALITY TEST takes place. This
+ differs from the behavior of the methods [visit_int], [visit_bool], etc.,
+ which perform an equality test. *)
+
+(* In a [map] visitor, we return THE FIRST ARGUMENT of the visitor. At arity
+ greater than 1, this is an ARBITRARY choice. It is not clear what else we
+ could do. *)
+
+(* In a [reduce] visitor, we return the neutral element, [self#zero]. *)
+
+(* In a [fold] visitor, we keep the default behavior, which is to behave like
+ a [map] visitor. *)
+
+class ascend_opaque (xs : variables) = object
+
+ inherit ascend []
+
+ method ascend_Map =
+ evar (hd xs) (* [xs] is the vector of arguments; pick the first one *)
+
+end
+
+(* The subclass [ascend_endo] defines the standard behavior of an [endo]
+ visitor, which is to perform physical equality tests. *)
+
+(* Its parameters are as follows:
+
+ [this] (a variable for) the data structure that is visited
+ [subjects] the matrix of arguments to the recursive calls
+ [rs], [ss] (vectors of variables for) the results of the recursive calls *)
+
+class virtual ascend_endo
+ (this : variable)
+ (subjects : expressions list)
+ (rs : variables)
+ (ss : variables)
+= object (self)
+
+ inherit ascend ss
+
+ (* An [endo] visitor first tests if the arguments of the recursive calls,
+ [subjects], are physically equal to the results of these calls, [rs]. If
+ that is the case, then it returns the original data structure, [this].
+ Otherwise, it reconstructs a new data structure, like a [map] visitor. *)
+ method! ascend_Endo =
+ (* [subjects] is a matrix of width [arity], and [arity] is [1]. The first
+ column of [subjects] is [map hd subjects]. *)
+ assert (for_all (fun es -> length es = arity) subjects);
+ assert (arity = 1);
+ Exp.ifthenelse
+ (eqphys (map hd subjects) (evars rs))
+ (evar this)
+ (Some self#ascend_Map)
+
+end
+
+(* The subclass [ascend_tuple] defines the desired behavior at tuple types. *)
+
+class ascend_tuple this subjects rs ss = object
+
+ inherit ascend_endo this subjects rs ss
+
+ (* A [map] visitor reconstructs a tuple. *)
+ method ascend_Map =
+ tuple (evars rs)
+
+end
+
+(* The subclass [ascend_algebraic] defines the desired behavior at a sum type
+ or record type. Its extra parameters are as follows:
+
+ [builder] how to reconstruct a data constructor or record
+ [decl] the type declaration under which we are working
+ [m] the name of the virtual ascending method
+ [tys] the types of the components of this data constructor or record *)
+
+class ascend_algebraic this subjects rs ss
+ (builder : builder)
+ (decl : type_declaration)
+ (m : methode)
+ (tys : core_types)
+= object
+
+ inherit ascend_endo this subjects rs ss
+
+ (* A [map] visitor reconstructs a data structure using the results [rs] of
+ the recursive calls. *)
+ method ascend_Map =
+ builder rs
+
+ (* A [fold] visitor invokes the virtual ascending method [m], with [env] and
+ [rs] as arguments. As a side effect, [ascend_Fold] declares this virtual
+ method. *)
+ method! ascend_Fold =
+ vhook m
+ (env :: rs)
+ (ty_arrows
+ (ty_env :: map fold_result_type tys)
+ (decl_result_type decl)
+ )
+
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* [visit_type env_in_scope ty] builds a small expression that represents the
+ visiting code associated with the OCaml type [ty]. For instance, if [ty] is
+ a local type constructor, this could be a call to the visitor method
+ associated with this type constructor. *)
+
+(* This expression may refer to the variable [self]. *)
+
+(* If [env_in_scope] is true, then this expression may refer to the variable
+ [env]. If [env_in_scope] is false, then this expression should denote a
+ function of [env]. The use of [env_in_scope] complicates things slightly,
+ but allows us to avoid the production of certain eta-redexes. *)
+
+(* If [ty] carries the attribute [@opaque], then we act as if there is nothing
+ to visit. The nature of the type [ty], in that case, plays no role. *)
+
+let rec visit_type (env_in_scope : bool) (ty : core_type) : expression =
+ match env_in_scope, opacity ty.ptyp_attributes, ty.ptyp_desc with
+
+ (* A type constructor [tycon] applied to type parameters [tys]. We handle
+ the case where [env_in_scope] is false, so we construct a function of
+ [env]. *)
+ | false,
+ NonOpaque,
+ Ptyp_constr ({ txt = tycon; _ }, tys) ->
+ (* [tycon] is a type constructor, applied to certain types [tys]. *)
+ (* We must call the visitor method associated with [tycon],
+ applied to the visitor functions associated with SOME of the [tys]. *)
+ let m, tys =
+ match is_local X.decls tycon with
+ | Some decl ->
+ let formals = decl_params decl in
+ (* [tycon] is a local type constructor, whose formal type parameters
+ are [formals]. Among these formal type parameters, some should be
+ treated in a monomorphic manner, and some should be treated in a
+ polymorphic manner. The function [X.poly], applied to a type
+ variable [formal], tells how it should be treated. *)
+ (* The regularity check is applied only to [mono] parameters. *)
+ check_regularity ty.ptyp_loc (Longident.last_exn tycon) formals tys;
+ (* The visitor method should be applied to the visitor functions
+ associated with the subset of [tys] that corresponds to [poly]
+ variables. *)
+ local_tycon_visitor_method decl,
+ filter2 X.poly formals tys
+ | None ->
+ (* [tycon] is a nonlocal type constructor. *)
+ (* The visitor method should be applied to visitor functions for all
+ of the types [tys]. *)
+ (* This visitor method is NOT generated by us, so it MUST be
+ inherited from an ancestor class; it is up to the user to
+ ensure that this method exists. (It may be virtual.) This
+ method may be polymorphic, so multiple call sites do not
+ pollute one another. *)
+ nonlocal_tycon_visitor_method ty,
+ tys
+ in
+ app
+ (call m [])
+ (map (visit_type false) tys)
+
+ (* A type variable [alpha] must be a formal parameter of the current
+ declaration. (Indeed, we do not handle GADTs yet.) Now, two cases
+ arise. If [alpha] is [mono], then it is handled by a virtual visitor
+ method. If [alpha] is [poly], then it is handled by a visitor function
+ which we must have received as an argument. *)
+ | false,
+ NonOpaque,
+ Ptyp_var alpha ->
+ if X.poly alpha then
+ evar (tyvar_visitor_function alpha)
+ else
+ vhook (tyvar_visitor_method alpha) [] tyvar_visitor_method_type
+
+ (* A tuple type. We handle the case where [env_in_scope] is true, as it
+ is easier. *)
+ | true,
+ NonOpaque,
+ Ptyp_tuple tys ->
+ (* Construct a function that takes [arity] tuples as arguments. *)
+ (* See [constructor_declaration] for comments. *)
+ let xss = componentss tys in
+ let subjects = evarss xss in
+ let rs = results xss
+ and ss = summaries xss in
+ let ascend = new ascend_tuple this subjects rs ss in
+ plambdas
+ (alias this (ptuples (transpose arity (pvarss xss))))
+ (bulk rs ss tys subjects ascend)
+
+ (* If [env_in_scope] does not have the desired value, wrap a recursive call
+ within an application or abstraction. At most one recursive call takes
+ place, so we never produce an eta-redex. *)
+ | true, NonOpaque, (Ptyp_constr _ | Ptyp_var _) ->
+ app (visit_type false ty) [evar env]
+ | false, _, _ ->
+ lambda env (visit_type true ty)
+
+ (* If [ty] is marked opaque, then we ignore the structure of [ty] and carry
+ out appropriate action, based on the current scheme. *)
+ | true, Opaque, _ ->
+ (* Construct a function that takes [arity] arguments. *)
+ lambdas things (
+ let ascend = new ascend_opaque things in
+ ascend#ascend
+ )
+
+ (* An unsupported construct. *)
+ | _, _, Ptyp_any
+ | _, _, Ptyp_arrow _
+ | _, _, Ptyp_object _
+ | _, _, Ptyp_class _
+ | _, _, Ptyp_alias _
+ | _, _, Ptyp_variant _
+ | _, _, Ptyp_poly _
+ | _, _, Ptyp_package _
+ | _, _, Ptyp_extension _ ->
+ unsupported ty
+
+and visit_types tys (ess : expressions list) : expressions =
+ (* The matrix [ess] is indexed first by component, then by index [j].
+ Thus, to each type [ty], corresponds a row [es] of expressions,
+ whose length is [arity]. *)
+ assert (is_matrix (length tys) arity ess);
+ map2 (fun ty es ->
+ app (visit_type true ty) es
+ ) tys ess
+
+(* -------------------------------------------------------------------------- *)
+
+(* The expression [bulk rs ss tys subjects ascend] represents the bulk of a
+ visitor method or visitor function. It performs the recursive calls, binds
+ their results to [rs] and/or [ss], then runs the ascending code. *)
+
+and bulk
+ (rs : variables) (ss : variables)
+ (tys : core_types)
+ (subjects : expressions list)
+ (ascend : < ascend: expression; .. >)
+=
+ bind rs ss
+ (visit_types tys subjects)
+ (ascend#ascend)
+
+(* -------------------------------------------------------------------------- *)
+
+(* [constructor_declaration] turns a constructor declaration (as found in a
+ declaration of a sum type) into a case, that is, a branch in the case
+ analysis construct that forms the body of the visitor method for this sum
+ type. At the same time, it generates several auxiliary method declarations
+ and definitions. *)
+
+let constructor_declaration decl (cd : constructor_declaration) : case =
+ datacon_opacity_warning cd;
+ let datacon = cd.pcd_name.txt in
+
+ (* This is either a traditional data constructor, whose components are
+ anonymous, or a data constructor whose components form an ``inline
+ record''. This is a new feature of OCaml 4.03. *)
+
+ (* In order to treat these two cases uniformly, we extract the following
+ information.
+ [xss] the names under which the components are known.
+ this matrix has [length tys] rows -- one per component --
+ and [arity] columns.
+ [tys] the types of the components.
+ [pss] the patterns that bind [xss], on the way down.
+ this matrix has [arity] rows.
+ it has [length tys] columns in the case of tuples,
+ and 1 column in the case of inline records.
+ [builder] a function which, applied to the results [rs] of the
+ recursive calls, rebuilds a data constructor, on the way up.
+ *)
+
+ let xss, tys, pss, (builder : builder) =
+ match cd.pcd_args with
+ (* A traditional data constructor. *)
+ | Pcstr_tuple tys ->
+ let xss = componentss tys in
+ let pss = transpose arity (pvarss xss) in
+ xss, tys, pss, fun rs -> constr datacon (evars rs)
+ (* An ``inline record'' data constructor. *)
+ | Pcstr_record lds ->
+ let labels, tys = ld_labels lds, ld_tys lds in
+ let xss = fieldss labels in
+ let pss = transpose arity (pvarss xss) in
+ xss, tys,
+ map (fun ps -> [precord ~closed:Closed (combine labels ps)]) pss,
+ fun rs -> constr datacon [record (combine labels (evars rs))]
+ in
+ assert (is_matrix (length tys) arity xss);
+ assert (length pss = arity);
+ let subjects = evarss xss in
+
+ (* Take a [@build] attribute into account. *)
+ let builder = ifbuild cd.pcd_attributes builder in
+
+ (* Find out which type variables [alphas] are formal parameters of this
+ declaration and are marked [poly]. We have to universally quantify over
+ (variants of) these type variables in the type of the hook, below.
+ Furthermore, we forbid these type variables from appearing under [@opaque],
+ as that would cause us to generate code whose actual type is less general
+ than its expected type. *)
+ let alphas = poly_params decl in
+ check_poly_under_opaque alphas tys;
+
+ (* Create new names [rs] and [ss] for the results of the recursive calls of
+ visitor methods. *)
+ let rs = results xss
+ and ss = summaries xss in
+
+ (* Construct a case for this data constructor in the visitor method associated
+ with this sum type. This case analyzes a tuple of width [arity]. After
+ binding the components [xss], we call the descending method associated with
+ this data constructor. The arguments of this method are:
+ 1. visitor functions for [poly] type variables;
+ 2. [env];
+ 3. [this] (see below);
+ 4. [xss].
+ In this method, we bind the variables [rs] and/or [ss] to the results of
+ the recursive calls to visitor methods, then produce a result (whose nature
+ depends on [scheme]). *)
+
+ (* If the variety is [endo] (which implies that [arity] is 1), then we bind
+ the variable [this] to the whole memory block. This variable is transmitted
+ to the descending method. When the time comes to allocate a new memory
+ block, if the components of the new block are physically equal to the
+ components of the existing block, then the address of the existing block is
+ returned; otherwise a new block is allocated, as in [map]. *)
+
+ let ascend =
+ new ascend_algebraic
+ this subjects rs ss
+ builder decl (datacon_ascending_method cd) tys
+ in
+
+ Exp.case
+ (ptuple (alias this (map (pconstr datacon) pss)))
+ (hook X.data
+ (datacon_descending_method cd)
+ (map tyvar_visitor_function alphas @ env :: transmit this (flatten xss))
+ (quantify alphas (ty_arrows
+ (map visitor_param_type alphas)
+ (visitor_fun_type (transmit (decl_type decl) tys) (decl_type decl))))
+ (bulk rs ss tys subjects ascend)
+ )
+
+(* -------------------------------------------------------------------------- *)
+
+(* [visit_decl decl] constructs an expression that represents the visiting
+ code associated with the type declaration [decl]. In other words, it is
+ the body of the visitor method associated with [decl]. *)
+
+let visit_decl (decl : type_declaration) : expression =
+
+ (* Check that the user does not use a reserved type variable name. *)
+ decl_params decl |> iter (fun alpha ->
+ if mem alpha reserved then
+ let loc = decl.ptype_loc in
+ raise_errorf ~loc "%s: the type variable name '%s is reserved."
+ plugin alpha
+ );
+
+ (* Bind the values to a vector of variables [xs]. *)
+ let xs = things in
+ assert (length xs = arity);
+
+ match decl.ptype_kind, decl.ptype_manifest with
+
+ (* A type abbreviation. *)
+ | Ptype_abstract, Some ty ->
+ visit_type true ty
+
+ (* A record type. *)
+ | Ptype_record (lds : label_declaration list), _ ->
+ let labels, tys = ld_labels lds, ld_tys (fix lds) in
+ (* See [constructor_declaration] for comments. *)
+ check_poly_under_opaque (poly_params decl) tys;
+ let builder rs = record (combine labels (evars rs)) in
+ let builder = ifbuild decl.ptype_attributes builder in
+ let subjects = accesses xs labels in
+ let rs = results labels
+ and ss = summaries labels in
+ let ascend =
+ new ascend_algebraic
+ (hd xs) subjects rs ss
+ builder decl (tycon_ascending_method decl) tys
+ in
+ lambdas xs (bulk rs ss tys subjects ascend)
+
+ (* A sum type. *)
+ | Ptype_variant (cds : constructor_declaration list), _ ->
+ sum_build_warning decl;
+ (* Generate one case per data constructor. Place these cases in a
+ [match] construct, which itself is placed in a function body. *)
+ (* If [arity] is greater than 1 and if there is more than one data
+ constructor, then generate also a default case. In this default
+ case, invoke the failure method, which raises an exception. The
+ failure method receives [env] and [xs] as arguments. *)
+ let default() : case =
+ Exp.case
+ (ptuple (pvars xs))
+ (hook true
+ (failure_method decl)
+ (env :: xs)
+ (quantify (poly_params decl) (visitor_method_type decl))
+ (efail (local_tycon_visitor_method decl))
+ )
+ in
+ let complete (cs : case list) : case list =
+ if arity = 1 || length cs <= 1 then cs else cs @ [ default() ]
+ in
+ lambdas xs (
+ Exp.match_
+ (tuple (evars xs))
+ (complete (map (constructor_declaration decl) cds))
+ )
+
+ (* Unsupported constructs. *)
+ | Ptype_abstract, None ->
+ let loc = decl.ptype_loc in
+ raise_errorf ~loc "%s: cannot deal with abstract types." plugin
+
+ | Ptype_open, _ ->
+ let loc = decl.ptype_loc in
+ raise_errorf ~loc "%s: cannot deal with open types." plugin
+
+(* -------------------------------------------------------------------------- *)
+
+(* [type_decl decl] generates the main visitor method associated with the type
+ declaration [decl], as well as the necessary auxiliary methods. It returns
+ no result. *)
+
+let type_decl (decl : type_declaration) : unit =
+ let alphas = poly_params decl in
+ generate_concrete_method
+ (local_tycon_visitor_method decl)
+ (lambdas (map tyvar_visitor_function alphas @ [env]) (visit_decl decl))
+ (quantify alphas (ty_arrows (map visitor_param_type alphas) (visitor_method_type decl)))
+
+(* -------------------------------------------------------------------------- *)
+
+(* [type_decls decls] processes the type declarations [decl] and produces a
+ list of structure items. It is the main entry point inside the body of
+ the functor [Setup]. *)
+
+let type_decls (decls : type_declaration list) : structure =
+ (* Analyze the type definitions, and populate our classes with methods. *)
+ iter type_decl decls;
+ (* Emit our preprocessor warnings (if any). *)
+ warnings() @
+ (* In the generated code, disable certain warnings, so that the user sees
+ no warnings, even if she explicitly enables them. We disable warnings
+ 26, 27 (unused variables) and 4 (fragile pattern matching; a feature
+ intentionally exploited by [iter2] and [map2]). *)
+ [ with_warnings "-4-26-27" (
+ (* Surround the generated code with floating attributes, which can be
+ used as markers to find and review the generated code. We use this
+ mechanism to show the generated code in the documentation. *)
+ floating "VISITORS.BEGIN" [] ::
+ (* Produce a class definition. *)
+ (* Our classes are parameterized over the type variable ['env]. They are
+ also parameterized over the type variable ['self], with a constraint
+ that this is the type of [self]. This trick allows us to omit the types
+ of the virtual methods, even if these types include type variables. *)
+ dump X.concrete X.ancestors [ ty_self, (NoVariance, NoInjectivity) ] pself X.name ::
+ floating "VISITORS.END" [] ::
+ []
+ )]
+
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* [type_decls decls] produces a list of structure items (that is, toplevel
+ definitions) associated with the type declarations [decls]. It is the
+ main entry point outside of the functor [Setup]. *)
+
+let type_decls ~options ~path:_ (decls : type_declaration list) : structure =
+ assert (decls <> []);
+ let module Process = Setup(Parse(struct
+ let loc = (VisitorsList.last decls).ptype_loc (* an approximation *)
+ let options = options
+ let decls = decls
+ end)) in
+ Process.type_decls decls
+
+(* -------------------------------------------------------------------------- *)
+
+(* Register our plugin with [ppx_deriving]. *)
+
+let () =
+ register (create plugin ~type_decl_str:type_decls ())
diff --git a/src/Visitors.mli b/src/Visitors.mli
new file mode 100644
index 0000000..d3e496f
--- /dev/null
+++ b/src/Visitors.mli
@@ -0,0 +1 @@
+(* This file intentionally empty. *)
diff --git a/src/VisitorsAnalysis.ml b/src/VisitorsAnalysis.ml
new file mode 100644
index 0000000..4e951a9
--- /dev/null
+++ b/src/VisitorsAnalysis.ml
@@ -0,0 +1,408 @@
+open Ppxlib
+open Result
+open Asttypes
+open Parsetree
+open Ast_helper
+open Ppx_deriving
+open VisitorsPlugin
+
+(* This module offers helper functions for abstract syntax tree analysis. *)
+
+(* -------------------------------------------------------------------------- *)
+
+type tycon = string
+type tyvar = string
+type tyvars = tyvar list
+
+(* -------------------------------------------------------------------------- *)
+
+(* Testing whether an identifier is valid. *)
+
+(* We use OCaml's lexer to analyze the string and check if it is a valid
+ identifier. This method is slightly unorthodox, as the lexer can have
+ undesired side effects, such as raising an [Error] exception or printing
+ warnings. We do our best to hide these effects. The strength of this
+ approach is to give us (at little cost) a correct criterion for deciding if
+ an identifier is valid. *)
+
+(* Note: [Location.formatter_for_warnings] appeared in OCaml 4.02.2. *)
+
+(* 2021/06/08 By default, [Parser] would be [Ppxlib.Parser], which exposes the
+ type [token] as an abstract type. Because we need the type [token] to be
+ concrete, we use [Ocaml_common.Parser] instead. [Ocaml_common] is part of
+ compiler-libs. *)
+
+type classification =
+ | LIDENT
+ | UIDENT
+ | OTHER
+
+let classify (s : string) : classification =
+ let lexbuf = Lexing.from_string s in
+ let backup = !Ocaml_common.Location.formatter_for_warnings in
+ let null = Format.formatter_of_buffer (Buffer.create 0) in
+ Ocaml_common.Location.formatter_for_warnings := null;
+ let result = try
+ let token1 = Lexer.token lexbuf in
+ let token2 = Lexer.token lexbuf in
+ let module Parser = Ocaml_common.Parser in
+ match token1, token2 with
+ | Parser.LIDENT _, Parser.EOF ->
+ LIDENT
+ | Parser.UIDENT _, Parser.EOF ->
+ UIDENT
+ | _, _ ->
+ OTHER
+ with Lexer.Error _ ->
+ OTHER
+ in
+ Ocaml_common.Location.formatter_for_warnings := backup;
+ result
+
+(* -------------------------------------------------------------------------- *)
+
+(* Testing if a string is a valid [mod_longident], i.e., a possibly-qualified
+ module identifier. *)
+
+(* We might wish to use OCaml's parser for this purpose, but [mod_longident] is
+ not declared as a start symbol. Furthermore, that would be perhaps slightly
+ too lenient, e.g., allowing whitespace and comments inside. Our solution is
+ to split at the dots and check that every piece is a valid module name. *)
+
+(* We used to use [Longident.parse] to do the splitting, but this function has
+ been deprecated as of 4.11.0, and its suggested replacements do not go as
+ far back in time as we need. So, we use our own variant of this code. *)
+
+let rec parse s n =
+ (* Parse the substring that extends from offset 0 to offset [n] excluded. *)
+ try
+ let i = String.rindex_from s (n - 1) '.' in
+ let segment = String.sub s (i + 1) (n - (i + 1)) in
+ Ldot (parse s i, segment)
+ with Not_found ->
+ Lident (String.sub s 0 n)
+
+let parse s =
+ parse s (String.length s)
+
+let is_valid_mod_longident (m : string) : bool =
+ String.length m > 0 &&
+ let ms = Longident.flatten_exn (parse m) in
+ List.for_all (fun m -> classify m = UIDENT) ms
+
+(* -------------------------------------------------------------------------- *)
+
+(* Testing if a string is a valid [class_longident], i.e., a possibly-qualified
+ class identifier. *)
+
+let is_valid_class_longident (m : string) : bool =
+ String.length m > 0 &&
+ match parse m with
+ | Lident c ->
+ classify c = LIDENT
+ | Ldot (m, c) ->
+ List.for_all (fun m -> classify m = UIDENT) (Longident.flatten_exn m) &&
+ classify c = LIDENT
+ | Lapply _ ->
+ assert false (* this cannot happen *)
+
+(* -------------------------------------------------------------------------- *)
+
+(* Testing if a string is a valid method name prefix. *)
+
+let is_valid_method_name_prefix (m : string) : bool =
+ String.length m > 0 &&
+ classify m = LIDENT
+
+(* -------------------------------------------------------------------------- *)
+
+(* Testing for the presence of attributes. *)
+
+(* We use [ppx_deriving] to extract a specific attribute from an attribute
+ list. By convention, an attribute named [foo] can also be referred to as
+ [visitors.foo] or as [deriving.visitors.foo]. *)
+
+(* [select foo attrs] extracts the attribute named [foo] from the attribute
+ list [attrs]. *)
+
+let select (foo : string) (attrs : attributes) : attribute option =
+ attr ~deriver:plugin foo attrs
+
+(* [present foo attrs] tests whether an attribute named [foo] is present
+ (with no argument) in the list [attrs]. *)
+
+let present (foo : string) (attrs : attributes) : bool =
+ Arg.get_flag ~deriver:plugin (select foo attrs)
+
+(* [opacity attrs] tests for the presence of an [@opaque] attribute. *)
+
+type opacity =
+ | Opaque
+ | NonOpaque
+
+let opacity (attrs : attributes) : opacity =
+ if present "opaque" attrs then Opaque else NonOpaque
+
+(* [name attrs] tests for the presence of a [@name] attribute, carrying a
+ payload of type [string]. We check that the payload is a valid (lowercase
+ or uppercase) identifier, because we intend to use it as the basis of a
+ method name. *)
+
+let identifier : string Arg.conv =
+ fun e ->
+ match Arg.string e with
+ | Error msg ->
+ Error msg
+ | Ok s ->
+ match classify s with
+ | LIDENT | UIDENT ->
+ Ok s
+ | OTHER ->
+ Error "identifier"
+
+let name (attrs : attributes) : string option =
+ Arg.get_attr ~deriver:plugin identifier (select "name" attrs)
+
+(* [build attrs] tests for the presence of a [@build] attribute,
+ carrying a payload that is an arbitrary OCaml expression. *)
+
+let build (attrs : attributes) : expression option =
+ Arg.get_attr ~deriver:plugin Arg.expr (select "build" attrs)
+
+(* [maybe ox y] returns [x] if present, otherwise [y]. *)
+
+let maybe (ox : 'a option) (y : 'a) : 'a =
+ match ox with Some x -> x | None -> y
+
+(* -------------------------------------------------------------------------- *)
+
+(* When parsing a record declaration, the OCaml parser attaches attributes
+ with field labels, whereas the user might naturally expect them to be
+ attached with the type. We rectify this situation by copying all attributes
+ from the label to the type. This might seem dangerous, but we use it only
+ to test for the presence of an [@opaque] attribute. *)
+
+let paste (ty : core_type) (attrs : attributes) : core_type =
+ { ty with ptyp_attributes = attrs @ ty.ptyp_attributes }
+
+let fix (ld : label_declaration) : label_declaration =
+ { ld with pld_type = paste ld.pld_type ld.pld_attributes }
+
+let fix =
+ List.map fix
+
+(* -------------------------------------------------------------------------- *)
+
+(* [type_param_to_tyvar] expects a type parameter as found in the field
+ [ptype_params] of a type definition, and returns the underlying type
+ variable. *)
+
+let type_param_to_tyvar ((ty, _) : core_type * (variance * injectivity)) : tyvar =
+ match ty.ptyp_desc with
+ | Ptyp_var tv ->
+ tv
+ | Ptyp_any ->
+ (* This error occurs if a formal type parameter is a wildcard [_].
+ We could support this form, but it makes life slightly simpler
+ to disallow it. It is usually used only in GADTs anyway. *)
+ raise_errorf ~loc:ty.ptyp_loc
+ "%s: every formal type parameter should be named." plugin
+ | _ ->
+ assert false
+
+let type_params_to_tyvars =
+ List.map type_param_to_tyvar
+
+(* [decl_params decl] returns the type parameters of the declaration [decl]. *)
+
+let decl_params (decl : type_declaration) : tyvars =
+ type_params_to_tyvars decl.ptype_params
+
+(* [is_local decls tycon] tests whether the type constructor [tycon] is
+ declared by the type declarations [decls]. If so, it returns the
+ corresponding declaration. *)
+
+let rec is_local (decls : type_declaration list) (tycon : tycon)
+: type_declaration option =
+ match decls with
+ | [] ->
+ None
+ | decl :: decls ->
+ if decl.ptype_name.txt = tycon then
+ Some decl
+ else
+ is_local decls tycon
+
+let is_local (decls : type_declaration list) (tycon : Longident.t)
+: type_declaration option =
+ match tycon with
+ | Lident tycon ->
+ is_local decls tycon
+ | Ldot _
+ | Lapply _ ->
+ None
+
+(* -------------------------------------------------------------------------- *)
+
+(* [occurs_type alpha ty] tests whether the type variable [alpha] occurs in
+ the type [ty]. This function goes down into all OCaml types, even those
+ that are not supported by [visitors]. *)
+
+exception Occurs of loc
+
+let rec occurs_type (alpha : tyvar) (ty : core_type) : unit =
+ match ty.ptyp_desc with
+ | Ptyp_any ->
+ ()
+ | Ptyp_var beta ->
+ if alpha = beta then
+ raise (Occurs ty.ptyp_loc)
+ | Ptyp_alias (ty, _) ->
+ (* This is not a binder; just go down into it. *)
+ occurs_type alpha ty
+ | Ptyp_arrow (_, ty1, ty2) ->
+ occurs_types alpha [ ty1; ty2 ]
+ | Ptyp_tuple tys
+ | Ptyp_constr (_, tys)
+ | Ptyp_class (_, tys) ->
+ occurs_types alpha tys
+ | Ptyp_object (fields, _) ->
+ fields
+ |> List.map VisitorsCompatibility.object_field_to_core_type
+ |> occurs_types alpha
+ | Ptyp_variant (fields, _, _) ->
+ List.iter (occurs_row_field alpha) fields
+ | Ptyp_poly (qs, ty) ->
+ let qs : string list = VisitorsCompatibility.quantifiers qs in
+ (* The type variables in [qs] are bound. *)
+ if not (occurs_quantifiers alpha qs) then
+ occurs_type alpha ty
+ | Ptyp_package (_, ltys) ->
+ List.iter (fun (_, ty) -> occurs_type alpha ty) ltys
+ | Ptyp_extension (_, payload) ->
+ occurs_payload alpha payload
+
+and occurs_types alpha tys =
+ List.iter (occurs_type alpha) tys
+
+and occurs_row_field alpha field =
+ field
+ |> VisitorsCompatibility.row_field_to_core_types
+ |> occurs_types alpha
+
+and occurs_quantifiers alpha (qs : string list) =
+ List.mem alpha qs
+
+and occurs_payload alpha = function
+ | PTyp ty ->
+ occurs_type alpha ty
+ (* | PStr _ | PPat _ *)
+ (* | PSig _ (* >= 4.03 *) *)
+ | _ ->
+ (* We assume that these cases won't arise or won't have any free type
+ variables in them. *)
+ ()
+
+(* -------------------------------------------------------------------------- *)
+
+(* An error message about an unsupported type. *)
+
+let unsupported ty =
+ let loc = ty.ptyp_loc in
+ raise_errorf ~loc
+ "%s: cannot deal with the type %s.\n\
+ Consider annotating it with [@opaque]."
+ plugin
+ (string_of_core_type ty)
+
+(* -------------------------------------------------------------------------- *)
+
+(* [at_opaque f ty] applies the function [f] to every [@opaque] component of
+ the type [ty]. *)
+
+let rec at_opaque (f : core_type -> unit) (ty : core_type) : unit =
+ match opacity ty.ptyp_attributes, ty.ptyp_desc with
+ | NonOpaque, Ptyp_any
+ | NonOpaque, Ptyp_var _ ->
+ ()
+ | NonOpaque, Ptyp_tuple tys
+ | NonOpaque, Ptyp_constr (_, tys) ->
+ List.iter (at_opaque f) tys
+ | Opaque, _ ->
+ f ty
+ | NonOpaque, Ptyp_arrow _
+ | NonOpaque, Ptyp_object _
+ | NonOpaque, Ptyp_class _
+ | NonOpaque, Ptyp_alias _
+ | NonOpaque, Ptyp_variant _
+ | NonOpaque, Ptyp_poly _
+ | NonOpaque, Ptyp_package _
+ | NonOpaque, Ptyp_extension _ ->
+ unsupported ty
+
+(* -------------------------------------------------------------------------- *)
+
+(* [check_poly_under_opaque alphas tys] checks that none of the type variables
+ [alphas] appears under [@opaque] in the types [tys]. *)
+
+let check_poly_under_opaque alphas tys =
+ List.iter (fun alpha ->
+ List.iter (fun ty ->
+ at_opaque (fun ty ->
+ try
+ occurs_type alpha ty
+ with Occurs loc ->
+ raise_errorf ~loc
+ "%s: a [polymorphic] type variable must not appear under @opaque."
+ plugin
+ ) ty
+ ) tys
+ ) alphas
+
+(* -------------------------------------------------------------------------- *)
+
+(* [subst_type sigma ty] applies [sigma], a substitution of types for type
+ variables, to the type [ty].
+
+ [rename_type rho ty] applies [rho], a renaming of type variables, to the
+ type [ty]. *)
+
+(* We do not go down into [@opaque] types. We replace every opaque type with a
+ wildcard [_]. Because we have checked that [poly] variables do not appear
+ under [@opaque], this is good enough: there is never a need for an
+ explicitly named/quantified type variable to describe an opaque
+ component. *)
+
+type substitution =
+ tyvar -> core_type
+
+type renaming =
+ tyvar -> tyvar
+
+let rec subst_type (sigma : substitution) (ty : core_type) : core_type =
+ match opacity ty.ptyp_attributes, ty.ptyp_desc with
+ | NonOpaque, Ptyp_any ->
+ ty
+ | NonOpaque, Ptyp_var alpha ->
+ sigma alpha
+ | NonOpaque, Ptyp_tuple tys ->
+ { ty with ptyp_desc = Ptyp_tuple (subst_types sigma tys) }
+ | NonOpaque, Ptyp_constr (tycon, tys) ->
+ { ty with ptyp_desc = Ptyp_constr (tycon, subst_types sigma tys) }
+ | Opaque, _ ->
+ Typ.any()
+ | NonOpaque, Ptyp_arrow _
+ | NonOpaque, Ptyp_object _
+ | NonOpaque, Ptyp_class _
+ | NonOpaque, Ptyp_alias _
+ | NonOpaque, Ptyp_variant _
+ | NonOpaque, Ptyp_poly _
+ | NonOpaque, Ptyp_package _
+ | NonOpaque, Ptyp_extension _ ->
+ unsupported ty
+
+and subst_types sigma tys =
+ List.map (subst_type sigma) tys
+
+let rename_type (rho : renaming) (ty : core_type) : core_type =
+ subst_type (fun alpha -> Typ.var (rho alpha)) ty
diff --git a/src/VisitorsCompatibility.ml b/src/VisitorsCompatibility.ml
new file mode 100644
index 0000000..0e8450b
--- /dev/null
+++ b/src/VisitorsCompatibility.ml
@@ -0,0 +1,103 @@
+let mknoloc = Location.mknoloc
+open Ppxlib
+open Asttypes
+open Parsetree
+open Ast_helper
+
+(* OCaml's abstract syntax tree evolves with time. We depend on this tree
+ because we analyze it (that is, we analyze type definitions) and because we
+ construct it (that is, we generate code). This module was initially created
+ to gather the ugly bits whose definition varies depending on the version of
+ OCaml that we are working with. That said, since we have switched to using
+ ppxlib, my understanding is that we always work with the latest version of
+ the AST. More precisely, the version of the AST that we get no longer
+ depends on which OCaml compiler we are using; it depends on which version
+ of ppxlib we are using. At the time of writing, we depend on ppxlib 0.9.0
+ or newer, which implies that we get an AST for OCaml 4.08 or newer. See
+ https://github.com/ocaml-ppx/ppxlib/blob/master/CHANGES.md *)
+
+(* Constructing an arrow type. *)
+
+let ty_arrow (a : core_type) (b : core_type) : core_type =
+ Typ.arrow Nolabel a b
+
+(* Constructing a function. *)
+
+let plambda (p : pattern) (e : expression) : expression =
+ Exp.fun_ Nolabel None p e
+
+(* [ld_label] and [ld_ty] extract a label and type out of an OCaml record label
+ declaration. *)
+
+let ld_label (ld : label_declaration) : label =
+ ld.pld_name.txt
+
+let ld_labels =
+ List.map ld_label
+
+let ld_ty (ld : label_declaration) : core_type =
+ ld.pld_type
+
+let ld_tys =
+ List.map ld_ty
+
+(* Between OCaml 4.04 and OCaml 4.05, the types of several functions in [Ast_helper]
+ have changed. They used to take arguments of type [string], and now take arguments
+ of type [str], thus requiring a conversion. These functions include [Typ.object_],
+ [Typ.poly], [Exp.send], [Exp.newtype], [Ctf.val_], [Ctf.method_], [Cf.inherit_]. *)
+
+type str =
+ string Location.loc
+
+let string2str (s : string) : str =
+ mknoloc s
+
+let str2string (s : str) : string =
+ s.txt
+
+let typ_poly (tyvars : string list) (cty : core_type) : core_type =
+ Typ.poly (List.map string2str tyvars) cty
+
+let exp_send (e : expression) (m : string) : expression =
+ Exp.send e (string2str m)
+
+(* In the data constructor [Ptyp_poly (qs, ty)], the type of [qs] has changed from
+ [string list] to [string loc list] between OCaml 4.04 and 4.05.
+ See commit b0e880c448c78ed0cedff28356fcaf88f1436eef.
+ The function [quantifiers] compensates for this. *)
+
+let quantifiers qs : string list =
+ List.map str2string qs
+
+(* In the data constructor [Ptyp_object (methods, _)], the type of [methods] has
+ changed from [(string loc * attributes * core_type) list] in OCaml 4.05 to
+ [object_field list] in OCaml 4.06. *)
+
+let object_field_to_core_type (field : object_field) : core_type =
+ match field.pof_desc with
+ | Otag (_, ty) -> ty
+ | Oinherit ty -> ty
+ (* this may seem nonsensical, but (so far) is used only in the
+ function [occurs_type], where we do not care what the types
+ mean *)
+
+let row_field_to_core_types (field : row_field) : core_type list =
+ match field.prf_desc with
+ | Rtag (_, _, tys) ->
+ tys
+ | Rinherit ty ->
+ [ ty ]
+
+(* -------------------------------------------------------------------------- *)
+
+(* [floating s items] produces a floating attribute whose name is [s] and
+ whose payload is the list of structure items [items]. *)
+
+(* The type [attribute] is defined in 4.07 as [string loc * payload], but in
+ 4.08 its definition changes to a record type and the function [Attr.mk]
+ appears. *)
+
+let floating (s : string) (items : structure) : structure_item =
+ let name = mknoloc s
+ and payload = PStr items in
+ Str.attribute (Attr.mk name payload)
diff --git a/src/VisitorsGeneration.ml b/src/VisitorsGeneration.ml
new file mode 100644
index 0000000..a7f28ec
--- /dev/null
+++ b/src/VisitorsGeneration.ml
@@ -0,0 +1,586 @@
+open Ppxlib
+let mknoloc = Ocaml_common.Location.mknoloc
+open Asttypes
+open Parsetree
+open Ast_helper
+open Ppx_deriving.Ast_convenience
+open VisitorsList
+open VisitorsAnalysis
+open VisitorsCompatibility
+
+(* This module offers helper functions for code generation. *)
+
+(* -------------------------------------------------------------------------- *)
+
+(* Type abbreviations. *)
+
+type variable = string
+type datacon = string
+type label = string
+type classe = string
+type methode = string
+type tyvar = string
+
+type variables = variable list
+type tyvars = tyvar list
+type core_types = core_type list
+type patterns = pattern list
+type expressions = expression list
+
+(* -------------------------------------------------------------------------- *)
+
+(* We should in principle ensure that our code makes sense even if the
+ standard names that we rely upon are shadowed by the user. *)
+
+(* This is made slightly difficult by the fact that the name [Pervasives]
+ has been deprecated in favor of [Stdlib] in OCaml 4.07. *)
+
+(* One viable approach would be to define the names that we need in the
+ library [VisitorsRuntime], then refer to this library in the generated
+ code. *)
+
+(* One problem is that defining an alias for the standard operator (&&)
+ causes it to become strict instead of lazy! So we cannot define an
+ alias for it. *)
+
+(* Let's just cross our fingers and assume that the user won't shadow
+ the standard names that we need. *)
+
+let pervasive (x : string) : Longident.t =
+ Lident x
+
+(* We normally place an improbable prefix in front of our private (local)
+ variables, so as to make sure that we do not shadow user variables that
+ are used in [@build] code fragments. *)
+
+(* When producing code for inclusion in the documentation, we remove this
+ prefix, just so that things look pretty. We rely on an undocumented
+ environment variable to toggle this behavior. *)
+
+let improbable (x : string) : string =
+ try
+ let _ = Sys.getenv "VISITORS_BUILDING_DOCUMENTATION" in
+ x
+ with Not_found ->
+ "_visitors_" ^ x
+
+(* -------------------------------------------------------------------------- *)
+
+(* Types. *)
+
+let ty_var (alpha : tyvar) : core_type =
+ Typ.var alpha
+
+let ty_vars (alphas : tyvars) : core_types =
+ List.map ty_var alphas
+
+let ty_any =
+ Typ.any()
+
+let ty_unit =
+ tconstr "unit" []
+
+(* For [ty_arrow], see [VisitorsCompatibility]. *)
+
+let ty_arrows : core_types -> core_type -> core_type =
+ List.fold_right ty_arrow
+
+(* [decl_type decl] turns a declaration of the type ['a foo] into a the type
+ ['a foo]. *)
+
+let decl_type (decl : type_declaration) : core_type =
+ tconstr decl.ptype_name.txt (ty_vars (decl_params decl))
+
+(* -------------------------------------------------------------------------- *)
+
+(* [unit] produces a unit constant. [tuple] produces a tuple. [record]
+ produces a record. These functions already exist; we redefine them without
+ any optional arguments so as avoid OCaml's warning 48 (implicit elimination
+ of optional arguments). *)
+
+let unit() =
+ unit()
+
+let tuple es =
+ tuple es
+
+let record les =
+ record les
+
+(* -------------------------------------------------------------------------- *)
+
+(* [number i thing] constructs an English description of "[i] thing(s)". *)
+
+let number i s =
+ match i with
+ | 0 ->
+ Printf.sprintf "zero %s" s
+ | 1 ->
+ Printf.sprintf "one %s" s
+ | _ ->
+ Printf.sprintf "%d %ss" i s
+
+(* -------------------------------------------------------------------------- *)
+
+(* [eident] converts a (possibly-qualified) identifier to an expression. *)
+
+let eident (id : Longident.t) : expression =
+ Exp.ident (mknoloc id)
+
+(* -------------------------------------------------------------------------- *)
+
+(* [pvars] converts a list of variables to a list of patterns. *)
+
+let pvars (xs : variables) : patterns =
+ List.map (fun x -> pvar x) xs
+
+(* [evars] converts a list of variables to a list of expressions. *)
+
+let evars (xs : variables) : expressions =
+ List.map (fun x -> evar x) xs
+
+(* [pvarss] converts a matrix of variables to a matrix of patterns. *)
+
+let pvarss (xss : variables list) : patterns list =
+ List.map pvars xss
+
+(* [evarss] converts a matrix of variables to a matrix of expressions. *)
+
+let evarss (xss : variables list) : expressions list =
+ List.map evars xss
+
+(* -------------------------------------------------------------------------- *)
+
+(* [wildcards] converts a list of anything to a list of wildcard patterns. *)
+
+let wildcards xs =
+ List.map (fun _ -> Pat.any()) xs
+
+(* -------------------------------------------------------------------------- *)
+
+(* [plambda p e] constructs a function [fun p -> e]. *)
+
+(* For [plambda], see [VisitorsCompatibility]. *)
+
+(* [lambda x e] constructs a function [fun x -> e]. *)
+
+let lambda (x : variable) (e : expression) : expression =
+ plambda (pvar x) e
+
+(* [plambdas ps e] constructs a multi-argument function [fun ps -> e]. *)
+
+let plambdas (ps : patterns) (e : expression) : expression =
+ List.fold_right plambda ps e
+
+(* [lambdas xs e] constructs a multi-argument function [fun xs -> e]. *)
+
+let lambdas (xs : variables) (e : expression) : expression =
+ List.fold_right lambda xs e
+
+(* -------------------------------------------------------------------------- *)
+
+(* [app] works like [Ast_convenience.app] (which it shadows), except it avoids
+ constructing nested applications of the form [(f x) y], transforming them
+ instead into a single application [f x y]. The difference is probably just
+ cosmetic. *)
+
+let app (e : expression) (es2 : expressions) : expression =
+ match e.pexp_desc with
+ | Pexp_apply (e1, les1) ->
+ let les2 = List.map (fun e -> Label.nolabel, e) es2 in
+ { e with pexp_desc = Pexp_apply (e1, les1 @ les2) }
+ | _ ->
+ app e es2
+
+(* -------------------------------------------------------------------------- *)
+
+(* [sequence es] constructs a sequence of the expressions [es]. *)
+
+let sequence (es : expressions) : expression =
+ (* Using [fold_right1] instead of [List.fold_right] allows us to get
+ rid of a final [()] constant at the end of the sequence. Cosmetic. *)
+ fold_right1
+ (fun e accu -> Exp.sequence e accu)
+ es
+ (unit())
+
+(* -------------------------------------------------------------------------- *)
+
+(* [vblet1 vb e] constructs a single [let] binding. *)
+
+let vblet1 (vb : value_binding) (e : expression) : expression =
+ Exp.let_ Nonrecursive [vb] e
+
+(* [let1 x e1 e2] constructs a single [let] binding. *)
+
+let let1 (x : variable) (e1 : expression) (e2 : expression) : expression =
+ vblet1 (Vb.mk (pvar x) e1) e2
+
+(* [let1p x y e1 e2] constructs a single [let] binding of a pair. *)
+
+let let1p (x, y : variable * variable) (e1 : expression) (e2 : expression) : expression =
+ vblet1 (Vb.mk (ptuple [pvar x; pvar y]) e1) e2
+
+(* [vbletn vbs e] constructs a series of nested [let] bindings. *)
+
+let vbletn (vbs : value_binding list) (e : expression) : expression =
+ List.fold_right vblet1 vbs e
+
+(* [letn xs es e] constructs a series of nested [let] bindings. *)
+
+let letn (xs : variables) (es : expressions) (e : expression) =
+ List.fold_right2 let1 xs es e
+
+(* [letnp xs ys es e] constructs a series of nested [let] bindings of pairs. *)
+
+let letnp (xs : variables) (ys : variables) (es : expressions) (e : expression) =
+ List.fold_right2 let1p (List.combine xs ys) es e
+
+(* -------------------------------------------------------------------------- *)
+
+(* [access x label] constructs a record access expression [x.label]. *)
+
+let access (x : variable) (label : label) : expression =
+ Exp.field (evar x) (mknoloc (Lident label))
+
+(* [accesses labels xs] constructs a matrix of record access expressions of
+ the form [x.label]. There is a row for every [label] and a column for every
+ [x]. *)
+
+let accesses (xs : variables) (labels : label list) : expressions list =
+ List.map (fun label -> List.map (fun x -> access x label) xs) labels
+
+(* -------------------------------------------------------------------------- *)
+
+(* [ptuple] is [Ast_convenience.ptuple], deprived of its optional arguments. *)
+
+let ptuple (ps : patterns) : pattern =
+ ptuple ps
+
+(* [ptuples] is [map ptuple]. *)
+
+let ptuples (pss : patterns list) : patterns =
+ List.map ptuple pss
+
+(* -------------------------------------------------------------------------- *)
+
+(* The Boolean expressions [false] and [true]. *)
+
+let efalse : expression =
+ Exp.construct (mknoloc (Lident "false")) None
+
+let etrue : expression =
+ Exp.construct (mknoloc (Lident "true")) None
+
+(* -------------------------------------------------------------------------- *)
+
+(* [conjunction es] constructs a Boolean conjunction of the expressions [es]. *)
+
+let conjunction : expression =
+ eident (pervasive "&&")
+
+let conjunction e1 e2 =
+ app conjunction [e1; e2]
+
+let conjunction (es : expressions) : expression =
+ fold_right1 conjunction es etrue
+
+(* -------------------------------------------------------------------------- *)
+
+(* [eassertfalse] is the expression [assert false]. *)
+
+let eassertfalse : expression =
+ Exp.assert_ efalse
+
+(* -------------------------------------------------------------------------- *)
+
+(* [eforce e] is the expression [Lazy.force e]. *)
+
+let eforce : expression =
+ eident (parse "Lazy.force")
+ (* danger: the module name [Lazy] must not be shadowed. *)
+
+let eforce (e : expression) : expression =
+ app eforce [e]
+
+(* -------------------------------------------------------------------------- *)
+
+(* [eqphy e1 e2] is the expression [e1 == e2]. *)
+
+let eqphy : expression =
+ eident (pervasive "==")
+
+let eqphy (e1 : expression) (e2 : expression) : expression =
+ app eqphy [e1; e2]
+
+(* [eqphys es1 es2] is the conjunction of the expressions [e1 == e2]. *)
+
+let eqphys (es1 : expressions) (es2 : expressions) : expression =
+ assert (List.length es1 = List.length es2);
+ conjunction (List.map2 eqphy es1 es2)
+
+(* -------------------------------------------------------------------------- *)
+
+(* [efail s] generates a call to [VisitorsRuntime.fail]. The parameter [s] is
+ a string, which could represent the place where a failure occurred, or the
+ reason why a failure occurred. As of now, it is unused. *)
+
+let efail : expression =
+ eident (Ldot (Lident "VisitorsRuntime", "fail"))
+ (* danger: the module name [VisitorsRuntime] must not be shadowed. *)
+
+let efail (_ : string) : expression =
+ app efail [ unit() ]
+
+(* -------------------------------------------------------------------------- *)
+
+(* [include_ e] constructs an [include] declaration. *)
+
+let include_ (e : module_expr) : structure_item =
+ Str.include_ {
+ pincl_mod = e;
+ pincl_loc = Location.none;
+ pincl_attributes = [];
+ }
+
+(* -------------------------------------------------------------------------- *)
+
+(* [with_warnings w items] wraps the structure items [items] in such a way
+ that the warning directive [w] is applied to these items. Technically, this
+ is done by emitting [include struct [@@@ocaml.warning <w>] <items> end]. *)
+
+let with_warnings (w : string) (items : structure_item list) : structure_item =
+ include_ (Mod.structure (
+ floating "ocaml.warning" [ Str.eval (Exp.constant (Const.string w)) ]
+ :: items
+ ))
+
+(* -------------------------------------------------------------------------- *)
+
+(* [class1 concrete ancestors params name self fields] builds a class
+ declaration and packages it as a structure item. (This implies that it
+ cannot be recursive with other class declarations). *)
+
+let class1
+ (concrete : bool)
+ (params : (core_type * (variance * injectivity)) list)
+ (name : classe)
+ (self : pattern)
+ (fields : class_field list)
+ : structure_item =
+ Str.class_ [{
+ pci_virt = if concrete then Concrete else Virtual;
+ pci_params = params;
+ pci_name = mknoloc name;
+ pci_expr = Cl.structure (Cstr.mk self fields);
+ pci_loc = !default_loc;
+ pci_attributes = [];
+ }]
+
+(* -------------------------------------------------------------------------- *)
+
+(* [inherit_ c tys] builds an [inherit] clause, where the superclass is [c]
+ and its actual type parameters are [tys]. No [super] identifier is bound. *)
+
+let inherit_ (c : Longident.t) (tys : core_types) : class_field =
+ Cf.inherit_ Fresh (Cl.constr (mknoloc c) tys) None
+
+(* -------------------------------------------------------------------------- *)
+
+(* An algebraic data type of the methods that we generate. These include
+ concrete methods (with code) and virtual methods (without code). They may
+ be public or private. The method type is optional. If omitted, then
+ it is inferred by OCaml. If present, it can be a polymorphic type. *)
+
+type meth =
+ Meth of private_flag * methode * expression option * core_type option
+
+let concrete_method p m e oty =
+ Meth (p, m, Some e, oty)
+
+let virtual_method p m oty =
+ Meth (p, m, None, oty)
+
+(* -------------------------------------------------------------------------- *)
+
+(* Converting a method description to OCaml abstract syntax. *)
+
+let oe2cfk (oe : expression option) (oty : core_type option) : class_field_kind =
+ match oe, oty with
+ | Some e, Some _ ->
+ Cf.concrete Fresh (Exp.poly e oty)
+ | Some e, None ->
+ Cf.concrete Fresh e
+ | None, Some ty ->
+ Cf.virtual_ ty
+ | None, None ->
+ Cf.virtual_ ty_any
+
+let meth2cf (Meth (p, m, oe, oty)) : class_field =
+ Cf.method_ (mknoloc m) p (oe2cfk oe oty)
+
+(* -------------------------------------------------------------------------- *)
+
+(* [method_name] extracts a method name out of a method description. *)
+
+let method_name (Meth (_, m, _, _)) : string =
+ m
+
+(* -------------------------------------------------------------------------- *)
+
+(* [is_virtual] tests whether a method description represents a virtual
+ method. *)
+
+let is_virtual (Meth (_, _, oe, _)) : bool =
+ oe = None
+
+(* -------------------------------------------------------------------------- *)
+
+(* [send o m es] produces a call to the method [o#m] with arguments [es]. *)
+
+let send (o : variable) (m : methode) (es : expressions) : expression =
+ app (exp_send (evar o) m) es
+
+(* -------------------------------------------------------------------------- *)
+
+(* An algebraic data type of the ``hoisted expressions'' that we generate. *)
+
+(* A ``hoisted expression'' is evaluated at most once after the object is
+ allocated. Its value is stored in an instance field. We allow such an
+ expression to reference [self], as long as it does not actually invoke any
+ methods. *)
+
+type hoisted =
+ Hoisted of string (* the name of the instance field *)
+ * expression (* the hoisted expression *)
+
+(* -------------------------------------------------------------------------- *)
+
+(* Converting a hoisted field description to OCaml abstract syntax. *)
+
+(* We generate a mutable field declaration, followed with an initialization:
+
+ val mutable x = lazy (assert false)
+ initializer x <- lazy e
+
+ We must do this in two steps because the expression [e] might contain
+ references to [self], which are invalid in a field declaration, whereas
+ they are allowed in an initializer.
+
+ The potential danger in this idiom lies in forcing [x] before the
+ initializer has finished running, leading to an assertion failure.
+ This should not happen if [e] does not perform any method calls
+ or read any fields. *)
+
+let hoisted2cf (Hoisted (x, e)) : class_field list =
+ [
+ Cf.val_ (mknoloc x) (Mutable) (Cf.concrete Fresh (Exp.lazy_ eassertfalse));
+ Cf.initializer_ (Exp.setinstvar (mknoloc x) (Exp.lazy_ e))
+ ]
+
+(* -------------------------------------------------------------------------- *)
+
+(* A facility for generating a class. *)
+
+module ClassFieldStore () : sig
+
+ (* [generate meth] adds [meth] to the list of methods. *)
+ val generate: meth -> unit
+
+ (* [hoist e] causes the expression [e] to be hoisted, that is, computed
+ once after the object is allocated. The result of evaluating [e] is
+ stored in a field. The call [hoist e] returns an expression which
+ reads this field. *)
+ val hoist: expression -> expression
+
+ (* [dump concrete ancestors params self c] returns a class definition. *)
+ val dump:
+ bool ->
+ Longident.t list ->
+ (core_type * (variance * injectivity)) list ->
+ pattern ->
+ classe ->
+ structure_item
+
+end = struct
+
+ let meths : meth list ref =
+ ref []
+
+ let generate meth =
+ meths := meth :: !meths
+
+ let dump () : class_field list =
+ let methods = List.rev !meths in
+ (* Move all of the virtual methods up front. If two virtual methods have
+ the same name, keep only one of them. This is useful because we allow
+ a virtual method declaration to be generated several times. In fact,
+ OCaml supports this, but it looks tidier if we remove duplicates. *)
+ let virtual_methods, concrete_methods = List.partition is_virtual methods in
+ let cmp meth1 meth2 = Stdlib.compare (method_name meth1) (method_name meth2) in
+ let virtual_methods = VisitorsList.weed cmp virtual_methods in
+ let methods = virtual_methods @ concrete_methods in
+ List.map meth2cf methods
+
+ let hoisted : hoisted list ref =
+ ref []
+
+ let fresh : unit -> int =
+ let c = ref 0 in
+ fun () ->
+ let x = !c in
+ c := x + 1;
+ x
+
+ let hoist (e : expression) : expression =
+ let x = Printf.sprintf "h%d" (fresh()) in
+ hoisted := Hoisted (x, e) :: !hoisted;
+ eforce (evar x)
+
+ let dump concrete ancestors params self c : structure_item =
+ class1 concrete params c self (
+ (* [inherit] clauses. *)
+ (* We ARBITRARILY assume that every ancestor class is parameterized
+ with ONE type parameter. *)
+ List.map (fun c -> inherit_ c [ ty_any ]) ancestors @
+ (* Hoisted expressions. *)
+ List.flatten (List.map hoisted2cf (List.rev !hoisted)) @
+ (* Methods. *)
+ dump()
+ )
+
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* A facility for emitting preprocessor warnings. *)
+
+(* Warnings must be emitted under the form of [ppwarning] attributes, placed
+ in the generated code. This is not very convenient; we must store these
+ warnings, waiting for a convenient time to emit them. *)
+
+module WarningStore () : sig
+
+ (* [warning loc format ...] emits a warning. *)
+ val warning: loc -> ('a, unit, string, unit) format4 -> 'a
+
+ (* [warnings()] returns a list of all warnings emitted so far. *)
+ val warnings: unit -> structure
+
+end = struct
+
+ let warnings : attribute list ref =
+ ref []
+
+ let warning loc msg =
+ warnings := attribute_of_warning loc msg :: !warnings
+
+ let warning loc format =
+ Printf.ksprintf (warning loc) format
+
+ let warnings () =
+ let ws = !warnings in
+ warnings := [];
+ List.map (fun a -> Str.attribute a) (List.rev ws)
+
+end
diff --git a/src/VisitorsList.ml b/src/VisitorsList.ml
new file mode 100644
index 0000000..9910463
--- /dev/null
+++ b/src/VisitorsList.ml
@@ -0,0 +1,125 @@
+open List
+
+(* [last xs] returns the last element of the nonempty list [xs]. *)
+
+let rec last1 x xs =
+ match xs with
+ | [] ->
+ x
+ | x :: xs ->
+ last1 x xs
+
+let last xs =
+ match xs with
+ | [] ->
+ assert false
+ | x :: xs ->
+ last1 x xs
+
+(* [interval i j] constructs a list representation of the semi-open interval
+ [i..j). *)
+
+let rec interval i j : int list =
+ if i < j then
+ i :: interval (i + 1) j
+ else
+ []
+
+(* [init i j f] constructs a list of the values [f i] up to [f (j - 1)]. *)
+
+let init i j (f : int -> 'a) : 'a list =
+ map f (interval i j)
+
+(* [is_matrix m n xss] checks that [xss] is an [m]-by-[n] matrix, represented
+ as a list of lists. *)
+
+let is_matrix m n (xss : _ list list) =
+ length xss = m && for_all (fun xs -> length xs = n) xss
+
+(* [transpose n xss] transposes a matrix, represented as a list of lists.
+ The parameter [n] is the width of the matrix, and is really useful only
+ in the case where the matrix has zero height, in which case [transpose]
+ constructs a matrix of height [n] and zero width. *)
+
+let transpose (n : int) (xss : 'a list list) : 'a list list =
+ let m = length xss in
+ assert (is_matrix m n xss);
+ (* Convert [xss] to an array, for speed. *)
+ let xss : 'a array array =
+ Array.(map of_list (of_list xss))
+ in
+ (* We have an [m]-by-[n] matrix, and construct an [n]-by-[m] matrix. *)
+ init 0 n (fun j ->
+ init 0 m (fun i ->
+ xss.(i).(j)
+ )
+ )
+
+(* [hextend xs n f] extends the vertical vector [xs] to a matrix of width [n].
+ A vector element [x] is turned into [f j x] in the [j]-th row. *)
+
+let hextend (xs : 'a list) (n : int) (f : int -> 'a -> 'a) : 'a list list =
+ map (fun x -> init 0 n (fun j -> f j x)) xs
+
+(* [uniq cmp xs] assumes that the list [xs] is sorted according to the
+ ordering [cmp] and returns the list [xs] deprived of any duplicate
+ elements. *)
+
+let rec uniq1 cmp x ys =
+ match ys with
+ | [] ->
+ []
+ | y :: ys ->
+ if cmp x y = 0 then
+ uniq1 Stdlib.compare x ys
+ else
+ y :: uniq1 cmp y ys
+
+let uniq cmp xs =
+ match xs with
+ | [] ->
+ []
+ | x :: xs ->
+ x :: uniq1 cmp x xs
+
+(* [weed cmp xs] returns the list [xs] deprived of any duplicate elements. *)
+
+let weed cmp xs =
+ uniq cmp (List.sort cmp xs)
+
+(* [fold_right1] is like [fold_right], but uses the last element of the list
+ (if the list is nonempty) as the initial accumulator, saving one call to
+ the binary operation [f]. This is equivalent to [fold_right] if [accu] is
+ a right unit for [f]. *)
+
+let fold_right1 f xs accu =
+ match List.rev xs with
+ | [] ->
+ accu
+ | x :: xs ->
+ let xs = List.rev xs in
+ (* We have decomposed [xs] as [xs] followed with [x]. We can now
+ ignore [accu] and use [x] as the initial accumulator in our
+ right-to-left sweep of the list. *)
+ List.fold_right f xs x
+
+(* [fold_left1] is like [fold_left], but uses the first element of the list
+ (if the list is nonempty) as the initial accumulator, saving one call to
+ the binary operation [f]. This is equivalent to [fold_left] if [accu] is
+ a left unit for [f]. *)
+
+let fold_left1 f accu xs =
+ match xs with
+ | [] ->
+ accu
+ | x :: xs ->
+ (* We can ignore [accu] and use [x] as the initial accumulator in
+ our left-to-right sweep of the list. *)
+ List.fold_left f x xs
+
+(* [filter2 f xs ys] returns the list of elements [y] in [ys] such that
+ the corresponding element [x] in [xs] satisfies [f]. *)
+
+let filter2 f xs ys =
+ assert (length xs = length ys);
+ map snd (filter (fun (x, _y) -> f x) (combine xs ys))
diff --git a/src/VisitorsPlugin.ml b/src/VisitorsPlugin.ml
new file mode 100644
index 0000000..113488e
--- /dev/null
+++ b/src/VisitorsPlugin.ml
@@ -0,0 +1,4 @@
+(* The name of our [ppx_deriving] plugin. *)
+
+let plugin =
+ "visitors"
diff --git a/src/VisitorsSettings.ml b/src/VisitorsSettings.ml
new file mode 100644
index 0000000..f7b7d1d
--- /dev/null
+++ b/src/VisitorsSettings.ml
@@ -0,0 +1,371 @@
+open Result
+open VisitorsString
+open List
+let sprintf = Printf.sprintf
+open Ppxlib
+open Parsetree
+open Ppx_deriving
+open VisitorsPlugin
+open VisitorsAnalysis
+open VisitorsGeneration
+
+(* -------------------------------------------------------------------------- *)
+
+(* We can generate classes that adhere to several distinct schemes, listed
+ below. These schemes differ only in the re-building code that is executed
+ after the recursive calls. In [iter], this code does nothing. In [map], it
+ reconstructs a data structure. In [endo], it also reconstructs a data
+ structure, but attempts to preserve sharing. In [reduce], it combines the
+ results of the recursive calls using a monoid operation. In [fold], this
+ code is missing; it is represented by a virtual method. *)
+
+type scheme =
+ | Iter
+ | Map
+ | Endo
+ | Reduce
+ | MapReduce
+ | Fold
+
+(* -------------------------------------------------------------------------- *)
+
+(* The parameters that can be set by the user. *)
+
+module type SETTINGS = sig
+
+ (* The type declarations that we are processing. *)
+ val decls: type_declaration list
+
+ (* The name of the generated class. *)
+ val name: classe
+
+ (* The arity of the generated code, e.g., 1 if one wishes to generate [iter]
+ and [map], 2 if one wishes to generate [iter2] and [map2], and so on. *)
+ val arity: int
+
+ (* The scheme of visitor that we wish to generate (see the definition of
+ the type [scheme] above). *)
+ val scheme: scheme
+
+ (* [variety] combines the information in [scheme] and [arity]. It is just
+ the string provided by the user. *)
+ val variety: string
+
+ (* [visit_prefix] is the common prefix used to name the descending visitor
+ methods. It must be nonempty and a valid identifier by itself. Its
+ default value is "visit_". *)
+ val visit_prefix: string
+
+ (* [build_prefix] is the common prefix used to name the ascending visitor
+ methods. It must be nonempty and a valid identifier by itself. Its
+ default value is "build_". *)
+ val build_prefix: string
+
+ (* [fail_prefix] is the common prefix used to name the failure methods. It
+ must be nonempty and a valid identifier by itself. Its default value is
+ "fail_". *)
+ val fail_prefix: string
+
+ (* The classes that the visitor should inherit. If [nude] is [false], the
+ class [VisitorsRuntime.<scheme>] is implicitly prepended to this list.
+ If [nude] is [true], it is not. *)
+ val ancestors: Longident.t list
+
+ (* [concrete] controls whether the generated class should be concrete or
+ virtual. By default, it is virtual. *)
+ val concrete: bool
+
+ (* If [irregular] is [true], the regularity check is suppressed; this allows
+ a local parameterized type to be instantiated. The definition of ['a t]
+ can then refer to [int t]. However, in most situations, this will lead to
+ ill-typed generated code. The generated code should be well-typed if [t]
+ is always instantiated in the same manner, e.g., if there are references
+ to [int t] but not to other instances of [t]. *)
+ val irregular: bool
+
+ (* If [public] is present, then every method is declared private, except
+ the methods whose name appears in the list [public]. *)
+ val public: string list option
+
+ (* If [polymorphic] is [true], then (possibly polymorphic) type annotations
+ for methods are generated. The function [poly], applied to the name of a
+ type variable (without its quote), tells whether this type variable
+ should receive monomorphic or polymorphic treatment. In the former case,
+ this type variable is dealt with via a visitor method; in the latter
+ case, it is dealt with via a visitor function. *)
+ val polymorphic: bool
+ val poly: tyvar -> bool
+
+ (* If [data] is [true], then descending visitor methods for data constructors
+ are generated. This allows the user to request per-data-constructor custom
+ behavior by overriding these methods. If [data] is [false], then these
+ methods are not generated. This yields simpler and faster code with
+ fewer customization opportunities. *)
+ val data: bool
+
+end
+
+(* -------------------------------------------------------------------------- *)
+
+(* The supported varieties. *)
+
+(* Note that [mapreduce] must appear in this list before [map], as shorter
+ prefixes must be tested last. *)
+
+let supported = [
+ "mapreduce", MapReduce;
+ "map", Map;
+ "iter", Iter;
+ "endo", Endo;
+ "reduce", Reduce;
+ "fold", Fold;
+ ]
+
+let valid_varieties =
+ "iter, map, endo, reduce, mapreduce, fold,\n\
+ iter2, map2, reduce2, mapreduce2, fold2"
+
+let invalid_variety loc =
+ raise_errorf ~loc
+ "%s: invalid variety. The valid varieties are\n\
+ %s."
+ plugin valid_varieties
+
+(* [parse_variety] takes a variety, which could be "iter", "map2", etc. and
+ returns a pair of a scheme and an arity. *)
+
+let parse_variety loc (s : string) : scheme * int =
+ (* A loop over [supported] tries each supported variety in turn. *)
+ let rec loop supported s =
+ match supported with
+ | (p, scheme) :: supported ->
+ if prefix p s then
+ let s = remainder p s in
+ let i = if s = "" then 1 else int_of_string s in
+ if i <= 0 then failwith "negative integer"
+ else scheme, i
+ else
+ loop supported s
+ | [] ->
+ failwith "unexpected prefix"
+ in
+ (* Start the loop and handle errors. *)
+ try
+ loop supported s
+ with Failure _ ->
+ invalid_variety loc
+
+(* -------------------------------------------------------------------------- *)
+
+let must_be_valid_method_name_prefix loc p =
+ if not (is_valid_method_name_prefix p) then
+ raise_errorf ~loc
+ "%s: %S is not a valid method name prefix." plugin p
+
+let must_be_valid_mod_longident loc m =
+ if not (is_valid_mod_longident m) then
+ raise_errorf ~loc
+ "%s: %S is not a valid module identifier." plugin m
+
+let must_be_valid_class_longident loc c =
+ if not (is_valid_class_longident c) then
+ raise_errorf ~loc
+ "%s: %S is not a valid class identifier." plugin c
+
+(* -------------------------------------------------------------------------- *)
+
+type bool_or_strings =
+ | Bool of bool
+ | Strings of string list
+
+let bool_or_strings : bool_or_strings Arg.conv =
+ fun e ->
+ match Arg.bool e, Arg.list Arg.string e with
+ | Ok b, Error _ ->
+ Ok (Bool b)
+ | Error _, Ok alphas ->
+ Ok (Strings alphas)
+ | Error _, Error _ ->
+ Error "Boolean or string list"
+ | Ok _, Ok _ ->
+ assert false
+
+(* -------------------------------------------------------------------------- *)
+
+(* The option processing code constructs a module of type [SETTINGS]. *)
+
+module Parse (O : sig
+ val loc: Location.t
+ val decls: type_declaration list
+ val options: (string * expression) list
+end)
+: SETTINGS
+= struct
+ open O
+
+ (* Set up a few parsers. *)
+
+ let bool = Arg.get_expr ~deriver:plugin Arg.bool
+ let string = Arg.get_expr ~deriver:plugin Arg.string
+ let strings = Arg.get_expr ~deriver:plugin (Arg.list Arg.string)
+ let bool_or_strings = Arg.get_expr ~deriver:plugin bool_or_strings
+
+ (* Default values. *)
+
+ let name = ref None
+ let arity = ref 1 (* dummy: [variety] is mandatory; see below *)
+ let scheme = ref Iter (* dummy: [variety] is mandatory; see below *)
+ let variety = ref None
+ let visit_prefix = ref "visit_"
+ let build_prefix = ref "build_"
+ let fail_prefix = ref "fail_"
+ let ancestors = ref []
+ let concrete = ref false
+ let data = ref true
+ let irregular = ref false
+ let nude = ref false
+ let polymorphic = ref false
+ let poly = ref (fun _ -> false)
+ let public = ref None
+
+ (* Parse every option. *)
+
+ let () =
+ iter (fun (o, e) ->
+ let loc = e.pexp_loc in
+ match o with
+ | "visit_prefix" ->
+ visit_prefix := string e;
+ must_be_valid_method_name_prefix loc !visit_prefix
+ | "build_prefix" ->
+ build_prefix := string e;
+ must_be_valid_method_name_prefix loc !build_prefix
+ | "fail_prefix" ->
+ fail_prefix := string e;
+ must_be_valid_method_name_prefix loc !fail_prefix
+ | "ancestors" ->
+ ancestors := strings e
+ | "concrete" ->
+ concrete := bool e
+ | "data" ->
+ data := bool e
+ | "irregular" ->
+ irregular := bool e
+ | "name" ->
+ name := Some (string e)
+ | "nude" ->
+ nude := bool e
+ | "polymorphic" ->
+ (* The [polymorphic] parameter can be a Boolean constant or a list
+ of type variable names. If [true], then all type variables are
+ considered polymorphic. If a list of type variables, then only
+ the variables in the list are considered polymorphic. *)
+ begin match bool_or_strings e with
+ | Bool b ->
+ polymorphic := b;
+ poly := (fun _ -> b)
+ | Strings alphas ->
+ let alphas = List.map unquote alphas in
+ polymorphic := true;
+ poly := (fun alpha -> List.mem alpha alphas)
+ end
+ | "monomorphic" ->
+ (* The [monomorphic] parameter is provided as a facility for the user.
+ It means the reverse of [polymorphic]. This is particularly useful
+ when the parameter is a list of type variables: then, only the
+ variables *not* in the list are considered polymorphic. *)
+ begin match bool_or_strings e with
+ | Bool b ->
+ polymorphic := not b;
+ poly := (fun _ -> not b)
+ | Strings alphas ->
+ let alphas = List.map unquote alphas in
+ polymorphic := true; (* yes, [true] *)
+ poly := (fun alpha -> not (List.mem alpha alphas))
+ end
+ | "public" ->
+ public := Some (strings e)
+ | "variety" ->
+ let v = string e in
+ variety := Some v;
+ let s, a = parse_variety loc v in
+ scheme := s;
+ arity := a;
+ (* [endo] is supported only at arity 1. *)
+ if s = Endo && a > 1 then
+ invalid_variety loc
+ | _ ->
+ (* We could emit a warning, instead of an error, if we find an
+ unsupported option. That might be preferable for forward
+ compatibility. That said, I am not sure that ignoring unknown
+ options is a good idea; it might cause us to generate code
+ that does not work as expected by the user. *)
+ raise_errorf ~loc "%s: option %s is not supported." plugin o
+ ) options
+
+ (* Export the results. *)
+
+ let decls = decls
+ let arity = !arity
+ let scheme = !scheme
+ let visit_prefix = !visit_prefix
+ let build_prefix = !build_prefix
+ let fail_prefix = !fail_prefix
+ let ancestors = !ancestors
+ let concrete = !concrete
+ let data = !data
+ let irregular = !irregular
+ let nude = !nude
+ let polymorphic = !polymorphic
+ let poly = !poly
+ let public = !public
+
+ (* Perform sanity checking. *)
+
+ (* The parameter [variety] is not optional. *)
+ let variety =
+ match !variety with
+ | None ->
+ raise_errorf ~loc
+ "%s: please specify the variety of the generated class.\n\
+ e.g. [@@deriving visitors { variety = \"iter\" }]" plugin
+ | Some variety ->
+ variety
+
+ (* The parameter [name] is optional. If it is absent, then [variety]
+ is used as its default value. *)
+ let name =
+ match !name with
+ | Some name ->
+ (* We expect [name] to be a valid class name. *)
+ if classify name <> LIDENT then
+ raise_errorf ~loc
+ "%s: %s is not a valid class name."
+ plugin name;
+ name
+ | None ->
+ variety
+
+ (* Every string in the list [ancestors] must be a valid (long) class
+ identifier. *)
+ let () =
+ iter (must_be_valid_class_longident loc) ancestors
+
+ (* When the variety is [iter], the class [VisitorsRuntime.iter] is an
+ implicit ancestor, and similarly for every variety. *)
+ let ancestors =
+ if nude then ancestors else ("VisitorsRuntime." ^ variety) :: ancestors
+ let ancestors =
+ map parse ancestors
+
+ (* If [scheme] is [Fold], then [polymorphic] must be [false]. Indeed,
+ we currently cannot generate polymorphic type annotations in that
+ case, as we cannot guess the return types of the visitor methods. *)
+ let () =
+ if scheme = Fold && polymorphic then
+ raise_errorf ~loc
+ "%s: cannot generate polymorphic\n\
+ type annotations for fold visitors."
+ plugin
+
+end
diff --git a/src/VisitorsString.ml b/src/VisitorsString.ml
new file mode 100644
index 0000000..bf0d4a1
--- /dev/null
+++ b/src/VisitorsString.ml
@@ -0,0 +1,70 @@
+open String
+
+(* [prefix s1 s2] tests whether [s1] is a prefix of [s2], i.e. whether
+ [s2] begins with [s1]. *)
+
+let prefix s1 s2 =
+ let n1 = length s1 in
+ n1 <= length s2 && s1 = sub s2 0 n1
+
+(* [remainder s1 s2] assumes that [s1] is a prefix of [s2], and chops
+ [s1] off [s2], returning the remainder. *)
+
+let remainder s1 s2 =
+ assert (prefix s1 s2);
+ let n1 = length s1 in
+ let n2 = length s2 in
+ sub s2 n1 (n2 - n1)
+
+(* [unquote alpha] removes a leading quote in the string [alpha], if
+ there is one. *)
+
+let unquote alpha =
+ let n = String.length alpha in
+ if n > 0 && alpha.[0] = '\'' then
+ String.sub alpha 1 (n-1)
+ else
+ alpha
+
+(* [print_longident] converts an OCaml long identifier to a string. *)
+
+let print_longident (x : Longident.t) : string =
+ String.concat "." (Longident.flatten x)
+
+(* Suppose the function [f] is a lossy (non-injective) mapping of ['a] to
+ [string]. Then, the function [protect f equal warn] is also a function of
+ ['a] to [string], which behaves like [f], except it warns if [f] is applied
+ to two values of type ['a] that have the same image of type [string]. *)
+
+(* [equal] must implement equality at type ['a]. *)
+
+(* [warn x1 x2 y] is invoked when [f] is applied at two distinct values [x1]
+ and [x2] that have the same image [y] through [f]. Precautions are taken
+ so that [f] is not invoked repeatedly if the same conflict is repeatedly
+ detected. *)
+
+module H = Hashtbl
+
+let protect
+ (f : 'a -> string)
+ (equal : 'a -> 'a -> bool)
+ (warn : 'a -> 'a -> string -> unit)
+: 'a -> string =
+ (* A hash table memoizes the inverse of [f]. *)
+ let table : (string, 'a list) H.t = H.create 127 in
+ fun (x : 'a) ->
+ let y = f x in
+ let xs = try H.find table y with Not_found -> [] in
+ H.add table y (x :: xs);
+ if List.exists (equal x) xs || xs = [] then
+ (* If the mapping of [x] to [y] is known already,
+ or if no pre-image of [y] was previously known,
+ then no warning is needed. *)
+ y
+ else
+ (* The list [xs] is nonempty and does not contain [x],
+ so its head [x'] is distinct from [x] and is also
+ a pre-image of [y]. Warn. *)
+ let x' = List.hd xs in
+ warn x' x y;
+ y
diff --git a/src/dune b/src/dune
new file mode 100644
index 0000000..89914ca
--- /dev/null
+++ b/src/dune
@@ -0,0 +1,22 @@
+(library
+ (name ppx_deriving_visitors)
+ (public_name visitors.ppx)
+ (synopsis "Compile-time support for generating visitors")
+ (kind ppx_deriver)
+ (libraries result compiler-libs.common ppxlib ppx_deriving.api)
+ (ppx_runtime_libraries visitors.runtime)
+)
+
+(env
+ (dev (flags
+ :standard
+ -safe-string
+ -g
+ -w @A-4-44
+ ))
+ (release (flags
+ :standard
+ -safe-string
+ -g
+ ))
+)
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 0000000..46c444f
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,3 @@
+.PHONY: test
+test:
+ @ make -C .. $@
diff --git a/test/OOinfer.ml b/test/OOinfer.ml
new file mode 100644
index 0000000..83d178c
--- /dev/null
+++ b/test/OOinfer.ml
@@ -0,0 +1,5 @@
+class int_cell = object
+ val mutable x = 0
+ method get = x
+ method incr y = x <- x + y
+end
diff --git a/test/OOinferfixed.ml b/test/OOinferfixed.ml
new file mode 100644
index 0000000..098dccf
--- /dev/null
+++ b/test/OOinferfixed.ml
@@ -0,0 +1,6 @@
+class virtual ['a] int_cell = object (self)
+ val mutable x = 0
+ method get = x
+ method set y = x <- self#check y
+ method virtual check: 'a -> _
+end
diff --git a/test/OOinferfixedagain.ml b/test/OOinferfixedagain.ml
new file mode 100644
index 0000000..cf78a1c
--- /dev/null
+++ b/test/OOinferfixedagain.ml
@@ -0,0 +1,6 @@
+class virtual ['a, 'b] cell (init) = object (self)
+ val mutable x = init
+ method get = x
+ method set y = x <- self#check y
+ method virtual check: 'a -> 'b
+end
diff --git a/test/OOinferfixedagaincheck.ml b/test/OOinferfixedagaincheck.ml
new file mode 100644
index 0000000..3c79f03
--- /dev/null
+++ b/test/OOinferfixedagaincheck.ml
@@ -0,0 +1,6 @@
+class virtual ['check] cell (init) = object (self)
+ val mutable x = init
+ method get = x
+ method set y = x <- self#check y
+ method virtual check: 'check
+end
diff --git a/test/OOinferself.ml b/test/OOinferself.ml
new file mode 100644
index 0000000..2564efd
--- /dev/null
+++ b/test/OOinferself.ml
@@ -0,0 +1,6 @@
+class virtual ['self] cell (init) = object (self : 'self)
+ val mutable x = init
+ method get = x
+ method set y = x <- self#check y
+ method virtual check: _
+end
diff --git a/test/OOinfervirtual.ml b/test/OOinfervirtual.ml
new file mode 100644
index 0000000..189d8d8
--- /dev/null
+++ b/test/OOinfervirtual.ml
@@ -0,0 +1,6 @@
+class virtual int_cell = object (self)
+ val mutable x = 0
+ method get = x
+ method incr y = x <- self#check (x + y)
+ method virtual check: _
+end
diff --git a/test/VisitorsRuntimeBootstrap.cppo.ml b/test/VisitorsRuntimeBootstrap.cppo.ml
new file mode 100644
index 0000000..81dc1f9
--- /dev/null
+++ b/test/VisitorsRuntimeBootstrap.cppo.ml
@@ -0,0 +1,30 @@
+type 'a option =
+ | None
+ | Some of 'a
+
+and 'a ref =
+ { mutable contents: 'a }
+
+#if OCAML_VERSION >= (4, 03, 0)
+
+and 'a list =
+ | Nil
+ | Cons of 'a * 'a list
+
+and ('a, 'b) result =
+ | Ok of 'a
+ | Error of 'b
+
+#endif
+
+[@@deriving
+visitors { variety = "iter"; public = []; polymorphic = true; data = false; nude = true },
+visitors { variety = "map"; public = []; polymorphic = true; data = false; nude = true },
+visitors { variety = "endo"; public = []; polymorphic = true; data = false; nude = true },
+visitors { variety = "reduce"; public = []; polymorphic = true; data = false; nude = true; ancestors = ["VisitorsRuntime.monoid"] },
+visitors { variety = "mapreduce"; public = []; polymorphic = true; data = false; nude = true; ancestors = ["VisitorsRuntime.monoid"] },
+visitors { variety = "iter2"; public = []; polymorphic = true; data = false; nude = true },
+visitors { variety = "map2"; public = []; polymorphic = true; data = false; nude = true },
+visitors { variety = "reduce2"; public = []; polymorphic = true; data = false; nude = true; ancestors = ["VisitorsRuntime.monoid"] },
+visitors { variety = "mapreduce2"; public = []; polymorphic = true; data = false; nude = true; ancestors = ["VisitorsRuntime.monoid"] }
+]
diff --git a/test/attic/expr07.ml b/test/attic/expr07.ml
new file mode 100644
index 0000000..e17c000
--- /dev/null
+++ b/test/attic/expr07.ml
@@ -0,0 +1,23 @@
+open Hashcons
+
+module Hash_consed = struct
+
+ let table =
+ create 128
+
+ let iter f env hcx =
+ f env hcx.node
+
+ let map f env hcx =
+ hashcons table (f env hcx.node)
+
+end
+
+type expr =
+ expr_node hash_consed
+
+and expr_node =
+ | EConst of int
+ | EAdd of expr * expr
+ [@@deriving visitors { name = "iter"; variety = "iter" },
+ visitors { name = "map" ; variety = "map" }]
diff --git a/test/bad/Makefile b/test/bad/Makefile
new file mode 100644
index 0000000..6c8b7d4
--- /dev/null
+++ b/test/bad/Makefile
@@ -0,0 +1,7 @@
+.PHONY: test clean
+
+test:
+ cram -iv visitors.t
+
+clean:
+ rm -f visitors.t.err
diff --git a/test/bad/conflict.ml b/test/bad/conflict.ml
new file mode 100644
index 0000000..86b0186
--- /dev/null
+++ b/test/bad/conflict.ml
@@ -0,0 +1,25 @@
+module Elt = struct
+ type t = int
+end
+
+type t =
+ | Leaf
+ | Node of { left: t; value: Elt.t; right: t }
+ [@@deriving visitors { variety = "iter" } ]
+
+(*
+
+Issue 3, reported by Gabriel Radanne.
+
+https://gitlab.inria.fr/fpottier/visitors/issues/3
+
+File "conflict.ml", line 5, characters 0-111:
+Error: This expression has type Elt.t = int
+ but an expression was expected of type t
+
+The naming convention for visitor methods causes a name clash:
+the types [Elt.t] and [t] have visitor methods by the same name.
+
+A warning should be issued.
+
+*)
diff --git a/test/bad/conflict_at_name.ml b/test/bad/conflict_at_name.ml
new file mode 100644
index 0000000..ab67704
--- /dev/null
+++ b/test/bad/conflict_at_name.ml
@@ -0,0 +1,17 @@
+module Elt = struct
+ type elt = int
+end
+
+type t =
+ | Leaf
+ | Node of { left: t; value: (Elt.elt[@name "t"]); right: t }
+ [@@deriving visitors { variety = "iter" } ]
+
+(*
+
+In this example, a stupid [@name] attribute causes a name clash:
+the types [elt] and [t] have visitor methods by the same name.
+
+A warning should be issued.
+
+*)
diff --git a/test/bad/conflict_atat_name.ml b/test/bad/conflict_atat_name.ml
new file mode 100644
index 0000000..7acce5e
--- /dev/null
+++ b/test/bad/conflict_atat_name.ml
@@ -0,0 +1,15 @@
+type t =
+ | Leaf
+ | Node of { left: t; value: elt; right: t }
+ [@@deriving visitors { variety = "iter" } ]
+
+and elt = int[@@name "t"]
+
+(*
+
+In this example, a stupid [@name] attribute causes a name clash:
+the types [elt] and [t] have visitor methods by the same name.
+
+A warning should be issued.
+
+*)
diff --git a/test/bad/datacon.ml b/test/bad/datacon.ml
new file mode 100644
index 0000000..86c7c7f
--- /dev/null
+++ b/test/bad/datacon.ml
@@ -0,0 +1,11 @@
+type t =
+ | A
+ | B of u
+
+and u =
+ | A of t
+ [@@deriving visitors { variety = "iter" }]
+
+(* Another example where two distinct types have a data constructor
+ named [A] (which OCaml warns about, but allows). This causes a
+ name clash on the methods [visit_A]. *)
diff --git a/test/bad/datacon_at_name.ml b/test/bad/datacon_at_name.ml
new file mode 100644
index 0000000..be3ce4a
--- /dev/null
+++ b/test/bad/datacon_at_name.ml
@@ -0,0 +1,10 @@
+type t =
+ | A
+ | B of u
+
+and u =
+ | C of t [@name "A"]
+ [@@deriving visitors { variety = "iter" }]
+
+(* Another example where two distinct types have a data constructor
+ renamed [A]. This causes a name clash on the methods [visit_A]. *)
diff --git a/test/bad/visitors.t b/test/bad/visitors.t
new file mode 100644
index 0000000..9ffdba9
--- /dev/null
+++ b/test/bad/visitors.t
@@ -0,0 +1,49 @@
+
+ $ compile="ocamlfind ocamlc -c -package visitors.ppx -package visitors.runtime"
+
+ $ $compile $TESTDIR/conflict.ml 2>&1 | sed -e "s|$TESTDIR/||"
+ File "conflict.ml", line 7, characters 30-35:
+ Warning 22: visitors: name clash: the types t and Elt.t
+ both have visitor methods named visit_t.
+ Please consider using [@@name] at type declaration sites
+ or [@name] at type reference sites.
+ File "conflict.ml", line 5, characters 0-111:
+ Error: This expression has type Elt.t = int
+ but an expression was expected of type t
+
+ $ $compile $TESTDIR/conflict_at_name.ml 2>&1 | sed -e "s|$TESTDIR/||"
+ File "conflict_at_name.ml", line 7, characters 31-38:
+ Warning 22: visitors: name clash: the types t and Elt.elt
+ both have visitor methods named visit_t.
+ Please consider using [@@name] at type declaration sites
+ or [@name] at type reference sites.
+ File "conflict_at_name.ml", line 5, characters 0-126:
+ Error: This expression has type Elt.elt = int
+ but an expression was expected of type t
+
+ $ $compile $TESTDIR/conflict_atat_name.ml 2>&1 | sed -e "s|$TESTDIR/||"
+ File "conflict_atat_name.ml", line 6, characters 0-25:
+ Warning 22: visitors: name clash: the types t and elt
+ both have visitor methods named visit_t.
+ Please consider using [@@name] at type declaration sites
+ or [@name] at type reference sites.
+ File "conflict_atat_name.ml", line 1, characters 0-136:
+ Error: The method `visit_t' has multiple definitions in this object
+
+ $ $compile $TESTDIR/datacon.ml 2>&1 | sed -e "s|$TESTDIR/||"
+ File "datacon.ml", line 6, characters 2-10:
+ Warning 22: visitors: name clash: the data constructors A and A
+ both have visitor methods named visit_A.
+ Please consider using [@name] at data constructor declaration sites.
+ File "datacon.ml", line 6, characters 2-10:
+ Warning 30: the constructor A is defined in both types t and u.
+ File "datacon.ml", line 1, characters 0-90:
+ Error: The method `visit_A' has multiple definitions in this object
+
+ $ $compile $TESTDIR/datacon_at_name.ml 2>&1 | sed -e "s|$TESTDIR/||"
+ File "datacon_at_name.ml", line 6, characters 2-22:
+ Warning 22: visitors: name clash: the data constructors A and C
+ both have visitor methods named visit_A.
+ Please consider using [@name] at data constructor declaration sites.
+ File "datacon_at_name.ml", line 1, characters 0-102:
+ Error: The method `visit_A' has multiple definitions in this object
diff --git a/test/bench.ml b/test/bench.ml
new file mode 100644
index 0000000..43cd6d1
--- /dev/null
+++ b/test/bench.ml
@@ -0,0 +1,136 @@
+module Bench = Core_bench.Bench
+module Command = Core.Command
+
+let run tests =
+ let tests =
+ List.map (fun (name, test) -> Bench.Test.create ~name test) tests
+ in
+ Command.run (Bench.make_command tests)
+
+type expr =
+ | EConst of (int[@opaque])
+ | EAdd of expr * expr
+ | EList of expr list
+ [@@deriving visitors { variety = "iter"; concrete = true },
+ visitors { variety = "map"; concrete = true },
+ visitors { variety = "reduce"; ancestors = ["VisitorsRuntime.addition_monoid"]; concrete = true }]
+
+let iter : expr -> unit =
+ new iter # visit_expr ()
+
+let rec native_iter env e =
+ match e with
+ | EConst _ ->
+ ()
+ | EAdd (e1, e2) ->
+ native_iter env e1;
+ native_iter env e2
+ | EList es ->
+ List.iter (native_iter env) es
+
+class size = object
+ inherit [_] reduce as super
+ method! visit_expr () e =
+ 1 + super # visit_expr () e
+end
+
+let size : expr -> int =
+ new size # visit_expr ()
+
+let rec native_size env e =
+ match e with
+ | EConst _ ->
+ 1
+ | EAdd (e1, e2) ->
+ native_size env e1 +
+ native_size env e2
+ | EList es ->
+ List.fold_left (fun accu e -> accu + native_size env e) 0 es
+
+let rec native_size_noenv e =
+ match e with
+ | EConst _ ->
+ 1
+ | EAdd (e1, e2) ->
+ native_size_noenv e1 +
+ native_size_noenv e2
+ | EList es ->
+ List.fold_left (fun accu e -> accu + native_size_noenv e) 0 es
+
+let rec native_size_noenv_accu accu e =
+ match e with
+ | EConst _ ->
+ accu + 1
+ | EAdd (e1, e2) ->
+ let accu = native_size_noenv_accu accu e1 in
+ native_size_noenv_accu accu e2
+ | EList es ->
+ List.fold_left native_size_noenv_accu accu es
+
+let split n =
+ assert (n >= 0);
+ let n1 = Random.int (n + 1) in
+ let n2 = n - n1 in
+ assert (0 <= n1 && n1 <= n);
+ assert (0 <= n2 && n2 <= n);
+ n1, n2
+
+let rec generate n =
+ assert (n >= 0);
+ if n = 0 then
+ EConst (Random.int 100)
+ else
+ match Random.int 2 with
+ | 0 ->
+ let n1, n2 = split (n - 1) in
+ EAdd (generate n1, generate n2)
+ | 1 ->
+ let n1, n2 = split (n - 1) in
+ EList [ generate n1; generate n2 ]
+ | _ ->
+ assert false
+
+let rec list_init i n f =
+ if i = n then
+ []
+ else
+ let x = f i in
+ x :: list_init (i + 1) n f
+
+let list_init n f =
+ list_init 0 n f
+
+let samples =
+ list_init 100 (fun _ -> generate 100)
+
+let test f () =
+ List.iter (fun e -> ignore (f e)) samples
+
+let () =
+ run [
+ "iter", test iter;
+ "native_iter", test (native_iter ());
+ ]
+
+let () =
+ run [
+ "size", test size;
+ "native_size", test (native_size ());
+(*
+ "native_size_noenv", test native_size_noenv;
+ "native_size_noenv_accu", test (native_size_noenv_accu 0);
+ *)
+ ]
+
+(* with hoisting, applied to self#visit_expr:
+ iter allocates no memory, and is 46% slower than native_iter (which allocates).
+ without hoisting:
+ iter allocates memory and is 65% slower than native_iter
+ So, in this case, hoisting helps a little.
+
+ with hoisting, applied to self#visit_expr:
+ size allocates no memory, and is 105% slower than native_size (which allocates).
+ without hoisting:
+ size allocates memory (same amount as native_size) and is 86% slower than native_size
+ So, in this case, hoisting seems counter-productive.
+ *)
diff --git a/test/build.ml b/test/build.ml
new file mode 100644
index 0000000..6c3c400
--- /dev/null
+++ b/test/build.ml
@@ -0,0 +1,10 @@
+(* Testing @build attributes. *)
+
+type foo =
+ | A
+ | B of int
+ | C of foo * foo [@build fun x y -> C (x, y)]
+
+and point = Point.point = private { x: int; y: int }
+ [@@build Point.make]
+ [@@deriving visitors { variety = "map" }]
diff --git a/test/cil_types.ml b/test/cil_types.ml
new file mode 100644
index 0000000..cdf228a
--- /dev/null
+++ b/test/cil_types.ml
@@ -0,0 +1,1811 @@
+module Integer = struct type t = int end (* fpottier/visitors *)
+(****************************************************************************)
+(* *)
+(* Copyright (C) 2001-2003 *)
+(* George C. Necula <necula@cs.berkeley.edu> *)
+(* Scott McPeak <smcpeak@cs.berkeley.edu> *)
+(* Wes Weimer <weimer@cs.berkeley.edu> *)
+(* Ben Liblit <liblit@cs.berkeley.edu> *)
+(* All rights reserved. *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in the *)
+(* documentation and/or other materials provided with the distribution. *)
+(* *)
+(* 3. The names of the contributors may not be used to endorse or *)
+(* promote products derived from this software without specific prior *)
+(* written permission. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *)
+(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *)
+(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *)
+(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *)
+(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *)
+(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *)
+(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *)
+(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *)
+(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *)
+(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *)
+(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *)
+(* POSSIBILITY OF SUCH DAMAGE. *)
+(* *)
+(* File modified by CEA (Commissariat à l'énergie atomique et aux *)
+(* énergies alternatives) *)
+(* and INRIA (Institut National de Recherche en Informatique *)
+(* et Automatique). *)
+(****************************************************************************)
+
+(** The Abstract Syntax of CIL.
+ @plugin development guide *)
+
+(**************************** WARNING ***************************************)
+(* Remember to reflect any change here into the visitor and pretty-printer *)
+(* in cil.ml. In particular, if a type becomes mutable, it is necessary to *)
+(* adapt the Cil.behavior type and the copy_behavior accordingly. *)
+(* A first test to see if something has been broken by a change is to launch*)
+(* ptests.byte -add-options '-files-debug "-check -copy"' *)
+(* In addition, it is a good idea to add some invariant checks in the *)
+(* check_file class in frama-c/src/file.ml (before lauching the tests) *)
+(****************************************************************************)
+
+(* ************************************************************************* *)
+(** {2 Root of the AST} *)
+(* ************************************************************************* *)
+
+(** In Frama-C, the whole AST is accessible through {!Ast.get}. *)
+
+(** The top-level representation of a CIL source file (and the result of the
+ parsing and elaboration). Its main contents is the list of global
+ declarations and definitions. You can iterate over the globals in a
+ {!Cil_types.file} using the following iterators: {!Cil.mapGlobals},
+ {!Cil.iterGlobals} and {!Cil.foldGlobals}. You can also use the
+ {!Cil.dummyFile} when you need a {!Cil_types.file} as a placeholder. For
+ each global item CIL stores the source location where it appears (using the
+ type {!Cil_types.location})
+ @plugin development guide *)
+type file = {
+ mutable fileName: string; (** The complete file name *)
+
+ mutable globals: global list;
+ (** List of globals as they will appear in the printed file *)
+
+ mutable globinit: fundec option;
+ (** An optional global initializer function. This is a function where you
+ can put stuff that must be executed before the program is
+ started. This function, is conceptually at the end of the file,
+ although it is not part of the globals list. Use {!Cil.getGlobInit} to
+ create/get one. *)
+
+ mutable globinitcalled: bool;
+(** Whether the global initialization function is called in main. This
+ should always be false if there is no global initializer. When you
+ create a global initialization CIL will try to insert code in main to
+ call it. *)
+}
+
+(** The main type for representing global declarations and definitions. A list
+ of these form a CIL file. The order of globals in the file is generally
+ important.
+ @plugin development guide *)
+and global =
+ | GType of typeinfo * location
+ (** A typedef. All uses of type names (through the [TNamed] constructor)
+ must be preceeded in the file by a definition of the name. The string
+ is the defined name and always not-empty. *)
+
+ | GCompTag of compinfo * location
+ (** Defines a struct/union tag with some fields. There must be one of
+ these for each struct/union tag that you use (through the [TComp]
+ constructor) since this is the only context in which the fields are
+ printed. Consequently nested structure tag definitions must be
+ broken into individual definitions with the innermost structure
+ defined first. *)
+
+ | GCompTagDecl of compinfo * location
+ (** Declares a struct/union tag. Use as a forward declaration. This is
+ printed without the fields. *)
+
+ | GEnumTag of enuminfo * location
+ (** Declares an enumeration tag with some fields. There must be one of
+ these for each enumeration tag that you use (through the [TEnum]
+ constructor) since this is the only context in which the items are
+ printed. *)
+
+ | GEnumTagDecl of enuminfo * location
+ (** Declares an enumeration tag. Use as a forward declaration. This is
+ printed without the items. *)
+
+ | GVarDecl of varinfo * location
+ (** A variable declaration (not a definition) for a variable with object
+ type. There can be several declarations and at most one definition for
+ a given variable. If both forms appear then they must share the same
+ varinfo structure. Either has storage Extern or there must be a
+ definition in this file *)
+
+ | GFunDecl of funspec * varinfo * location
+ (** A variable declaration (not a definition) for a function, i.e. a
+ prototype. There can be several declarations and at most one definition
+ for a given function. If both forms appear then they must share the same
+ varinfo structure. A prototype shares the varinfo with the fundec of the
+ definition. Either has storage Extern or there must be a definition in
+ this file. *)
+
+ | GVar of varinfo * initinfo * location
+ (** A variable definition. Can have an initializer. The initializer is
+ updateable so that you can change it without requiring to recreate the
+ list of globals. There can be at most one definition for a variable in an
+ entire program. Cannot have storage Extern or function type. *)
+
+ | GFun of fundec * location
+ (** A function definition. *)
+
+ | GAsm of string * location
+ (** Global asm statement. These ones can contain only a template *)
+
+ | GPragma of attribute * location
+ (** Pragmas at top level. Use the same syntax as attributes *)
+
+ | GText of string
+ (** Some text (printed verbatim) at top level. E.g., this way you can put
+ comments in the output. *)
+
+ | GAnnot of global_annotation * location
+(** a global annotation. Can be
+ - an axiom or a lemma
+ - a predicate declaration or definition
+ - a global type invariant
+ - a global invariant
+ - a logic function declaration or definition. *)
+
+(* ************************************************************************* *)
+(** {2 Types} *)
+(* ************************************************************************* *)
+
+(** A C type is represented in CIL using the type {!Cil_types.typ}. Among types
+ we differentiate the integral types (with different kinds denoting the sign
+ and precision), floating point types, enumeration types, array and pointer
+ types, and function types. Every type is associated with a list of
+ attributes, which are always kept in sorted order. Use {!Cil.addAttribute}
+ and {!Cil.addAttributes} to construct list of attributes. If you want to
+ inspect a type, you should use {!Cil.unrollType} or {!Cil.unrollTypeDeep} to
+ see through the uses of named types.
+
+ CIL is configured at build-time with the sizes and alignments of the
+ underlying compiler (GCC or MSVC). CIL contains functions that can compute
+ the size of a type (in bits) {!Cil.bitsSizeOf}, the alignment of a type (in
+ bytes) {!Cil.alignOf_int}, and can convert an offset into a start and width
+ (both in bits) using the function {!Cil.bitsOffset}. At the moment these
+ functions do not take into account the [packed] attributes and pragmas. *)
+
+and typ =
+ | TVoid of attributes (** Void type. Also predefined as {!Cil.voidType} *)
+
+ | TInt of ikind * attributes
+ (** An integer type. The kind specifies the sign and width. Several useful
+ variants are predefined as {!Cil.intType}, {!Cil.uintType},
+ {!Cil.longType}, {!Cil.charType}. *)
+
+ | TFloat of fkind * attributes
+ (** A floating-point type. The kind specifies the precision. You can also use
+ the predefined constant {!Cil.doubleType}. *)
+
+ | TPtr of typ * attributes
+ (** Pointer type. Several useful variants are predefined as
+ {!Cil.charPtrType}, {!Cil.charConstPtrType} (pointer to a constant
+ character), {!Cil.voidPtrType}, {!Cil.intPtrType} *)
+
+ | TArray of typ * exp option * bitsSizeofTypCache * attributes
+ (** Array type. It indicates the base type and the array length. *)
+
+ | TFun of typ * (string * typ * attributes) list option * bool * attributes
+ (** Function type. Indicates the type of the result, the name, type
+ and name attributes of the formal arguments ([None] if no arguments
+ were specified, as in a function whose definition or prototype we
+ have not seen; [Some \[\]] means void). Use {!Cil.argsToList} to
+ obtain a list of arguments. The boolean indicates if it is a
+ variable-argument function. If this is the type of a varinfo for
+ which we have a function declaration then the information for the
+ formals must match that in the function's sformals. Use
+ {!Cil.setFormals}, or {!Cil.setFunctionType}, or
+ {!Cil.makeFormalVar} for this purpose. *)
+
+ | TNamed of typeinfo * attributes
+ (** The use of a named type. All uses of the same type name must share the
+ typeinfo. Each such type name must be preceeded in the file by a [GType]
+ global. This is printed as just the type name. The actual referred type
+ is not printed here and is carried only to simplify processing. To see
+ through a sequence of named type references, use {!Cil.unrollType}. The
+ attributes are in addition to those given when the type name was
+ defined. *)
+
+ | TComp of compinfo * bitsSizeofTypCache * attributes
+ (** A reference to a struct or a union type. All references to the
+ same struct or union must share the same compinfo among them and
+ with a [GCompTag] global that preceeds all uses (except maybe
+ those that are pointers to the composite type). The attributes
+ given are those pertaining to this use of the type and are in
+ addition to the attributes that were given at the definition of
+ the type and which are stored in the compinfo. *)
+
+ | TEnum of enuminfo * attributes
+ (** A reference to an enumeration type. All such references must
+ share the enuminfo among them and with a [GEnumTag] global that
+ preceeds all uses. The attributes refer to this use of the
+ enumeration and are in addition to the attributes of the
+ enumeration itself, which are stored inside the enuminfo *)
+
+ | TBuiltin_va_list of attributes
+(** This is the same as the gcc's type with the same name *)
+
+(** Various kinds of integers *)
+and ikind =
+ IBool (** [_Bool] *)
+ | IChar (** [char] *)
+ | ISChar (** [signed char] *)
+ | IUChar (** [unsigned char] *)
+ | IInt (** [int] *)
+ | IUInt (** [unsigned int] *)
+ | IShort (** [short] *)
+ | IUShort (** [unsigned short] *)
+ | ILong (** [long] *)
+ | IULong (** [unsigned long] *)
+ | ILongLong (** [long long] (or [_int64] on Microsoft Visual C) *)
+ | IULongLong (** [unsigned long long] (or [unsigned _int64] on Microsoft
+ Visual C) *)
+
+(** Various kinds of floating-point numbers*)
+and fkind =
+ FFloat (** [float] *)
+ | FDouble (** [double] *)
+ | FLongDouble (** [long double] *)
+
+(** This is used to cache the computation of the size of types in bits. *)
+and bitsSizeofTyp =
+ | Not_Computed
+ | Computed of int
+ | Not_Computable of (string * typ) (** Explanation of the error *)
+
+and bitsSizeofTypCache = { mutable scache : bitsSizeofTyp}
+
+(* ************************************************************************* *)
+(** {2 Attributes} *)
+(* ************************************************************************* *)
+
+and attribute =
+ | Attr of string * attrparam list
+ (** An attribute has a name and some optional parameters. The name should not
+ start or end with underscore. When CIL parses attribute names it will
+ strip leading and ending underscores (to ensure that the multitude of GCC
+ attributes such as const, __const and __const__ all mean the same
+ thing.) *)
+
+ | AttrAnnot of string
+
+(** Attributes are lists sorted by the attribute name. Use the functions
+ {!Cil.addAttribute} and {!Cil.addAttributes} to insert attributes in an
+ attribute list and maintain the sortedness. *)
+and attributes = attribute list
+
+(** The type of parameters of attributes *)
+and attrparam =
+ | AInt of (Integer.t[@opaque]) (** An integer constant *)
+ | AStr of string (** A string constant *)
+ | ACons of string * attrparam list
+ (** Constructed attributes. These are printed [foo(a1,a2,...,an)]. The list
+ of parameters can be empty and in that case the parentheses are not
+ printed. *)
+ | ASizeOf of typ (** A way to talk about types *)
+ | ASizeOfE of attrparam
+ | AAlignOf of typ
+ | AAlignOfE of attrparam
+ | AUnOp of unop * attrparam
+ | ABinOp of binop * attrparam * attrparam
+ | ADot of attrparam * string (** a.foo **)
+ | AStar of attrparam (** * a *)
+ | AAddrOf of attrparam (** & a **)
+ | AIndex of attrparam * attrparam (** a1[a2] *)
+ | AQuestion of attrparam * attrparam * attrparam (** a1 ? a2 : a3 **)
+
+(* ************************************************************************* *)
+(** {2 Structures} *)
+(* ************************************************************************* *)
+
+(** The {!Cil_types.compinfo} describes the definition of a structure or union
+ type. Each such {!Cil_types.compinfo} must be defined at the top-level using
+ the [GCompTag] constructor and must be shared by all references to this type
+ (using either the [TComp] type constructor or from the definition of the
+ fields.
+
+ If all you need is to scan the definition of each composite type once, you
+ can do that by scanning all top-level [GCompTag].
+
+ Constructing a {!Cil_types.compinfo} can be tricky since it must contain
+ fields that might refer to the host {!Cil_types.compinfo} and furthermore
+ the type of the field might need to refer to the {!Cil_types.compinfo} for
+ recursive types. Use the {!Cil.mkCompInfo} function to create a
+ {!Cil_types.compinfo}. You can easily fetch the {!Cil_types.fieldinfo} for a
+ given field in a structure with {!Cil.getCompField}. *)
+
+(** The definition of a structure or union type. Use {!Cil.mkCompInfo} to make
+ one and use {!Cil.copyCompInfo} to copy one (this ensures that a new key is
+ assigned and that the fields have the right pointers to parents.).
+ @plugin development guide *)
+and compinfo = {
+ mutable cstruct: bool;
+ (** [true] if struct, [false] if union *)
+
+ corig_name: string;
+ (** Original name as found in C file. Will never be changed *)
+
+ mutable cname: string;
+ (** The name. Always non-empty. Use {!Cil.compFullName} to get the full name
+ of a comp (along with the struct or union) *)
+
+ mutable ckey: int;
+ (** A unique integer. This is assigned by {!Cil.mkCompInfo} using a global
+ variable in the Cil module. Thus two identical structs in two different
+ files might have different keys. Use {!Cil.copyCompInfo} to copy
+ structures so that a new key is assigned. *)
+
+ mutable cfields: fieldinfo list;
+ (** Information about the fields. Notice that each fieldinfo has a pointer
+ back to the host compinfo. This means that you should not share
+ fieldinfo's between two compinfo's *)
+
+ mutable cattr: attributes;
+ (** The attributes that are defined at the same time as the composite
+ type. These attributes can be supplemented individually at each
+ reference to this [compinfo] using the [TComp] type constructor. *)
+
+ mutable cdefined: bool;
+ (** This boolean flag can be used to distinguish between structures
+ that have not been defined and those that have been defined but have
+ no fields (such things are allowed in gcc). *)
+
+ mutable creferenced: bool;
+(** [true] if used. Initially set to [false]. *)
+}
+
+(* ************************************************************************* *)
+(** {2 Structure fields} *)
+(* ************************************************************************* *)
+
+(** The {!Cil_types.fieldinfo} structure is used to describe a structure or
+ union field. Fields, just like variables, can have attributes associated
+ with the field itself or associated with the type of the field (stored along
+ with the type of the field). *)
+
+(** Information about a struct/union field.
+ @plugin development guide *)
+and fieldinfo = {
+ mutable fcomp: compinfo;
+ (** The host structure that contains this field. There can be only one
+ [compinfo] that contains the field. *)
+
+ forig_name: string;
+ (** original name as found in C file. *)
+
+ mutable fname: string;
+ (** The name of the field. Might be the value of {!Cil.missingFieldName} in
+ which case it must be a bitfield and is not printed and it does not
+ participate in initialization *)
+
+ mutable ftype: typ;
+ (** The type. If the field is a bitfield, a special attribute
+ [FRAMA_C_BITFIELD_SIZE] indicating the width of the bitfield is added. *)
+
+ mutable fbitfield: int option;
+ (** If a bitfield then ftype should be an integer type and the width of the
+ bitfield must be 0 or a positive integer smaller or equal to the width of
+ the integer type. A field of width 0 is used in C to control the alignment
+ of fields. *)
+
+ mutable fattr: attributes;
+ (** The attributes for this field (not for its type) *)
+
+ mutable floc: location;
+ (** The location where this field is defined *)
+
+ mutable faddrof: bool;
+ (** Adapted from CIL [vaddrof] field for variables. Only set for non-array
+ fields. Variable whose field address is taken is not marked anymore as
+ having its own address taken. True if the address of this field is
+ taken. CIL will set these flags when it parses C, but you should make
+ sure to set the flag whenever your transformation create [AddrOf]
+ expression. *)
+
+ mutable fsize_in_bits: int option;
+ (** (Deprecated. Use {!Cil.bitsOffset} instead.) Similar to [fbitfield] for
+ all types of fields.
+ @deprecated only Jessie uses this *)
+
+ mutable foffset_in_bits: int option;
+ (** Offset at which the field starts in the structure. Do not read directly,
+ but use {!Cil.bitsOffset} instead. *)
+
+ mutable fpadding_in_bits: int option;
+(** (Deprecated.) Store the size of the padding that follows the field, if any.
+ @deprecated only Jessie uses this *)
+}
+
+(* ************************************************************************* *)
+(** {2 Enumerations} *)
+(* ************************************************************************* *)
+
+(** Information about an enumeration. This is shared by all references to an
+ enumeration. Make sure you have a [GEnumTag] for each of these. *)
+
+(** Information about an enumeration.
+ @plugin development guide *)
+and enuminfo = {
+ eorig_name: string; (** original name as found in C file. *)
+
+ mutable ename: string; (** The name. Always non-empty. *)
+
+ mutable eitems: enumitem list; (** Items. The list must be non-empty *)
+
+ mutable eattr: attributes;
+ (** The attributes that are defined at the same time as the enumeration
+ type. These attributes can be supplemented individually at each
+ reference to this [enuminfo] using the [TEnum] type constructor. *)
+
+ mutable ereferenced: bool; (** [true] if used. Initially set to [false]. *)
+ mutable ekind: ikind (** The integer kind used to represent this enum. MSVC
+ always assumes IInt but this is not the case
+ for gcc. See ISO C 6.7.2.2 *)
+}
+
+and enumitem = {
+ eiorig_name: string; (** original name as found in C file. *)
+ mutable einame: string; (** the name, always non-empty. *)
+ mutable eival: exp; (** value of the item. Must be a compile-time constant *)
+ mutable eihost: enuminfo; (** the host enumeration in which the item is
+ declared. *)
+ eiloc: location;
+}
+
+(** Information about a defined type.
+ @plugin development guide *)
+and typeinfo = {
+ torig_name: string; (** original name as found in C file. *)
+
+ mutable tname: string;
+ (** The name. Can be empty only in a [GType] when introducing a composite or
+ enumeration tag. If empty cannot be refered to from the file *)
+
+ mutable ttype: typ;
+ (** The actual type. This includes the attributes that were present in the
+ typedef *)
+
+ mutable treferenced: bool; (** [true] if used. Initially set to [false]. *)
+}
+
+(* ************************************************************************* *)
+(** {2 Variables} *)
+(* ************************************************************************* *)
+
+(** Each local or global variable is represented by a unique
+ {!Cil_types.varinfo} structure. A global {!Cil_types.varinfo} can be
+ introduced with the [GVarDecl] or [GVar], [GFunDecl] or [GFun] globals.
+ A local varinfo can be introduced as part of a function definition
+ {!Cil_types.fundec}.
+
+ All references to a given global or local variable must refer to the same
+ copy of the [varinfo]. Each [varinfo] has a globally unique identifier that
+ can be used to index maps and hashtables (the name can also be used for this
+ purpose, except for locals from different functions). This identifier is
+ constructor using a global counter.
+
+ It is very important that you construct [varinfo] structures using only one
+ of the following functions:
+ - {!Cil.makeGlobalVar} : to make a global variable
+ - {!Cil.makeTempVar} : to make a temporary local variable whose name
+ will be generated so that to avoid conflict with other locals.
+ - {!Cil.makeLocalVar} : like {!Cil.makeTempVar} but you can specify the
+ exact name to be used.
+ - {!Cil.copyVarinfo}: make a shallow copy of a varinfo assigning a new name
+ and a new unique identifier
+
+ A [varinfo] is also used in a function type to denote the list of
+ formals. *)
+
+(** Information about a variable.
+ @plugin development guide *)
+and varinfo = {
+ mutable vname: string;
+ (** The name of the variable. Cannot be empty. It is primarily your
+ responsibility to ensure the uniqueness of a variable name. For local
+ variables {!Cil.makeTempVar} helps you ensure that the name is
+ unique. *)
+
+ vorig_name: string;
+ (** the original name of the variable. Need not be unique. *)
+
+ mutable vtype: typ;
+ (** The declared type of the variable. *)
+
+ mutable vattr: attributes;
+ (** A list of attributes associated with the variable.*)
+
+ mutable vstorage: storage;
+ (** The storage-class *)
+
+ mutable vglob: bool;
+ (** True if this is a global variable*)
+
+ mutable vdefined: bool;
+ (** True if the variable or function is defined in the file. Only relevant
+ for functions and global variables. Not used in particular for local
+ variables and logic variables. *)
+
+ mutable vformal: bool;
+ (** True if the variable is a formal parameter of a function. *)
+
+ mutable vinline: bool;
+ (** Whether this varinfo is for an inline function. *)
+
+ mutable vdecl: location;
+ (** Location of variable declaration. *)
+
+ mutable vid: int;
+ (** A unique integer identifier. This field will be set for you if you use
+ one of the {!Cil.makeFormalVar}, {!Cil.makeLocalVar},
+ {!Cil.makeTempVar}, {!Cil.makeGlobalVar}, or {!Cil.copyVarinfo}. *)
+
+ mutable vaddrof: bool;
+ (** [true] if the address of this variable is taken. CIL will set these
+ flags when it parses C, but you should make sure to set the flag
+ whenever your transformation create [AddrOf] expression. *)
+
+ mutable vreferenced: bool;
+ (** [true] if this variable is ever referenced. This is computed by
+ [removeUnusedVars]. It is safe to just initialize this to [false]. *)
+
+ vtemp: bool;
+ (** [true] for temporary variables generated by CIL normalization. [false]
+ for all the other variables. *)
+
+ mutable vdescr: string option;
+ (** For most temporary variables, a description of what the var holds.
+ (e.g. for temporaries used for function call results, this string is a
+ representation of the function call.) *)
+
+ mutable vdescrpure: bool;
+ (** Indicates whether the vdescr above is a pure expression or call. True
+ for all CIL expressions and Lvals, but false for e.g. function calls.
+ Printing a non-pure vdescr more than once may yield incorrect
+ results. *)
+
+ mutable vghost: bool;
+ (** Indicates if the variable is declared in ghost code *)
+
+ vsource: bool;
+ (** [true] iff this variable appears in the source of the program, which is
+ the case of all the variables in the initial AST. Plugins may create
+ variables with [vsource=false], for example to handle dynamic allocation.
+ Those variables do *not* have an associated {!GVar} or {!GVarDecl}. *)
+
+ mutable vlogic_var_assoc: logic_var option
+ (** Logic variable representing this variable in the logic world. Do not
+ access this field directly. Instead, call {!Cil.cvar_to_lvar}. *)
+}
+
+(** Storage-class information *)
+and storage =
+ NoStorage (** The default storage. Nothing is printed *)
+ | Static
+ | Register
+ | Extern
+
+(* ************************************************************************* *)
+(** {2 Expressions} *)
+(* ************************************************************************* *)
+
+(** The CIL expression language contains only the side-effect free expressions
+ of C. They are represented as the type {!Cil_types.exp}. There are several
+ interesting aspects of CIL expressions:
+
+ Integer and floating point constants can carry their textual representation.
+ This way the integer 15 can be printed as 0xF if that is how it occurred in
+ the source.
+
+ CIL uses arbitrary precision integers
+ to represent the integer constants and also stores the
+ width of the integer type. Care must be taken to ensure that the constant is
+ representable with the given width. Use the functions {!Cil.kinteger},
+ {!Cil.kinteger64} and {!Cil.integer} to construct constant expressions. CIL
+ predefines the constants {!Cil.zero}, {!Cil.one} and {!Cil.mone} (for -1).
+
+ Use the functions {!Cil.isConstant} and {!Cil.isInteger} to test if an
+ expression is a constant and a constant integer respectively.
+
+ CIL keeps the type of all unary and binary expressions. You can think of
+ that type qualifying the operator. Furthermore there are different operators
+ for arithmetic and comparisons on arithmetic types and on pointers.
+
+ Another unusual aspect of CIL is that the implicit conversion between an
+ expression of array type and one of pointer type is made explicit, using the
+ [StartOf] expression constructor (which is not printed). If you apply the
+ [AddrOf]constructor to an lvalue of type [T] then you will be getting an
+ expression of type [TPtr(T)].
+
+ You can find the type of an expression with {!Cil.typeOf}.
+
+ You can perform constant folding on expressions using the function
+ {!Cil.constFold}. *)
+
+(** Expressions (Side-effect free)*)
+and exp = {
+ eid: int; (** unique identifier *)
+ enode: exp_node; (** the expression itself *)
+ eloc: location; (** location of the expression. *)
+}
+
+and exp_node =
+ | Const of constant (** Constant *)
+ | Lval of lval (** Lvalue *)
+ | SizeOf of typ
+ (** sizeof(<type>). Has [unsigned int] type (ISO 6.5.3.4). This is not
+ turned into a constant because some transformations might want to change
+ types *)
+
+ | SizeOfE of exp (** sizeof(<expression>) *)
+
+ | SizeOfStr of string
+ (** sizeof(string_literal). We separate this case out because this is the
+ only instance in which a string literal should not be treated as having
+ type pointer to character. *)
+
+ | AlignOf of typ
+ (** This corresponds to the GCC __alignof_. Has [unsigned int] type *)
+
+ | AlignOfE of exp
+
+ | UnOp of unop * exp * typ
+ (** Unary operation. Includes the type of the result. *)
+
+ | BinOp of binop * exp * exp * typ
+ (** Binary operation. Includes the type of the result. The arithmetic
+ conversions are made explicit for the arguments.
+ @plugin development guide *)
+
+ | CastE of typ * exp
+ (** Use {!Cil.mkCast} to make casts. *)
+
+ | AddrOf of lval
+ (** Always use {!Cil.mkAddrOf} to construct one of these. Apply to an lvalue
+ of type [T] yields an expression of type [TPtr(T)] *)
+
+ | StartOf of lval
+ (** Conversion from an array to a pointer to the beginning of the array.
+ Given an lval of type [TArray(T)] produces an expression of type
+ [TPtr(T)]. In C this operation is implicit, the [StartOf] operator is not
+ printed. We have it in CIL because it makes the typing rules simpler. *)
+
+ | Info of exp * exp_info
+(** Additional information on the underlying expression *)
+
+(** Additional information on an expression *)
+and exp_info = {
+ exp_type : logic_type; (** when used as placeholder for a term *)
+ exp_name: string list;
+}
+
+(* ************************************************************************* *)
+(** {2 Constants} *)
+(* ************************************************************************* *)
+
+(** Literal constants *)
+and constant =
+ | CInt64 of (Integer.t[@opaque]) * ikind * string option
+ (** Integer constant. Give the ikind (see ISO9899 6.1.3.2) and the
+ textual representation. Textual representation is always set to Some s
+ when it comes from user code. This allows us to print a
+ constant as it was represented in the code, for example,
+ 0xF instead of 15. It is usually None for constant generated by Cil
+ itself. Use {!Cil.integer} or {!Cil.kinteger} to create these. *)
+
+ | CStr of string
+ (** String constant. The escape characters inside the string have been already
+ interpreted. This constant has pointer to character type! The only case
+ when you would like a string literal to have an array type is when it is
+ an argument to sizeof. In that case you should use SizeOfStr. *)
+
+ | CWStr of int64 list
+ (** Wide character string constant. Note that the local interpretation of such
+ a literal depends on {!Cil.theMachine.wcharType} and
+ {!Cil.theMachine.wcharKind}. Such a constant has type pointer to
+ {!Cil.theMachine.wcharType}. The escape characters in the string have not
+ been "interpreted" in the sense that L"A\xabcd" remains "A\xabcd" rather
+ than being represented as the wide character list with two elements: 65
+ and 43981. That "interpretation" depends on the underlying wide character
+ type. *)
+
+ | CChr of char
+ (** Character constant. This has type int, so use charConstToInt to read the
+ value in case sign-extension is needed. *)
+
+ | CReal of float * fkind * string option
+ (** Floating point constant. Give the fkind (see ISO 6.4.4.2) and also the
+ textual representation, if available. *)
+
+ | CEnum of enumitem
+(** An enumeration constant. Use [Cillower.lowerEnumVisitor] to replace these
+ with integer constants. *)
+
+(** Unary operators *)
+and unop =
+ Neg (** Unary minus *)
+ | BNot (** Bitwise complement (~) *)
+ | LNot (** Logical Not (!) *)
+
+(** Binary operations *)
+and binop =
+ PlusA (** arithmetic + *)
+ | PlusPI (** pointer + integer *)
+ | IndexPI (** pointer + integer but only when it arises from an expression
+ [e\[i\]] when [e] is a pointer and
+ not an array. This is semantically
+ the same as PlusPI but CCured uses
+ this as a hint that the integer is
+ probably positive. *)
+ | MinusA (** arithmetic - *)
+ | MinusPI (** pointer - integer *)
+ | MinusPP (** pointer - pointer *)
+ | Mult (** * *)
+ | Div (** /
+ @plugin development guide *)
+ | Mod (** %
+ @plugin development guide *)
+ | Shiftlt (** shift left *)
+ | Shiftrt (** shift right *)
+
+ | Lt (** < (arithmetic comparison) *)
+ | Gt (** > (arithmetic comparison) *)
+ | Le (** <= (arithmetic comparison) *)
+ | Ge (** >= (arithmetic comparison) *)
+ | Eq (** == (arithmetic comparison) *)
+ | Ne (** != (arithmetic comparison) *)
+ | BAnd (** bitwise and *)
+ | BXor (** exclusive-or *)
+ | BOr (** inclusive-or *)
+
+ | LAnd (** logical and. Unlike other expressions this one does not always
+ evaluate both operands. If you want
+ to use these, you must set
+ {!Cil.useLogicalOperators}. *)
+ | LOr (** logical or. Unlike other expressions this one does not always
+ evaluate both operands. If you
+ want to use these, you must set
+ {!Cil.useLogicalOperators}. *)
+
+(* ************************************************************************* *)
+(** {2 Left values} *)
+(* ************************************************************************* *)
+
+(** Left values (aka Lvalues) are the sublanguage of expressions that can appear
+ at the left of an assignment or as operand to the address-of operator. In C
+ the syntax for lvalues is not always a good indication of the meaning of the
+ lvalue. For example the C value {v a[0][1][2] v} might involve 1, 2 or 3
+ memory reads when used in an expression context, depending on the declared
+ type of the variable [a]. If [a] has type [int \[4\]\[4\]\[4\]] then we have
+ one memory read from somewhere inside the area that stores the array [a]. On
+ the other hand if [a] has type [int ***] then the expression really means [*
+ ( * ( * (a + 0) + 1) + 2)], in which case it is clear that it involves three
+ separate memory operations.
+
+ An lvalue denotes the contents of a range of memory addresses. This range is
+ denoted as a host object along with an offset within the object. The host
+ object can be of two kinds: a local or global variable, or an object whose
+ address is in a pointer expression. We distinguish the two cases so that we
+ can tell quickly whether we are accessing some component of a variable
+ directly or we are accessing a memory location through a pointer. To make
+ it easy to tell what an lvalue means CIL represents lvalues as a host object
+ and an offset (see {!Cil_types.lval}). The host object (represented as
+ {!Cil_types.lhost}) can be a local or global variable or can be the object
+ pointed-to by a pointer expression. The offset (represented as
+ {!Cil_types.offset}) is a sequence of field or array index designators.
+
+ Both the typing rules and the meaning of an lvalue is very precisely
+ specified in CIL.
+
+ The following are a few useful function for operating on lvalues:
+ - {!Cil.mkMem} - makes an lvalue of [Mem] kind. Use this to ensure
+ that certain equivalent forms of lvalues are canonized.
+ For example, [*&x = x].
+ - {!Cil.typeOfLval} - the type of an lvalue
+ - {!Cil.typeOffset} - the type of an offset, given the type of the
+ host.
+ - {!Cil.addOffset} and {!Cil.addOffsetLval} - extend sequences
+ of offsets.
+ - {!Cil.removeOffset} and {!Cil.removeOffsetLval} - shrink sequences
+ of offsets.
+
+ The following equivalences hold {v
+ Mem(AddrOf(Mem a, aoff)), off = Mem a, aoff + off
+ Mem(AddrOf(Var v, aoff)), off = Var v, aoff + off
+ AddrOf (Mem a, NoOffset) = a
+ v} *)
+
+and lval = lhost * offset
+
+(** The host part of an {!Cil_types.lval}. *)
+and lhost =
+ | Var of varinfo
+ (** The host is a variable. *)
+
+ | Mem of exp
+(** The host is an object of type [T] when the expression has pointer
+ [TPtr(T)]. *)
+
+
+(** The offset part of an {!Cil_types.lval}. Each offset can be applied to
+ certain kinds of lvalues and its effect is that it advances the starting
+ address of the lvalue and changes the denoted type, essentially focussing
+ to some smaller lvalue that is contained in the original one.
+ @plugin development guide *)
+and offset =
+ | NoOffset
+ (** No offset. Can be applied to any lvalue and does not change either the
+ starting address or the type. This is used when the lval consists of just
+ a host or as a terminator in a list of other kinds of offsets. *)
+
+ | Field of fieldinfo * offset
+ (** A field offset. Can be applied only to an lvalue that denotes a structure
+ or a union that contains the mentioned field. This advances the offset to
+ the beginning of the mentioned field and changes the type to the type of
+ the mentioned field. *)
+
+ | Index of exp * offset
+(** An array index offset. Can be applied only to an lvalue that denotes an
+ array. This advances the starting address of the lval to the beginning of
+ the mentioned array element and changes the denoted type to be the type of
+ the array element *)
+
+(* ************************************************************************* *)
+(** {2 Initializers} *)
+(* ************************************************************************* *)
+
+(** A special kind of expressions are those that can appear as initializers for
+ global variables (initialization of local variables is turned into
+ assignments). The initializers are represented as type
+ {!Cil_types.init}. You can create initializers with {!Cil.makeZeroInit} and
+ you can conveniently scan compound initializers them with
+ {!Cil.foldLeftCompound}. *)
+
+(** Initializers for global variables. *)
+and init =
+ | SingleInit of exp (** A single initializer *)
+ | CompoundInit of typ * (offset * init) list
+(** Used only for initializers of structures, unions and arrays. The offsets
+ are all of the form [Field(f, NoOffset)] or [Index(i, NoOffset)] and
+ specify the field or the index being initialized. For structures all fields
+ must have an initializer (except the unnamed bitfields), in the proper
+ order. This is necessary since the offsets are not printed. For arrays the
+ list must contain a prefix of the initializers; the rest are 0-initialized.
+ For unions there must be exactly one initializer. If the initializer is not
+ for the first field then a field designator is printed, so you better be on
+ GCC since MSVC does not understand this. You can scan an initializer list
+ with {!Cil.foldLeftCompound}. *)
+
+(** We want to be able to update an initializer in a global variable, so we
+ define it as a mutable field *)
+and initinfo = { mutable init : init option }
+
+(* ************************************************************************* *)
+(** {2 Function definitions} *)
+(* ************************************************************************* *)
+
+(** A function definition is always introduced with a [GFun] constructor at the
+ top level. All the information about the function is stored into a
+ {!Cil_types.fundec}. Some of the information (e.g. its name, type, storage,
+ attributes) is stored as a {!Cil_types.varinfo} that is a field of the
+ [fundec]. To refer to the function from the expression language you must use
+ the [varinfo].
+
+ The function definition contains, in addition to the body, a list of all the
+ local variables and separately a list of the formals. Both kind of variables
+ can be referred to in the body of the function. The formals must also be
+ shared with the formals that appear in the function type. For that reason,
+ to manipulate formals you should use the provided functions
+ {!Cil.makeFormalVar} and {!Cil.setFormals}. *)
+
+(** Function definitions.
+ @plugin development guide *)
+and fundec = {
+ mutable svar: varinfo;
+ (** Holds the name and type as a variable, so we can refer to it easily
+ from the program. All references to this function either in a function
+ call or in a prototype must point to the same [varinfo]. *)
+
+ mutable sformals: varinfo list;
+ (** Formals. These must be in the same order and with the same information
+ as the formal information in the type of the function. Use
+ {!Cil.setFormals} or {!Cil.setFunctionType} to set these formals and
+ ensure that they are reflected in the function type. Do not make
+ copies of these because the body refers to them. *)
+
+ mutable slocals: varinfo list;
+ (** Locals. Does NOT include the sformals. Do not make copies of these
+ because the body refers to them. *)
+
+ mutable smaxid: int;
+ (** Max local id. Starts at 0. Used for creating the names of new
+ temporary variables. Updated by {!Cil.makeLocalVar} and
+ {!Cil.makeTempVar}. You can also use {!Cil.setMaxId} to set it after
+ you have added the formals and locals. *)
+
+ mutable sbody: block; (** The function body. *)
+
+ mutable smaxstmtid: int option;
+ (** max id of a (reachable) statement in this function, if we have
+ computed it. range = 0 ... (smaxstmtid-1). This is computed by
+ {!Cfg.computeCFGInfo}. *)
+
+ mutable sallstmts: stmt list;
+ (** After you call {!Cfg.computeCFGInfo} this field is set to contain all
+ statements in the function. *)
+
+ mutable sspec: funspec;
+}
+
+(** A block is a sequence of statements with the control falling through from
+ one element to the next *)
+and block = {
+ mutable battrs: attributes; (** Attributes for the block *)
+
+ mutable blocals: varinfo list;
+ (** variables that are local to the block. It is a subset of the slocals of
+ the enclosing function. *)
+
+ mutable bstmts: stmt list; (** The statements comprising the block. *)
+}
+
+(* ************************************************************************* *)
+(** {2 Statements} *)
+(* ************************************************************************* *)
+
+(** CIL statements are the structural elements that make the CFG. They are
+ represented using the type {!Cil_types.stmt}. Every statement has a
+ (possibly empty) list of labels. The {!Cil_types.stmtkind} field of a
+ statement indicates what kind of statement it is.
+
+ Use {!Cil.mkStmt} to make a statement and the fill-in the fields.
+
+ CIL also comes with support for control-flow graphs. The [sid] field in
+ [stmt] can be used to give unique numbers to statements, and the [succs] and
+ [preds] fields can be used to maintain a list of successors and predecessors
+ for every statement. The CFG information is not computed by default. Instead
+ you must explicitly use the functions {!Cfg.prepareCFG} and
+ {!Cfg.computeCFGInfo} to do it. *)
+
+(** Statements.
+ @plugin development guide *)
+and stmt = {
+ mutable labels: label list;
+ (** Whether the statement starts with some labels, case statements or
+ default statements. *)
+
+ mutable skind: stmtkind;
+ (** The kind of statement *)
+
+ mutable sid: int;
+ (** A number (>= 0) that is unique in a function. Filled in only after the
+ CFG is computed. *)
+
+ mutable succs: stmt list;
+ (** The successor statements. They can always be computed from the skind and
+ the context in which this statement appears. Filled in only after the CFG
+ is computed. *)
+
+ mutable preds: stmt list;
+ (** The inverse of the succs function. *)
+
+ mutable ghost : bool
+}
+
+(** Labels *)
+and label =
+ | Label of string * location * bool
+ (** A real label. If the bool is "true", the label is from the input source
+ program. If the bool is "false", the label was created by CIL or some
+ other transformation *)
+
+ | Case of exp * location
+ (** A case statement. This expression is lowered into a constant if
+ {!Cil.lowerConstants} is set to [true]. *)
+
+ | Default of location (** A default statement *)
+
+(* The various kinds of statements *)
+and stmtkind =
+ | Instr of instr
+ (** An instruction that does not contain control flow. Control implicitly
+ falls through.
+ @plugin development guide *)
+
+ | Return of exp option * location
+ (** The return statement. This is a leaf in the CFG.
+ @plugin development guide *)
+
+ | Goto of stmt ref * location
+ (** A goto statement. Appears from actual goto's in the code or from goto's
+ that have been inserted during elaboration. The reference points to the
+ statement that is the target of the Goto. This means that you have to
+ update the reference whenever you replace the target statement. The
+ target statement MUST have at least a label.
+ @plugin development guide *)
+
+ | Break of location
+ (** A break to the end of the nearest enclosing Loop or Switch.
+ @plugin development guide *)
+
+ | Continue of location
+ (** A continue to the start of the nearest enclosing [Loop].
+ @plugin development guide *)
+
+ | If of exp * block * block * location
+ (** A conditional. Two successors, the "then" and the "else" branches (in
+ this order).
+ Both branches fall-through to the successor of the If statement.
+ @plugin development guide *)
+
+ | Switch of exp * block * (stmt list) * location
+ (** A switch statement. [exp] is the index of the switch. [block] is
+ the body of the switch. [stmt list] contains the set of
+ statements whose [labels] are cases of the switch (i.e. for each
+ case, the corresponding statement is in [stmt list], a statement
+ cannot appear more than once in the list, and statements in
+ [stmt list] can have several labels corresponding to several
+ cases.
+ @plugin development guide *)
+
+ | Loop of
+ code_annotation list * block * location * (stmt option) * (stmt option)
+ (** A [while(1)] loop. The termination test is implemented in the body of a
+ loop using a [Break] statement. If {!Cfg.prepareCFG} has been called, the
+ first stmt option will point to the stmt containing the continue label
+ for this loop and the second will point to the stmt containing the break
+ label for this loop.
+ @plugin development guide *)
+
+ | Block of block
+ (** Just a block of statements. Use it as a way to keep some block attributes
+ local.
+ @plugin development guide *)
+
+ | UnspecifiedSequence of (stmt * lval list
+ * lval list * lval list * stmt ref list) list
+ (** statements whose order of execution is not specified by
+ ISO/C. This is important for the order of side effects
+ during evaluation of expressions. Each statement comes
+ together with three list of lval, in this order.
+ - lvals that are written during the sequence and whose future
+ value depends upon the statement (it is legal to read from them, but
+ not to write to them)
+ - lvals that are written during the evaluation of the statement itself
+ - lval that are read.
+ - Function calls in the corresponding statement
+ Note that this include only a subset of the affectations
+ of the statement. Namely, the
+ temporary variables generated by cil are excluded (i.e. it
+ is assumed that the "compilation" is correct). In addition,
+ side effects caused by function applications are not taken
+ into account in the list. For a single statement, the written lvals
+ are supposed to be ordered (or their order of evaluation doesn't
+ matter), so that an alarm should be emitted only if the lvals read by
+ a statement overlap with the lvals written (or read) by another
+ statement of the sequence.
+
+ At this time this feature is
+ experimental and may miss some unspecified sequences.
+
+ In case you do not care about this feature just handle it
+ like a block (see {!Cil.block_from_unspecified_sequence}).
+ @plugin development guide *)
+
+ | Throw of (exp * typ) option * location
+ (** Throws an exception, C++ style.
+ We keep the type of the expression, to match
+ it against the appropriate catch clause. A Throw node has
+ no successor, even if it is in try-catch block that will catch
+ the exception: we keep normal and exceptional control-flow
+ completely separate, as in Jo and Chang, ICSSA 2004.
+ *)
+
+ | TryCatch of block * (catch_binder * block) list * location
+
+ | TryFinally of block * block * location
+ (** On MSVC we support structured exception handling. This is what you might
+ expect. Control can get into the finally block either from the end of the
+ body block, or if an exception is thrown.
+ @plugin development guide *)
+
+ | TryExcept of block * (instr list * exp) * block * location
+(** On MSVC we support structured exception handling. The try/except
+ statement is a bit tricky:
+ {v __try \{ blk \}
+ __except (e) \{
+ handler
+ \}
+ v}
+
+ The argument to __except must be an expression. However, we keep a
+ list of instructions AND an expression in case you need to make
+ function calls. We'll print those as a comma expression. The control
+ can get to the __except expression only if an exception is thrown.
+ After that, depending on the value of the expression the control
+ goes to the handler, propagates the exception, or retries the
+ exception. The location corresponds to the try keyword.
+ @plugin development guide *)
+
+(** Kind of exceptions that are caught by a given clause. *)
+and catch_binder =
+ | Catch_exn of varinfo * (varinfo * block) list
+ (** catch exception of given type(s).
+ If the list is empty, only exceptions with the same type as the
+ varinfo can be caught. If the list is non-empty, only exceptions
+ matching one of the type of a varinfo in the list are caught.
+ The associated block contains the operations necessary to transform
+ the matched varinfo into the principal one.
+ Semantics is by value (i.e. the varinfo is bound to a copy of the
+ caught object).
+
+ This clause is a declaration point for the varinfo(s)
+ mentioned in it. More precisely, for
+ [Catch_exn(v_0,[(v_1, b_1),..., (v_n, b_n)])],
+ the [v_i] must be referenced in the [slocals] of the
+ enclosing [fundec], and _must not_ appear in any [blocals]
+ of some block. The scope of v_0 is all the [b_i] and
+ the corresponding block in the [catch_binder * block list] of the
+ [TryCatch] node the binder belongs to. The scope of the other [v_i]
+ is the corresponding [b_i].
+ *)
+ | Catch_all (** default catch clause: all exceptions are caught. *)
+
+(** Instructions. They may cause effects directly but may not have control
+ flow.*)
+and instr =
+ | Set of lval * exp * location
+ (** An assignment. A cast is present if the exp has different type from
+ lval *)
+
+ | Call of lval option * exp * exp list * location
+ (** optional: result is an lval. A cast might be necessary if the declared
+ result type of the function is not the same as that of the destination.
+ Actual arguments must have a type equivalent (i.e. {!Cil.need_cast} must
+ return [false]) to the one of the formals of the function.
+ If the type of the result variable is not the same as the declared type of
+ the function result then an implicit cast exists.
+ *)
+
+ (* See the GCC specification for the meaning of ASM.
+ If the source is MS VC then only the templates
+ are used.
+
+ [sm] I've added a notes.txt file which contains more
+ information on interpreting Asm instructions *)
+ | Asm of
+ attributes (* Really only const and volatile can appear here *)
+ * string list (* templates (CR-separated) *)
+ * extended_asm option
+ * location
+ (** An inline assembly instruction. The arguments are
+ (1) a list of attributes (only const and volatile can appear here and only
+ for GCC)
+ (2) templates (CR-separated)
+ (3) GCC extended asm information if any
+ (4) location information *)
+
+ | Skip of location
+
+ | Code_annot of code_annotation * location
+
+
+(** GNU extended-asm information:
+ - a list of outputs, each of which is an lvalue with optional names and
+ constraints.
+ - a list of input expressions along with constraints
+ - clobbered registers
+ - Possible destinations statements *)
+and extended_asm =
+ {
+ asm_outputs: (string option * string * lval) list
+ (** outputs must be lvals with optional names and constraints. I would
+ like these to be actually variables, but I run into some trouble with
+ ASMs in the Linux sources *);
+ asm_inputs: (string option * string * exp) list
+ (** inputs with optional names and constraints *);
+ asm_clobbers: string list (** register clobbers *);
+ asm_gotos: (stmt ref) list
+ (** list of statements this asm section may jump to. Destination
+ must have a label. *);
+ }
+
+(** Describes a location in a source file *)
+and location = Lexing.position * Lexing.position [@opaque]
+
+(** {1 Abstract syntax trees for annotations} *)
+
+and logic_constant =
+ | Integer of (Integer.t[@opaque]) * string option
+ (** Integer constant with a textual representation. *)
+ | LStr of string (** String constant. *)
+ | LWStr of int64 list (** Wide character string constant. *)
+ | LChr of char (** Character constant. *)
+ | LReal of logic_real
+ | LEnum of enumitem (** An enumeration constant.*)
+
+(** Real constants. *)
+and logic_real = {
+ r_literal : string ; (** Initial string representation [s]. *)
+ r_nearest : float ; (** Nearest approximation of [s] in double precision. *)
+ r_upper : float ; (** Smallest double [u] such that [s <= u]. *)
+ r_lower : float ; (** Greatest double [l] such that [l <= s]. *)
+}
+
+(** Types of logic terms. *)
+and logic_type =
+ | Ctype of typ (** a C type *)
+ | Ltype of logic_type_info * logic_type list
+ (** an user-defined logic type with its parameters *)
+ | Lvar of string (** a type variable. *)
+ | Linteger (** mathematical integers, {i i.e.} Z *)
+ | Lreal (** mathematical reals, {i i.e.} R *)
+ | Larrow of logic_type list * logic_type (** (n-ary) function type *)
+
+(** tsets with an unique identifier.
+ Use [Logic_const.new_location] to generate a new id. *)
+and identified_term = {
+ it_id: int; (** the identifier. *)
+ it_content: term (** the term *)
+}
+
+(** logic label referring to a particular program point. *)
+and logic_label =
+ | StmtLabel of stmt ref (** label of a C statement. *)
+ | LogicLabel of (stmt option * string) (* [JS 2011/05/13] why a tuple here? *)
+(** builtin logic label ({t Here, Pre}, ...) *)
+
+(* ************************************************************************* *)
+(** {2 Terms} *)
+(* ************************************************************************* *)
+
+(** C Expressions as logic terms follow C constructs (with prefix T) *)
+
+(** Logic terms. *)
+and term = {
+ term_node : term_node; (** kind of term. *)
+ term_loc : Lexing.position * Lexing.position [@opaque];
+ (** position in the source file. *)
+ term_type : logic_type; (** type of the term. *)
+ term_name: string list;
+ (** names of the term if any. A name can be an arbitrary string, where
+ '"' and '\'' are escaped by a \, and which does not end with a \.
+ Hence, "name" and 'name' should be recognized as a unique label by most
+ tools. *)
+}
+
+(** the various kind of terms. *)
+and term_node =
+ (* same constructs as exp *)
+ | TConst of logic_constant (** a constant. *)
+ | TLval of term_lval (** an L-value *)
+ | TSizeOf of typ (** size of a given C type. *)
+ | TSizeOfE of term (** size of the type of an expression. *)
+ | TSizeOfStr of string (** size of a string constant. *)
+ | TAlignOf of typ (** alignment of a type. *)
+ | TAlignOfE of term (** alignment of the type of an expression. *)
+ | TUnOp of unop * term (** unary operator. *)
+ | TBinOp of binop * term * term (** binary operators. *)
+ | TCastE of typ * term (** cast to a C type. *)
+ | TAddrOf of term_lval (** address of a term. *)
+ | TStartOf of term_lval (** beginning of an array. *)
+
+ (* additional constructs *)
+ | Tapp of logic_info * (logic_label * logic_label) list * term list
+ (** application of a logic function. *)
+ | Tlambda of quantifiers * term (** lambda abstraction. *)
+ | TDataCons of logic_ctor_info * term list
+ (** constructor of logic sum-type. *)
+ | Tif of term * term * term
+ (** conditional operator*)
+ | Tat of term * logic_label
+ (** term refers to a particular program point. *)
+ | Tbase_addr of logic_label * term (** base address of a pointer. *)
+ | Toffset of logic_label * term (** offset from the base address of a pointer. *)
+ | Tblock_length of logic_label * term (** length of the block pointed to by the term. *)
+ | Tnull (** the null pointer. *)
+ | TLogic_coerce of logic_type * term
+ (** implicit conversion from a C type to a logic type.
+ The logic type must not be a Ctype. In particular, used to denote
+ lifting to Linteger and Lreal.
+ *)
+ | TCoerce of term * typ (** coercion to a given C type. *)
+ | TCoerceE of term * term (** coercion to the type of a given term. *)
+ | TUpdate of term * term_offset * term
+ (** functional update of a field. *)
+ | Ttypeof of term (** type tag for a term. *)
+ | Ttype of typ (** type tag for a C type. *)
+ | Tempty_set (** the empty set. *)
+ | Tunion of term list (** union of terms. *)
+ | Tinter of term list (** intersection of terms. *)
+ | Tcomprehension of
+ term * quantifiers * predicate option
+ (** set defined in comprehension ({t \{ t[i] | integer i; 0 <= i < 5\}}) *)
+ | Trange of term option * term option (** range of integers. *)
+ | Tlet of logic_info * term (** local binding *)
+
+(** lvalue: base address and offset. *)
+and term_lval =
+ term_lhost * term_offset
+
+(** base address of an lvalue. *)
+and term_lhost =
+ | TVar of logic_var (** a variable. *)
+ | TResult of typ (** value returned by a C function.
+ Only used in post-conditions or assigns
+ *)
+ | TMem of term (** memory access. *)
+
+(** model field. *)
+and model_info = {
+ mi_name: string; (** name *)
+ mi_field_type: logic_type; (** type of the field *)
+ mi_base_type: typ; (** type to which the field is associated. *)
+ mi_decl: location; (** where the field has been declared. *)
+}
+
+(** offset of an lvalue. *)
+and term_offset =
+ | TNoOffset (** no further offset. *)
+ | TField of fieldinfo * term_offset
+ (** access to the field of a compound type. *)
+ | TModel of model_info * term_offset (** access to a model field. *)
+ | TIndex of term * term_offset
+ (** index. Note that a range is denoted by [TIndex(Trange(i1,i2),ofs)] *)
+
+(** description of a logic function or predicate.
+@plugin development guide *)
+and logic_info = {
+(*
+ mutable l_name : string; (** name of the function. *)
+*)
+ mutable l_var_info : logic_var;
+ (** we use only fields lv_name and lv_id of l_var_info
+ we should factorize lv_type and l_type+l_profile below *)
+ mutable l_labels : logic_label list; (** label arguments of the function. *)
+ mutable l_tparams : string list; (** type parameters *)
+ mutable l_type : logic_type option; (** return type. None for predicates *)
+ mutable l_profile : logic_var list; (** type of the arguments. *)
+ mutable l_body : logic_body; (** body of the function. *)
+}
+
+and builtin_logic_info = {
+ mutable bl_name: string;
+ mutable bl_labels: logic_label list;
+ mutable bl_params: string list;
+ mutable bl_type: logic_type option;
+ mutable bl_profile: (string * logic_type) list;
+}
+
+and logic_body =
+ | LBnone (** no definition and no reads clause *)
+ | LBreads of identified_term list
+ (** read accesses performed by a function. *)
+ | LBterm of term (** direct definition of a function. *)
+ | LBpred of predicate (** direct definition of a predicate. *)
+ | LBinductive of
+ (string * logic_label list * string list * predicate) list
+ (** inductive definition *)
+
+(** Description of a logic type.
+ @plugin development guide *)
+and logic_type_info = {
+ lt_name: string;
+ lt_params : string list; (** type parameters*)
+ mutable lt_def: logic_type_def option
+ (** definition of the type. None for abstract types. *)
+}
+(* will be expanded when dealing with concrete types *)
+
+and logic_type_def =
+ | LTsum of logic_ctor_info list (** sum type with its constructors. *)
+ | LTsyn of logic_type (** Synonym of another type. *)
+
+(** origin of a logic variable. *)
+and logic_var_kind =
+ | LVGlobal (** global logic function or predicate. *)
+ | LVC (** Logic counterpart of a C variable. *)
+ | LVFormal (** formal parameter of a logic function / predicate
+ or \lambda abstraction *)
+ | LVQuant (** Bound by a quantifier (\exists or \forall) *)
+ | LVLocal (** local \let *)
+
+(** description of a logic variable
+@plugin development guide *)
+and logic_var = {
+ mutable lv_name : string; (** name of the variable. *)
+ mutable lv_id : int; (** unique identifier *)
+ mutable lv_type : logic_type; (** type of the variable. *)
+ mutable lv_kind: logic_var_kind; (** kind of the variable *)
+ mutable lv_origin : varinfo option
+(** when the logic variable stems from a C variable, set to the original C
+ variable. *)
+}
+
+(** Description of a constructor of a logic sum-type.
+ @plugin development guide *)
+and logic_ctor_info =
+ { ctor_name: string; (** name of the constructor. *)
+ ctor_type: logic_type_info; (** type to which the constructor belongs. *)
+ ctor_params: logic_type list
+ (** types of the parameters of the constructor. *)
+ }
+
+(* ************************************************************************* *)
+(** {2 Predicates} *)
+(* ************************************************************************* *)
+
+(** variables bound by a quantifier. *)
+and quantifiers = logic_var list
+
+(** comparison relations*)
+and relation =
+ | Rlt
+ | Rgt
+ | Rle
+ | Rge
+ | Req
+ | Rneq (** @plugin development guide *)
+
+
+(** predicates *)
+and predicate_node =
+ | Pfalse (** always-false predicate. *)
+ | Ptrue (** always-true predicate. *)
+ | Papp of logic_info * (logic_label * logic_label) list * term list
+ (** application of a predicate. *)
+ | Pseparated of term list
+ | Prel of relation * term * term (** comparison of two terms. *)
+ | Pand of predicate * predicate (** conjunction *)
+ | Por of predicate * predicate (** disjunction. *)
+ | Pxor of predicate * predicate (** logical xor. *)
+ | Pimplies of predicate * predicate (** implication. *)
+ | Piff of predicate * predicate (** equivalence. *)
+ | Pnot of predicate (** negation. *)
+ | Pif of term * predicate * predicate (** conditional *)
+ | Plet of logic_info * predicate (** definition of a local variable *)
+ | Pforall of quantifiers * predicate (** universal quantification. *)
+ | Pexists of quantifiers * predicate (** existential quantification. *)
+ | Pat of predicate * logic_label
+ (** predicate refers to a particular program point. *)
+ | Pvalid_read of logic_label * term (** the given locations are valid for reading. *)
+ | Pvalid of logic_label * term (** the given locations are valid. *)
+ | Pvalid_function of term
+ (** the pointed function has a type compatible with the one of pointer. *)
+ | Pinitialized of logic_label * term (** the given locations are initialized. *)
+ | Pdangling of logic_label * term (** the given locations contain dangling
+ adresses. *)
+ | Pallocable of logic_label * term (** the given locations can be allocated. *)
+ | Pfreeable of logic_label * term (** the given locations can be free. *)
+ | Pfresh of logic_label * logic_label * term * term
+ (** \fresh(pointer, n)
+ A memory block of n bytes is newly allocated to the pointer.*)
+ | Psubtype of term * term
+ (** First term is a type tag that is a subtype of the second. *)
+
+(** predicate with an unique identifier. Use [Logic_const.new_predicate] to
+ create fresh predicates *)
+and identified_predicate = {
+ ip_id: int; (** identifier *)
+ ip_content: predicate; (** the predicate itself*)
+}
+
+(** predicates with a location and an optional list of names *)
+and predicate = {
+ pred_name : string list; (** list of given names *)
+ pred_loc : location; (** position in the source code. *)
+ pred_content : predicate_node;(** content *)
+}
+
+(* Polymorphic types shared with parsed trees (Logic_ptree) *)
+(** variant of a loop or a recursive function. Type shared with Logic_ptree. *)
+and 'term variant = 'term * string option
+
+(** allocates and frees.
+ @since Oxygen-20120901 *)
+and 'locs allocation =
+ | FreeAlloc of 'locs list * 'locs list (** tsets. Empty list means \nothing. *)
+ | FreeAllocAny (** Nothing specified. Semantics depends on where it
+ is written. *)
+
+(** dependencies of an assigned location. Shared with Logic_ptree. *)
+and 'locs deps =
+ | From of 'locs list (** tsets. Empty list means \nothing. *)
+ | FromAny (** Nothing specified. Any location can be involved. *)
+
+and 'locs from = ('locs * 'locs deps)
+
+(** zone assigned with its dependencies. Type shared with Logic_ptree. *)
+and 'locs assigns =
+ | WritesAny (** Nothing specified. Anything can be written. *)
+ | Writes of 'locs from list
+ (** list of locations that can be written. Empty list means \nothing. *)
+
+(** Function or statement contract. This type shares the name of its
+ constructors with {!Logic_ptree.spec}. *)
+and spec = {
+ mutable spec_behavior : behavior list;
+ (** behaviors *)
+
+ mutable spec_variant : term variant option;
+ (** variant for recursive functions. *)
+
+ mutable spec_terminates: identified_predicate option;
+ (** termination condition. *)
+
+ mutable spec_complete_behaviors: string list list;
+ (** list of complete behaviors.
+ It is possible to have more than one set of complete behaviors *)
+
+ mutable spec_disjoint_behaviors: string list list;
+ (** list of disjoint behaviors.
+ It is possible to have more than one set of disjoint behaviors *)
+}
+
+
+(** extension to standard ACSL clause.
+ Each extension is associated to a keyword. An extension
+ can be registered through the following functions:
+ - {!Logic_typing.register_behavior_extension} for parsing and type-checking
+ - {!Cil_printer.register_behavior_extension} for pretty-printing an
+ extended clause
+ - {!Cil.register_behavior_extension} for visiting an extended clause
+
+ @plugin development guide *)
+and acsl_extension = string * acsl_extension_kind
+
+and acsl_extension_kind =
+ | Ext_id of int (** id used internally by the extension itself. *)
+ | Ext_terms of term list
+ | Ext_preds of predicate list
+ (** a list of predicates, the most common case of for extensions *)
+
+(** Behavior of a function or statement. This type shares the name of its
+ constructors with {!Logic_ptree.behavior}.
+ @since Oxygen-20120901 [b_allocation] has been added.
+ @since Carbon-20101201 [b_requires] has been added.
+ @modify Boron-20100401 [b_ensures] is replaced by [b_post_cond].
+ Old [b_ensures] represent the [Normal] case of [b_post_cond]. *)
+and behavior = {
+ mutable b_name : string; (** name of the behavior. *)
+ mutable b_requires : identified_predicate list; (** require clauses. *)
+ mutable b_assumes : identified_predicate list; (** assume clauses. *)
+ mutable b_post_cond : (termination_kind * identified_predicate) list
+ (** post-condition. *);
+ mutable b_assigns : identified_term assigns; (** assignments. *)
+ mutable b_allocation : identified_term allocation; (** frees, allocates. *)
+ mutable b_extended : acsl_extension list (** extensions *)
+}
+
+(** kind of termination a post-condition applies to. See ACSL manual. *)
+and termination_kind = Normal | Exits | Breaks | Continues | Returns
+
+(** Pragmas for the value analysis plugin of Frama-C.
+ Type shared with Logic_ptree.*)
+and 'term loop_pragma =
+ | Unroll_specs of 'term list
+ | Widen_hints of 'term list
+ | Widen_variables of 'term list
+
+(** Pragmas for the slicing plugin of Frama-C. Type shared with Logic_ptree.*)
+and 'term slice_pragma =
+ | SPexpr of 'term
+ | SPctrl
+ | SPstmt
+
+(** Pragmas for the impact plugin of Frama-C. Type shared with Logic_ptree.*)
+and 'term impact_pragma =
+ | IPexpr of 'term
+ | IPstmt
+
+(** The various kinds of pragmas. Type shared with Logic_ptree. *)
+and 'term pragma =
+ | Loop_pragma of 'term loop_pragma
+ | Slice_pragma of 'term slice_pragma
+ | Impact_pragma of 'term impact_pragma
+
+(** all annotations that can be found in the code.
+ This type shares the name of its constructors with
+ {!Logic_ptree.code_annot}. *)
+and code_annotation_node =
+ | AAssert of string list * predicate
+ (** assertion to be checked. The list of strings is the list of
+ behaviors to which this assertion applies. *)
+
+ | AStmtSpec of string list * spec
+ (** statement contract
+ (potentially restricted to some enclosing behaviors). *)
+
+ | AInvariant of string list * bool * predicate
+ (** loop/code invariant. The list of strings is the list of behaviors to which
+ this invariant applies. The boolean flag is true for normal loop
+ invariants and false for invariant-as-assertions. *)
+
+ | AVariant of term variant
+ (** loop variant. Note that there can be at most one variant associated to a
+ given statement *)
+
+ | AAssigns of string list * identified_term assigns
+ (** loop assigns. (see [b_assigns] in the behaviors for other assigns). At
+ most one clause associated to a given (statement, behavior) couple. *)
+
+ | AAllocation of string list * identified_term allocation
+ (** loop allocation clause. (see [b_allocation] in the behaviors for other
+ allocation clauses).
+ At most one clause associated to a given (statement, behavior) couple.
+ @since Oxygen-20120901 when [b_allocation] has been added. *)
+
+ | APragma of term pragma (** pragma. *)
+ | AExtended of string list * acsl_extension
+ (** extension in a loop annotation.
+ @since Silicon-20161101 *)
+
+(** function contract. *)
+
+and funspec = spec
+
+(** code annotation with an unique identifier.
+ Use [Logic_const.new_code_annotation] to create new code annotations with
+ a fresh id. *)
+and code_annotation = {
+ annot_id: int; (** identifier. *)
+ annot_content : code_annotation_node; (** content of the annotation. *)
+}
+
+(** behavior of a function. *)
+and funbehavior = behavior
+
+(** global annotations, not attached to a statement or a function. *)
+and global_annotation =
+ | Dfun_or_pred of logic_info * location
+ | Dvolatile of
+ identified_term list * varinfo option * varinfo option * location
+ (** associated terms, reading function, writing function *)
+ | Daxiomatic of string * global_annotation list * location
+ | Dtype of logic_type_info * location (** declaration of a logic type. *)
+ | Dlemma of
+ string * bool * logic_label list * string list *
+ predicate * location
+ (** definition of a lemma. The boolean flag is [true] if the property should
+ be taken as an axiom and [false] if it must be proved. *)
+ | Dinvariant of logic_info * location
+ (** global invariant. The predicate does not have any argument. *)
+ | Dtype_annot of logic_info * location
+ (** type invariant. The predicate has exactly one argument. *)
+ | Dmodel_annot of model_info * location
+ (** Model field for a type t, seen as a logic function with one
+ argument of type t *)
+ | Dcustom_annot of custom_tree * string* location
+ (*Custom declaration*)
+
+and custom_tree = CustomDummy
+(*
+ | CustomType of logic_type
+ | CustomLexpr of lexpr
+ | CustomOther of string * (custom_tree list)
+*)
+[@@deriving visitors { variety = "iter"; irregular = true },
+ visitors { variety = "map"; irregular = true },
+ visitors { variety = "endo"; irregular = true },
+ visitors { variety = "reduce"; irregular = true },
+ visitors { variety = "mapreduce"; irregular = true },
+ visitors { variety = "fold"; irregular = true; ancestors = ["VisitorsRuntime.map"] },
+ visitors { variety = "iter2"; irregular = true },
+ visitors { variety = "map2"; irregular = true },
+ visitors { variety = "reduce2"; irregular = true },
+ visitors { variety = "mapreduce2"; irregular = true },
+ visitors { variety = "fold2"; irregular = true; ancestors = ["VisitorsRuntime.map2"] }
+]
+
+(* Provide the missing methods so as to obtain concrete classes. *)
+class ['self] iter_ = object (self : 'self)
+ inherit [_] iter
+ method visit_'locs env (t : identified_term) = self#visit_identified_term env t
+ method visit_'term env (t : term) = self#visit_term env t
+end
+class ['self] map_ = object (self : 'self)
+ inherit [_] map
+ method visit_'locs env (t : identified_term) = self#visit_identified_term env t
+ method visit_'term env (t : term) = self#visit_term env t
+end
+class ['self] endo_ = object (self : 'self)
+ inherit [_] endo
+ method visit_'locs env (t : identified_term) = self#visit_identified_term env t
+ method visit_'term env (t : term) = self#visit_term env t
+end
+class ['self] reduce_ = object (self : 'self)
+ inherit [_] VisitorsRuntime.addition_monoid
+ inherit [_] reduce
+ method visit_'locs env (t : identified_term) = self#visit_identified_term env t
+ method visit_'term env (t : term) = self#visit_term env t
+end
+class ['self] mapreduce_ = object (self : 'self)
+ inherit [_] VisitorsRuntime.addition_monoid
+ inherit [_] mapreduce
+ method visit_'locs env (t : identified_term) = self#visit_identified_term env t
+ method visit_'term env (t : term) = self#visit_term env t
+end
+
+type kinstr =
+ | Kstmt of stmt
+ | Kglobal
+
+(** Internal representation of decorated C functions *)
+type cil_function =
+ | Definition of (fundec * location) (** defined function *)
+ | Declaration of (funspec * varinfo * varinfo list option * location)
+ (** Declaration(spec,f,args,loc) represents a leaf function [f] with
+ specification [spec] and arguments [args], at location [loc]. As
+ with the [TFun] constructor of {!Cil_types.typ}, the arg list is
+ optional, to distinguish [void f()] ([None]) from
+ [void f(void)] ([Some []]). *)
+
+(** Only field [fundec] can be used directly. Use {!Annotations.funspec},
+ [Annotations.add_*] and [Annotations.remove_*] to query or modify field
+ [spec]. *)
+type kernel_function = {
+ mutable fundec : cil_function;
+ mutable spec : funspec;
+}
+
+(* [VP] TODO: VLocal should be attached to a particular block, not a whole
+ function. *)
+type localisation =
+ | VGlobal
+ | VLocal of kernel_function
+ | VFormal of kernel_function
+
+type mach = {
+ sizeof_short: int; (* Size of "short" *)
+ sizeof_int: int; (* Size of "int" *)
+ sizeof_long: int ; (* Size of "long" *)
+ sizeof_longlong: int; (* Size of "long long" *)
+ sizeof_ptr: int; (* Size of pointers *)
+ sizeof_float: int; (* Size of "float" *)
+ sizeof_double: int; (* Size of "double" *)
+ sizeof_longdouble: int; (* Size of "long double" *)
+ sizeof_void: int; (* Size of "void" *)
+ sizeof_fun: int; (* Size of function *)
+ size_t: string; (* Type of "sizeof(T)" *)
+ wchar_t: string; (* Type of "wchar_t" *)
+ ptrdiff_t: string; (* Type of "ptrdiff_t" *)
+ alignof_short: int; (* Alignment of "short" *)
+ alignof_int: int; (* Alignment of "int" *)
+ alignof_long: int; (* Alignment of "long" *)
+ alignof_longlong: int; (* Alignment of "long long" *)
+ alignof_ptr: int; (* Alignment of pointers *)
+ alignof_float: int; (* Alignment of "float" *)
+ alignof_double: int; (* Alignment of "double" *)
+ alignof_longdouble: int; (* Alignment of "long double" *)
+ alignof_str: int; (* Alignment of strings *)
+ alignof_fun: int; (* Alignment of function *)
+ char_is_unsigned: bool; (* Whether "char" is unsigned *)
+ underscore_name: bool; (* If assembly names have leading underscore *)
+ const_string_literals: bool; (* Whether string literals have const chars *)
+ little_endian: bool; (* whether the machine is little endian *)
+ alignof_aligned: int (* Alignment of a type with aligned attribute *);
+ has__builtin_va_list: bool (* Whether [__builtin_va_list] is a known type *);
+ __thread_is_keyword: bool (* Whether [__thread] is a keyword *);
+ compiler: string; (* Compiler being used. Currently recognized names
+ are 'gcc', 'msvc' and 'generic'. *)
+ version: string; (* Information on this machdep *)
+}
diff --git a/test/cil_types.ml.orig b/test/cil_types.ml.orig
new file mode 100644
index 0000000..d5558eb
--- /dev/null
+++ b/test/cil_types.ml.orig
@@ -0,0 +1,1775 @@
+(****************************************************************************)
+(* *)
+(* Copyright (C) 2001-2003 *)
+(* George C. Necula <necula@cs.berkeley.edu> *)
+(* Scott McPeak <smcpeak@cs.berkeley.edu> *)
+(* Wes Weimer <weimer@cs.berkeley.edu> *)
+(* Ben Liblit <liblit@cs.berkeley.edu> *)
+(* All rights reserved. *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in the *)
+(* documentation and/or other materials provided with the distribution. *)
+(* *)
+(* 3. The names of the contributors may not be used to endorse or *)
+(* promote products derived from this software without specific prior *)
+(* written permission. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *)
+(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *)
+(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *)
+(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *)
+(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *)
+(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *)
+(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *)
+(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *)
+(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *)
+(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *)
+(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *)
+(* POSSIBILITY OF SUCH DAMAGE. *)
+(* *)
+(* File modified by CEA (Commissariat à l'énergie atomique et aux *)
+(* énergies alternatives) *)
+(* and INRIA (Institut National de Recherche en Informatique *)
+(* et Automatique). *)
+(****************************************************************************)
+
+(** The Abstract Syntax of CIL.
+ @plugin development guide *)
+
+(**************************** WARNING ***************************************)
+(* Remember to reflect any change here into the visitor and pretty-printer *)
+(* in cil.ml. In particular, if a type becomes mutable, it is necessary to *)
+(* adapt the Cil.behavior type and the copy_behavior accordingly. *)
+(* A first test to see if something has been broken by a change is to launch*)
+(* ptests.byte -add-options '-files-debug "-check -copy"' *)
+(* In addition, it is a good idea to add some invariant checks in the *)
+(* check_file class in frama-c/src/file.ml (before lauching the tests) *)
+(****************************************************************************)
+
+(* ************************************************************************* *)
+(** {2 Root of the AST} *)
+(* ************************************************************************* *)
+
+(** In Frama-C, the whole AST is accessible through {!Ast.get}. *)
+
+(** The top-level representation of a CIL source file (and the result of the
+ parsing and elaboration). Its main contents is the list of global
+ declarations and definitions. You can iterate over the globals in a
+ {!Cil_types.file} using the following iterators: {!Cil.mapGlobals},
+ {!Cil.iterGlobals} and {!Cil.foldGlobals}. You can also use the
+ {!Cil.dummyFile} when you need a {!Cil_types.file} as a placeholder. For
+ each global item CIL stores the source location where it appears (using the
+ type {!Cil_types.location})
+ @plugin development guide *)
+type file = {
+ mutable fileName: string; (** The complete file name *)
+
+ mutable globals: global list;
+ (** List of globals as they will appear in the printed file *)
+
+ mutable globinit: fundec option;
+ (** An optional global initializer function. This is a function where you
+ can put stuff that must be executed before the program is
+ started. This function, is conceptually at the end of the file,
+ although it is not part of the globals list. Use {!Cil.getGlobInit} to
+ create/get one. *)
+
+ mutable globinitcalled: bool;
+(** Whether the global initialization function is called in main. This
+ should always be false if there is no global initializer. When you
+ create a global initialization CIL will try to insert code in main to
+ call it. *)
+}
+
+(** The main type for representing global declarations and definitions. A list
+ of these form a CIL file. The order of globals in the file is generally
+ important.
+ @plugin development guide *)
+and global =
+ | GType of typeinfo * location
+ (** A typedef. All uses of type names (through the [TNamed] constructor)
+ must be preceeded in the file by a definition of the name. The string
+ is the defined name and always not-empty. *)
+
+ | GCompTag of compinfo * location
+ (** Defines a struct/union tag with some fields. There must be one of
+ these for each struct/union tag that you use (through the [TComp]
+ constructor) since this is the only context in which the fields are
+ printed. Consequently nested structure tag definitions must be
+ broken into individual definitions with the innermost structure
+ defined first. *)
+
+ | GCompTagDecl of compinfo * location
+ (** Declares a struct/union tag. Use as a forward declaration. This is
+ printed without the fields. *)
+
+ | GEnumTag of enuminfo * location
+ (** Declares an enumeration tag with some fields. There must be one of
+ these for each enumeration tag that you use (through the [TEnum]
+ constructor) since this is the only context in which the items are
+ printed. *)
+
+ | GEnumTagDecl of enuminfo * location
+ (** Declares an enumeration tag. Use as a forward declaration. This is
+ printed without the items. *)
+
+ | GVarDecl of varinfo * location
+ (** A variable declaration (not a definition) for a variable with object
+ type. There can be several declarations and at most one definition for
+ a given variable. If both forms appear then they must share the same
+ varinfo structure. Either has storage Extern or there must be a
+ definition in this file *)
+
+ | GFunDecl of funspec * varinfo * location
+ (** A variable declaration (not a definition) for a function, i.e. a
+ prototype. There can be several declarations and at most one definition
+ for a given function. If both forms appear then they must share the same
+ varinfo structure. A prototype shares the varinfo with the fundec of the
+ definition. Either has storage Extern or there must be a definition in
+ this file. *)
+
+ | GVar of varinfo * initinfo * location
+ (** A variable definition. Can have an initializer. The initializer is
+ updateable so that you can change it without requiring to recreate the
+ list of globals. There can be at most one definition for a variable in an
+ entire program. Cannot have storage Extern or function type. *)
+
+ | GFun of fundec * location
+ (** A function definition. *)
+
+ | GAsm of string * location
+ (** Global asm statement. These ones can contain only a template *)
+
+ | GPragma of attribute * location
+ (** Pragmas at top level. Use the same syntax as attributes *)
+
+ | GText of string
+ (** Some text (printed verbatim) at top level. E.g., this way you can put
+ comments in the output. *)
+
+ | GAnnot of global_annotation * location
+(** a global annotation. Can be
+ - an axiom or a lemma
+ - a predicate declaration or definition
+ - a global type invariant
+ - a global invariant
+ - a logic function declaration or definition. *)
+
+(* ************************************************************************* *)
+(** {2 Types} *)
+(* ************************************************************************* *)
+
+(** A C type is represented in CIL using the type {!Cil_types.typ}. Among types
+ we differentiate the integral types (with different kinds denoting the sign
+ and precision), floating point types, enumeration types, array and pointer
+ types, and function types. Every type is associated with a list of
+ attributes, which are always kept in sorted order. Use {!Cil.addAttribute}
+ and {!Cil.addAttributes} to construct list of attributes. If you want to
+ inspect a type, you should use {!Cil.unrollType} or {!Cil.unrollTypeDeep} to
+ see through the uses of named types.
+
+ CIL is configured at build-time with the sizes and alignments of the
+ underlying compiler (GCC or MSVC). CIL contains functions that can compute
+ the size of a type (in bits) {!Cil.bitsSizeOf}, the alignment of a type (in
+ bytes) {!Cil.alignOf_int}, and can convert an offset into a start and width
+ (both in bits) using the function {!Cil.bitsOffset}. At the moment these
+ functions do not take into account the [packed] attributes and pragmas. *)
+
+and typ =
+ | TVoid of attributes (** Void type. Also predefined as {!Cil.voidType} *)
+
+ | TInt of ikind * attributes
+ (** An integer type. The kind specifies the sign and width. Several useful
+ variants are predefined as {!Cil.intType}, {!Cil.uintType},
+ {!Cil.longType}, {!Cil.charType}. *)
+
+ | TFloat of fkind * attributes
+ (** A floating-point type. The kind specifies the precision. You can also use
+ the predefined constant {!Cil.doubleType}. *)
+
+ | TPtr of typ * attributes
+ (** Pointer type. Several useful variants are predefined as
+ {!Cil.charPtrType}, {!Cil.charConstPtrType} (pointer to a constant
+ character), {!Cil.voidPtrType}, {!Cil.intPtrType} *)
+
+ | TArray of typ * exp option * bitsSizeofTypCache * attributes
+ (** Array type. It indicates the base type and the array length. *)
+
+ | TFun of typ * (string * typ * attributes) list option * bool * attributes
+ (** Function type. Indicates the type of the result, the name, type
+ and name attributes of the formal arguments ([None] if no arguments
+ were specified, as in a function whose definition or prototype we
+ have not seen; [Some \[\]] means void). Use {!Cil.argsToList} to
+ obtain a list of arguments. The boolean indicates if it is a
+ variable-argument function. If this is the type of a varinfo for
+ which we have a function declaration then the information for the
+ formals must match that in the function's sformals. Use
+ {!Cil.setFormals}, or {!Cil.setFunctionType}, or
+ {!Cil.makeFormalVar} for this purpose. *)
+
+ | TNamed of typeinfo * attributes
+ (** The use of a named type. All uses of the same type name must share the
+ typeinfo. Each such type name must be preceeded in the file by a [GType]
+ global. This is printed as just the type name. The actual referred type
+ is not printed here and is carried only to simplify processing. To see
+ through a sequence of named type references, use {!Cil.unrollType}. The
+ attributes are in addition to those given when the type name was
+ defined. *)
+
+ | TComp of compinfo * bitsSizeofTypCache * attributes
+ (** A reference to a struct or a union type. All references to the
+ same struct or union must share the same compinfo among them and
+ with a [GCompTag] global that preceeds all uses (except maybe
+ those that are pointers to the composite type). The attributes
+ given are those pertaining to this use of the type and are in
+ addition to the attributes that were given at the definition of
+ the type and which are stored in the compinfo. *)
+
+ | TEnum of enuminfo * attributes
+ (** A reference to an enumeration type. All such references must
+ share the enuminfo among them and with a [GEnumTag] global that
+ preceeds all uses. The attributes refer to this use of the
+ enumeration and are in addition to the attributes of the
+ enumeration itself, which are stored inside the enuminfo *)
+
+ | TBuiltin_va_list of attributes
+(** This is the same as the gcc's type with the same name *)
+
+(** Various kinds of integers *)
+and ikind =
+ IBool (** [_Bool] *)
+ | IChar (** [char] *)
+ | ISChar (** [signed char] *)
+ | IUChar (** [unsigned char] *)
+ | IInt (** [int] *)
+ | IUInt (** [unsigned int] *)
+ | IShort (** [short] *)
+ | IUShort (** [unsigned short] *)
+ | ILong (** [long] *)
+ | IULong (** [unsigned long] *)
+ | ILongLong (** [long long] (or [_int64] on Microsoft Visual C) *)
+ | IULongLong (** [unsigned long long] (or [unsigned _int64] on Microsoft
+ Visual C) *)
+
+(** Various kinds of floating-point numbers*)
+and fkind =
+ FFloat (** [float] *)
+ | FDouble (** [double] *)
+ | FLongDouble (** [long double] *)
+
+(** This is used to cache the computation of the size of types in bits. *)
+and bitsSizeofTyp =
+ | Not_Computed
+ | Computed of int
+ | Not_Computable of (string * typ) (** Explanation of the error *)
+
+and bitsSizeofTypCache = { mutable scache : bitsSizeofTyp}
+
+(* ************************************************************************* *)
+(** {2 Attributes} *)
+(* ************************************************************************* *)
+
+and attribute =
+ | Attr of string * attrparam list
+ (** An attribute has a name and some optional parameters. The name should not
+ start or end with underscore. When CIL parses attribute names it will
+ strip leading and ending underscores (to ensure that the multitude of GCC
+ attributes such as const, __const and __const__ all mean the same
+ thing.) *)
+
+ | AttrAnnot of string
+
+(** Attributes are lists sorted by the attribute name. Use the functions
+ {!Cil.addAttribute} and {!Cil.addAttributes} to insert attributes in an
+ attribute list and maintain the sortedness. *)
+and attributes = attribute list
+
+(** The type of parameters of attributes *)
+and attrparam =
+ | AInt of Integer.t (** An integer constant *)
+ | AStr of string (** A string constant *)
+ | ACons of string * attrparam list
+ (** Constructed attributes. These are printed [foo(a1,a2,...,an)]. The list
+ of parameters can be empty and in that case the parentheses are not
+ printed. *)
+ | ASizeOf of typ (** A way to talk about types *)
+ | ASizeOfE of attrparam
+ | AAlignOf of typ
+ | AAlignOfE of attrparam
+ | AUnOp of unop * attrparam
+ | ABinOp of binop * attrparam * attrparam
+ | ADot of attrparam * string (** a.foo **)
+ | AStar of attrparam (** * a *)
+ | AAddrOf of attrparam (** & a **)
+ | AIndex of attrparam * attrparam (** a1[a2] *)
+ | AQuestion of attrparam * attrparam * attrparam (** a1 ? a2 : a3 **)
+
+(* ************************************************************************* *)
+(** {2 Structures} *)
+(* ************************************************************************* *)
+
+(** The {!Cil_types.compinfo} describes the definition of a structure or union
+ type. Each such {!Cil_types.compinfo} must be defined at the top-level using
+ the [GCompTag] constructor and must be shared by all references to this type
+ (using either the [TComp] type constructor or from the definition of the
+ fields.
+
+ If all you need is to scan the definition of each composite type once, you
+ can do that by scanning all top-level [GCompTag].
+
+ Constructing a {!Cil_types.compinfo} can be tricky since it must contain
+ fields that might refer to the host {!Cil_types.compinfo} and furthermore
+ the type of the field might need to refer to the {!Cil_types.compinfo} for
+ recursive types. Use the {!Cil.mkCompInfo} function to create a
+ {!Cil_types.compinfo}. You can easily fetch the {!Cil_types.fieldinfo} for a
+ given field in a structure with {!Cil.getCompField}. *)
+
+(** The definition of a structure or union type. Use {!Cil.mkCompInfo} to make
+ one and use {!Cil.copyCompInfo} to copy one (this ensures that a new key is
+ assigned and that the fields have the right pointers to parents.).
+ @plugin development guide *)
+and compinfo = {
+ mutable cstruct: bool;
+ (** [true] if struct, [false] if union *)
+
+ corig_name: string;
+ (** Original name as found in C file. Will never be changed *)
+
+ mutable cname: string;
+ (** The name. Always non-empty. Use {!Cil.compFullName} to get the full name
+ of a comp (along with the struct or union) *)
+
+ mutable ckey: int;
+ (** A unique integer. This is assigned by {!Cil.mkCompInfo} using a global
+ variable in the Cil module. Thus two identical structs in two different
+ files might have different keys. Use {!Cil.copyCompInfo} to copy
+ structures so that a new key is assigned. *)
+
+ mutable cfields: fieldinfo list;
+ (** Information about the fields. Notice that each fieldinfo has a pointer
+ back to the host compinfo. This means that you should not share
+ fieldinfo's between two compinfo's *)
+
+ mutable cattr: attributes;
+ (** The attributes that are defined at the same time as the composite
+ type. These attributes can be supplemented individually at each
+ reference to this [compinfo] using the [TComp] type constructor. *)
+
+ mutable cdefined: bool;
+ (** This boolean flag can be used to distinguish between structures
+ that have not been defined and those that have been defined but have
+ no fields (such things are allowed in gcc). *)
+
+ mutable creferenced: bool;
+(** [true] if used. Initially set to [false]. *)
+}
+
+(* ************************************************************************* *)
+(** {2 Structure fields} *)
+(* ************************************************************************* *)
+
+(** The {!Cil_types.fieldinfo} structure is used to describe a structure or
+ union field. Fields, just like variables, can have attributes associated
+ with the field itself or associated with the type of the field (stored along
+ with the type of the field). *)
+
+(** Information about a struct/union field.
+ @plugin development guide *)
+and fieldinfo = {
+ mutable fcomp: compinfo;
+ (** The host structure that contains this field. There can be only one
+ [compinfo] that contains the field. *)
+
+ forig_name: string;
+ (** original name as found in C file. *)
+
+ mutable fname: string;
+ (** The name of the field. Might be the value of {!Cil.missingFieldName} in
+ which case it must be a bitfield and is not printed and it does not
+ participate in initialization *)
+
+ mutable ftype: typ;
+ (** The type. If the field is a bitfield, a special attribute
+ [FRAMA_C_BITFIELD_SIZE] indicating the width of the bitfield is added. *)
+
+ mutable fbitfield: int option;
+ (** If a bitfield then ftype should be an integer type and the width of the
+ bitfield must be 0 or a positive integer smaller or equal to the width of
+ the integer type. A field of width 0 is used in C to control the alignment
+ of fields. *)
+
+ mutable fattr: attributes;
+ (** The attributes for this field (not for its type) *)
+
+ mutable floc: location;
+ (** The location where this field is defined *)
+
+ mutable faddrof: bool;
+ (** Adapted from CIL [vaddrof] field for variables. Only set for non-array
+ fields. Variable whose field address is taken is not marked anymore as
+ having its own address taken. True if the address of this field is
+ taken. CIL will set these flags when it parses C, but you should make
+ sure to set the flag whenever your transformation create [AddrOf]
+ expression. *)
+
+ mutable fsize_in_bits: int option;
+ (** (Deprecated. Use {!Cil.bitsOffset} instead.) Similar to [fbitfield] for
+ all types of fields.
+ @deprecated only Jessie uses this *)
+
+ mutable foffset_in_bits: int option;
+ (** Offset at which the field starts in the structure. Do not read directly,
+ but use {!Cil.bitsOffset} instead. *)
+
+ mutable fpadding_in_bits: int option;
+(** (Deprecated.) Store the size of the padding that follows the field, if any.
+ @deprecated only Jessie uses this *)
+}
+
+(* ************************************************************************* *)
+(** {2 Enumerations} *)
+(* ************************************************************************* *)
+
+(** Information about an enumeration. This is shared by all references to an
+ enumeration. Make sure you have a [GEnumTag] for each of these. *)
+
+(** Information about an enumeration.
+ @plugin development guide *)
+and enuminfo = {
+ eorig_name: string; (** original name as found in C file. *)
+
+ mutable ename: string; (** The name. Always non-empty. *)
+
+ mutable eitems: enumitem list; (** Items. The list must be non-empty *)
+
+ mutable eattr: attributes;
+ (** The attributes that are defined at the same time as the enumeration
+ type. These attributes can be supplemented individually at each
+ reference to this [enuminfo] using the [TEnum] type constructor. *)
+
+ mutable ereferenced: bool; (** [true] if used. Initially set to [false]. *)
+ mutable ekind: ikind (** The integer kind used to represent this enum. MSVC
+ always assumes IInt but this is not the case
+ for gcc. See ISO C 6.7.2.2 *)
+}
+
+and enumitem = {
+ eiorig_name: string; (** original name as found in C file. *)
+ mutable einame: string; (** the name, always non-empty. *)
+ mutable eival: exp; (** value of the item. Must be a compile-time constant *)
+ mutable eihost: enuminfo; (** the host enumeration in which the item is
+ declared. *)
+ eiloc: location;
+}
+
+(** Information about a defined type.
+ @plugin development guide *)
+and typeinfo = {
+ torig_name: string; (** original name as found in C file. *)
+
+ mutable tname: string;
+ (** The name. Can be empty only in a [GType] when introducing a composite or
+ enumeration tag. If empty cannot be refered to from the file *)
+
+ mutable ttype: typ;
+ (** The actual type. This includes the attributes that were present in the
+ typedef *)
+
+ mutable treferenced: bool; (** [true] if used. Initially set to [false]. *)
+}
+
+(* ************************************************************************* *)
+(** {2 Variables} *)
+(* ************************************************************************* *)
+
+(** Each local or global variable is represented by a unique
+ {!Cil_types.varinfo} structure. A global {!Cil_types.varinfo} can be
+ introduced with the [GVarDecl] or [GVar], [GFunDecl] or [GFun] globals.
+ A local varinfo can be introduced as part of a function definition
+ {!Cil_types.fundec}.
+
+ All references to a given global or local variable must refer to the same
+ copy of the [varinfo]. Each [varinfo] has a globally unique identifier that
+ can be used to index maps and hashtables (the name can also be used for this
+ purpose, except for locals from different functions). This identifier is
+ constructor using a global counter.
+
+ It is very important that you construct [varinfo] structures using only one
+ of the following functions:
+ - {!Cil.makeGlobalVar} : to make a global variable
+ - {!Cil.makeTempVar} : to make a temporary local variable whose name
+ will be generated so that to avoid conflict with other locals.
+ - {!Cil.makeLocalVar} : like {!Cil.makeTempVar} but you can specify the
+ exact name to be used.
+ - {!Cil.copyVarinfo}: make a shallow copy of a varinfo assigning a new name
+ and a new unique identifier
+
+ A [varinfo] is also used in a function type to denote the list of
+ formals. *)
+
+(** Information about a variable.
+ @plugin development guide *)
+and varinfo = {
+ mutable vname: string;
+ (** The name of the variable. Cannot be empty. It is primarily your
+ responsibility to ensure the uniqueness of a variable name. For local
+ variables {!Cil.makeTempVar} helps you ensure that the name is
+ unique. *)
+
+ vorig_name: string;
+ (** the original name of the variable. Need not be unique. *)
+
+ mutable vtype: typ;
+ (** The declared type of the variable. *)
+
+ mutable vattr: attributes;
+ (** A list of attributes associated with the variable.*)
+
+ mutable vstorage: storage;
+ (** The storage-class *)
+
+ mutable vglob: bool;
+ (** True if this is a global variable*)
+
+ mutable vdefined: bool;
+ (** True if the variable or function is defined in the file. Only relevant
+ for functions and global variables. Not used in particular for local
+ variables and logic variables. *)
+
+ mutable vformal: bool;
+ (** True if the variable is a formal parameter of a function. *)
+
+ mutable vinline: bool;
+ (** Whether this varinfo is for an inline function. *)
+
+ mutable vdecl: location;
+ (** Location of variable declaration. *)
+
+ mutable vid: int;
+ (** A unique integer identifier. This field will be set for you if you use
+ one of the {!Cil.makeFormalVar}, {!Cil.makeLocalVar},
+ {!Cil.makeTempVar}, {!Cil.makeGlobalVar}, or {!Cil.copyVarinfo}. *)
+
+ mutable vaddrof: bool;
+ (** [true] if the address of this variable is taken. CIL will set these
+ flags when it parses C, but you should make sure to set the flag
+ whenever your transformation create [AddrOf] expression. *)
+
+ mutable vreferenced: bool;
+ (** [true] if this variable is ever referenced. This is computed by
+ [removeUnusedVars]. It is safe to just initialize this to [false]. *)
+
+ vtemp: bool;
+ (** [true] for temporary variables generated by CIL normalization. [false]
+ for all the other variables. *)
+
+ mutable vdescr: string option;
+ (** For most temporary variables, a description of what the var holds.
+ (e.g. for temporaries used for function call results, this string is a
+ representation of the function call.) *)
+
+ mutable vdescrpure: bool;
+ (** Indicates whether the vdescr above is a pure expression or call. True
+ for all CIL expressions and Lvals, but false for e.g. function calls.
+ Printing a non-pure vdescr more than once may yield incorrect
+ results. *)
+
+ mutable vghost: bool;
+ (** Indicates if the variable is declared in ghost code *)
+
+ vsource: bool;
+ (** [true] iff this variable appears in the source of the program, which is
+ the case of all the variables in the initial AST. Plugins may create
+ variables with [vsource=false], for example to handle dynamic allocation.
+ Those variables do *not* have an associated {!GVar} or {!GVarDecl}. *)
+
+ mutable vlogic_var_assoc: logic_var option
+ (** Logic variable representing this variable in the logic world. Do not
+ access this field directly. Instead, call {!Cil.cvar_to_lvar}. *)
+}
+
+(** Storage-class information *)
+and storage =
+ NoStorage (** The default storage. Nothing is printed *)
+ | Static
+ | Register
+ | Extern
+
+(* ************************************************************************* *)
+(** {2 Expressions} *)
+(* ************************************************************************* *)
+
+(** The CIL expression language contains only the side-effect free expressions
+ of C. They are represented as the type {!Cil_types.exp}. There are several
+ interesting aspects of CIL expressions:
+
+ Integer and floating point constants can carry their textual representation.
+ This way the integer 15 can be printed as 0xF if that is how it occurred in
+ the source.
+
+ CIL uses arbitrary precision integers
+ to represent the integer constants and also stores the
+ width of the integer type. Care must be taken to ensure that the constant is
+ representable with the given width. Use the functions {!Cil.kinteger},
+ {!Cil.kinteger64} and {!Cil.integer} to construct constant expressions. CIL
+ predefines the constants {!Cil.zero}, {!Cil.one} and {!Cil.mone} (for -1).
+
+ Use the functions {!Cil.isConstant} and {!Cil.isInteger} to test if an
+ expression is a constant and a constant integer respectively.
+
+ CIL keeps the type of all unary and binary expressions. You can think of
+ that type qualifying the operator. Furthermore there are different operators
+ for arithmetic and comparisons on arithmetic types and on pointers.
+
+ Another unusual aspect of CIL is that the implicit conversion between an
+ expression of array type and one of pointer type is made explicit, using the
+ [StartOf] expression constructor (which is not printed). If you apply the
+ [AddrOf]constructor to an lvalue of type [T] then you will be getting an
+ expression of type [TPtr(T)].
+
+ You can find the type of an expression with {!Cil.typeOf}.
+
+ You can perform constant folding on expressions using the function
+ {!Cil.constFold}. *)
+
+(** Expressions (Side-effect free)*)
+and exp = {
+ eid: int; (** unique identifier *)
+ enode: exp_node; (** the expression itself *)
+ eloc: location; (** location of the expression. *)
+}
+
+and exp_node =
+ | Const of constant (** Constant *)
+ | Lval of lval (** Lvalue *)
+ | SizeOf of typ
+ (** sizeof(<type>). Has [unsigned int] type (ISO 6.5.3.4). This is not
+ turned into a constant because some transformations might want to change
+ types *)
+
+ | SizeOfE of exp (** sizeof(<expression>) *)
+
+ | SizeOfStr of string
+ (** sizeof(string_literal). We separate this case out because this is the
+ only instance in which a string literal should not be treated as having
+ type pointer to character. *)
+
+ | AlignOf of typ
+ (** This corresponds to the GCC __alignof_. Has [unsigned int] type *)
+
+ | AlignOfE of exp
+
+ | UnOp of unop * exp * typ
+ (** Unary operation. Includes the type of the result. *)
+
+ | BinOp of binop * exp * exp * typ
+ (** Binary operation. Includes the type of the result. The arithmetic
+ conversions are made explicit for the arguments.
+ @plugin development guide *)
+
+ | CastE of typ * exp
+ (** Use {!Cil.mkCast} to make casts. *)
+
+ | AddrOf of lval
+ (** Always use {!Cil.mkAddrOf} to construct one of these. Apply to an lvalue
+ of type [T] yields an expression of type [TPtr(T)] *)
+
+ | StartOf of lval
+ (** Conversion from an array to a pointer to the beginning of the array.
+ Given an lval of type [TArray(T)] produces an expression of type
+ [TPtr(T)]. In C this operation is implicit, the [StartOf] operator is not
+ printed. We have it in CIL because it makes the typing rules simpler. *)
+
+ | Info of exp * exp_info
+(** Additional information on the underlying expression *)
+
+(** Additional information on an expression *)
+and exp_info = {
+ exp_type : logic_type; (** when used as placeholder for a term *)
+ exp_name: string list;
+}
+
+(* ************************************************************************* *)
+(** {2 Constants} *)
+(* ************************************************************************* *)
+
+(** Literal constants *)
+and constant =
+ | CInt64 of Integer.t * ikind * string option
+ (** Integer constant. Give the ikind (see ISO9899 6.1.3.2) and the
+ textual representation. Textual representation is always set to Some s
+ when it comes from user code. This allows us to print a
+ constant as it was represented in the code, for example,
+ 0xF instead of 15. It is usually None for constant generated by Cil
+ itself. Use {!Cil.integer} or {!Cil.kinteger} to create these. *)
+
+ | CStr of string
+ (** String constant. The escape characters inside the string have been already
+ interpreted. This constant has pointer to character type! The only case
+ when you would like a string literal to have an array type is when it is
+ an argument to sizeof. In that case you should use SizeOfStr. *)
+
+ | CWStr of int64 list
+ (** Wide character string constant. Note that the local interpretation of such
+ a literal depends on {!Cil.theMachine.wcharType} and
+ {!Cil.theMachine.wcharKind}. Such a constant has type pointer to
+ {!Cil.theMachine.wcharType}. The escape characters in the string have not
+ been "interpreted" in the sense that L"A\xabcd" remains "A\xabcd" rather
+ than being represented as the wide character list with two elements: 65
+ and 43981. That "interpretation" depends on the underlying wide character
+ type. *)
+
+ | CChr of char
+ (** Character constant. This has type int, so use charConstToInt to read the
+ value in case sign-extension is needed. *)
+
+ | CReal of float * fkind * string option
+ (** Floating point constant. Give the fkind (see ISO 6.4.4.2) and also the
+ textual representation, if available. *)
+
+ | CEnum of enumitem
+(** An enumeration constant. Use [Cillower.lowerEnumVisitor] to replace these
+ with integer constants. *)
+
+(** Unary operators *)
+and unop =
+ Neg (** Unary minus *)
+ | BNot (** Bitwise complement (~) *)
+ | LNot (** Logical Not (!) *)
+
+(** Binary operations *)
+and binop =
+ PlusA (** arithmetic + *)
+ | PlusPI (** pointer + integer *)
+ | IndexPI (** pointer + integer but only when it arises from an expression
+ [e\[i\]] when [e] is a pointer and
+ not an array. This is semantically
+ the same as PlusPI but CCured uses
+ this as a hint that the integer is
+ probably positive. *)
+ | MinusA (** arithmetic - *)
+ | MinusPI (** pointer - integer *)
+ | MinusPP (** pointer - pointer *)
+ | Mult (** * *)
+ | Div (** /
+ @plugin development guide *)
+ | Mod (** %
+ @plugin development guide *)
+ | Shiftlt (** shift left *)
+ | Shiftrt (** shift right *)
+
+ | Lt (** < (arithmetic comparison) *)
+ | Gt (** > (arithmetic comparison) *)
+ | Le (** <= (arithmetic comparison) *)
+ | Ge (** >= (arithmetic comparison) *)
+ | Eq (** == (arithmetic comparison) *)
+ | Ne (** != (arithmetic comparison) *)
+ | BAnd (** bitwise and *)
+ | BXor (** exclusive-or *)
+ | BOr (** inclusive-or *)
+
+ | LAnd (** logical and. Unlike other expressions this one does not always
+ evaluate both operands. If you want
+ to use these, you must set
+ {!Cil.useLogicalOperators}. *)
+ | LOr (** logical or. Unlike other expressions this one does not always
+ evaluate both operands. If you
+ want to use these, you must set
+ {!Cil.useLogicalOperators}. *)
+
+(* ************************************************************************* *)
+(** {2 Left values} *)
+(* ************************************************************************* *)
+
+(** Left values (aka Lvalues) are the sublanguage of expressions that can appear
+ at the left of an assignment or as operand to the address-of operator. In C
+ the syntax for lvalues is not always a good indication of the meaning of the
+ lvalue. For example the C value {v a[0][1][2] v} might involve 1, 2 or 3
+ memory reads when used in an expression context, depending on the declared
+ type of the variable [a]. If [a] has type [int \[4\]\[4\]\[4\]] then we have
+ one memory read from somewhere inside the area that stores the array [a]. On
+ the other hand if [a] has type [int ***] then the expression really means [*
+ ( * ( * (a + 0) + 1) + 2)], in which case it is clear that it involves three
+ separate memory operations.
+
+ An lvalue denotes the contents of a range of memory addresses. This range is
+ denoted as a host object along with an offset within the object. The host
+ object can be of two kinds: a local or global variable, or an object whose
+ address is in a pointer expression. We distinguish the two cases so that we
+ can tell quickly whether we are accessing some component of a variable
+ directly or we are accessing a memory location through a pointer. To make
+ it easy to tell what an lvalue means CIL represents lvalues as a host object
+ and an offset (see {!Cil_types.lval}). The host object (represented as
+ {!Cil_types.lhost}) can be a local or global variable or can be the object
+ pointed-to by a pointer expression. The offset (represented as
+ {!Cil_types.offset}) is a sequence of field or array index designators.
+
+ Both the typing rules and the meaning of an lvalue is very precisely
+ specified in CIL.
+
+ The following are a few useful function for operating on lvalues:
+ - {!Cil.mkMem} - makes an lvalue of [Mem] kind. Use this to ensure
+ that certain equivalent forms of lvalues are canonized.
+ For example, [*&x = x].
+ - {!Cil.typeOfLval} - the type of an lvalue
+ - {!Cil.typeOffset} - the type of an offset, given the type of the
+ host.
+ - {!Cil.addOffset} and {!Cil.addOffsetLval} - extend sequences
+ of offsets.
+ - {!Cil.removeOffset} and {!Cil.removeOffsetLval} - shrink sequences
+ of offsets.
+
+ The following equivalences hold {v
+ Mem(AddrOf(Mem a, aoff)), off = Mem a, aoff + off
+ Mem(AddrOf(Var v, aoff)), off = Var v, aoff + off
+ AddrOf (Mem a, NoOffset) = a
+ v} *)
+
+and lval = lhost * offset
+
+(** The host part of an {!Cil_types.lval}. *)
+and lhost =
+ | Var of varinfo
+ (** The host is a variable. *)
+
+ | Mem of exp
+(** The host is an object of type [T] when the expression has pointer
+ [TPtr(T)]. *)
+
+
+(** The offset part of an {!Cil_types.lval}. Each offset can be applied to
+ certain kinds of lvalues and its effect is that it advances the starting
+ address of the lvalue and changes the denoted type, essentially focussing
+ to some smaller lvalue that is contained in the original one.
+ @plugin development guide *)
+and offset =
+ | NoOffset
+ (** No offset. Can be applied to any lvalue and does not change either the
+ starting address or the type. This is used when the lval consists of just
+ a host or as a terminator in a list of other kinds of offsets. *)
+
+ | Field of fieldinfo * offset
+ (** A field offset. Can be applied only to an lvalue that denotes a structure
+ or a union that contains the mentioned field. This advances the offset to
+ the beginning of the mentioned field and changes the type to the type of
+ the mentioned field. *)
+
+ | Index of exp * offset
+(** An array index offset. Can be applied only to an lvalue that denotes an
+ array. This advances the starting address of the lval to the beginning of
+ the mentioned array element and changes the denoted type to be the type of
+ the array element *)
+
+(* ************************************************************************* *)
+(** {2 Initializers} *)
+(* ************************************************************************* *)
+
+(** A special kind of expressions are those that can appear as initializers for
+ global variables (initialization of local variables is turned into
+ assignments). The initializers are represented as type
+ {!Cil_types.init}. You can create initializers with {!Cil.makeZeroInit} and
+ you can conveniently scan compound initializers them with
+ {!Cil.foldLeftCompound}. *)
+
+(** Initializers for global variables. *)
+and init =
+ | SingleInit of exp (** A single initializer *)
+ | CompoundInit of typ * (offset * init) list
+(** Used only for initializers of structures, unions and arrays. The offsets
+ are all of the form [Field(f, NoOffset)] or [Index(i, NoOffset)] and
+ specify the field or the index being initialized. For structures all fields
+ must have an initializer (except the unnamed bitfields), in the proper
+ order. This is necessary since the offsets are not printed. For arrays the
+ list must contain a prefix of the initializers; the rest are 0-initialized.
+ For unions there must be exactly one initializer. If the initializer is not
+ for the first field then a field designator is printed, so you better be on
+ GCC since MSVC does not understand this. You can scan an initializer list
+ with {!Cil.foldLeftCompound}. *)
+
+(** We want to be able to update an initializer in a global variable, so we
+ define it as a mutable field *)
+and initinfo = { mutable init : init option }
+
+(* ************************************************************************* *)
+(** {2 Function definitions} *)
+(* ************************************************************************* *)
+
+(** A function definition is always introduced with a [GFun] constructor at the
+ top level. All the information about the function is stored into a
+ {!Cil_types.fundec}. Some of the information (e.g. its name, type, storage,
+ attributes) is stored as a {!Cil_types.varinfo} that is a field of the
+ [fundec]. To refer to the function from the expression language you must use
+ the [varinfo].
+
+ The function definition contains, in addition to the body, a list of all the
+ local variables and separately a list of the formals. Both kind of variables
+ can be referred to in the body of the function. The formals must also be
+ shared with the formals that appear in the function type. For that reason,
+ to manipulate formals you should use the provided functions
+ {!Cil.makeFormalVar} and {!Cil.setFormals}. *)
+
+(** Function definitions.
+ @plugin development guide *)
+and fundec = {
+ mutable svar: varinfo;
+ (** Holds the name and type as a variable, so we can refer to it easily
+ from the program. All references to this function either in a function
+ call or in a prototype must point to the same [varinfo]. *)
+
+ mutable sformals: varinfo list;
+ (** Formals. These must be in the same order and with the same information
+ as the formal information in the type of the function. Use
+ {!Cil.setFormals} or {!Cil.setFunctionType} to set these formals and
+ ensure that they are reflected in the function type. Do not make
+ copies of these because the body refers to them. *)
+
+ mutable slocals: varinfo list;
+ (** Locals. Does NOT include the sformals. Do not make copies of these
+ because the body refers to them. *)
+
+ mutable smaxid: int;
+ (** Max local id. Starts at 0. Used for creating the names of new
+ temporary variables. Updated by {!Cil.makeLocalVar} and
+ {!Cil.makeTempVar}. You can also use {!Cil.setMaxId} to set it after
+ you have added the formals and locals. *)
+
+ mutable sbody: block; (** The function body. *)
+
+ mutable smaxstmtid: int option;
+ (** max id of a (reachable) statement in this function, if we have
+ computed it. range = 0 ... (smaxstmtid-1). This is computed by
+ {!Cfg.computeCFGInfo}. *)
+
+ mutable sallstmts: stmt list;
+ (** After you call {!Cfg.computeCFGInfo} this field is set to contain all
+ statements in the function. *)
+
+ mutable sspec: funspec;
+}
+
+(** A block is a sequence of statements with the control falling through from
+ one element to the next *)
+and block = {
+ mutable battrs: attributes; (** Attributes for the block *)
+
+ mutable blocals: varinfo list;
+ (** variables that are local to the block. It is a subset of the slocals of
+ the enclosing function. *)
+
+ mutable bstmts: stmt list; (** The statements comprising the block. *)
+}
+
+(* ************************************************************************* *)
+(** {2 Statements} *)
+(* ************************************************************************* *)
+
+(** CIL statements are the structural elements that make the CFG. They are
+ represented using the type {!Cil_types.stmt}. Every statement has a
+ (possibly empty) list of labels. The {!Cil_types.stmtkind} field of a
+ statement indicates what kind of statement it is.
+
+ Use {!Cil.mkStmt} to make a statement and the fill-in the fields.
+
+ CIL also comes with support for control-flow graphs. The [sid] field in
+ [stmt] can be used to give unique numbers to statements, and the [succs] and
+ [preds] fields can be used to maintain a list of successors and predecessors
+ for every statement. The CFG information is not computed by default. Instead
+ you must explicitly use the functions {!Cfg.prepareCFG} and
+ {!Cfg.computeCFGInfo} to do it. *)
+
+(** Statements.
+ @plugin development guide *)
+and stmt = {
+ mutable labels: label list;
+ (** Whether the statement starts with some labels, case statements or
+ default statements. *)
+
+ mutable skind: stmtkind;
+ (** The kind of statement *)
+
+ mutable sid: int;
+ (** A number (>= 0) that is unique in a function. Filled in only after the
+ CFG is computed. *)
+
+ mutable succs: stmt list;
+ (** The successor statements. They can always be computed from the skind and
+ the context in which this statement appears. Filled in only after the CFG
+ is computed. *)
+
+ mutable preds: stmt list;
+ (** The inverse of the succs function. *)
+
+ mutable ghost : bool
+}
+
+(** Labels *)
+and label =
+ | Label of string * location * bool
+ (** A real label. If the bool is "true", the label is from the input source
+ program. If the bool is "false", the label was created by CIL or some
+ other transformation *)
+
+ | Case of exp * location
+ (** A case statement. This expression is lowered into a constant if
+ {!Cil.lowerConstants} is set to [true]. *)
+
+ | Default of location (** A default statement *)
+
+(* The various kinds of statements *)
+and stmtkind =
+ | Instr of instr
+ (** An instruction that does not contain control flow. Control implicitly
+ falls through.
+ @plugin development guide *)
+
+ | Return of exp option * location
+ (** The return statement. This is a leaf in the CFG.
+ @plugin development guide *)
+
+ | Goto of stmt ref * location
+ (** A goto statement. Appears from actual goto's in the code or from goto's
+ that have been inserted during elaboration. The reference points to the
+ statement that is the target of the Goto. This means that you have to
+ update the reference whenever you replace the target statement. The
+ target statement MUST have at least a label.
+ @plugin development guide *)
+
+ | Break of location
+ (** A break to the end of the nearest enclosing Loop or Switch.
+ @plugin development guide *)
+
+ | Continue of location
+ (** A continue to the start of the nearest enclosing [Loop].
+ @plugin development guide *)
+
+ | If of exp * block * block * location
+ (** A conditional. Two successors, the "then" and the "else" branches (in
+ this order).
+ Both branches fall-through to the successor of the If statement.
+ @plugin development guide *)
+
+ | Switch of exp * block * (stmt list) * location
+ (** A switch statement. [exp] is the index of the switch. [block] is
+ the body of the switch. [stmt list] contains the set of
+ statements whose [labels] are cases of the switch (i.e. for each
+ case, the corresponding statement is in [stmt list], a statement
+ cannot appear more than once in the list, and statements in
+ [stmt list] can have several labels corresponding to several
+ cases.
+ @plugin development guide *)
+
+ | Loop of
+ code_annotation list * block * location * (stmt option) * (stmt option)
+ (** A [while(1)] loop. The termination test is implemented in the body of a
+ loop using a [Break] statement. If {!Cfg.prepareCFG} has been called, the
+ first stmt option will point to the stmt containing the continue label
+ for this loop and the second will point to the stmt containing the break
+ label for this loop.
+ @plugin development guide *)
+
+ | Block of block
+ (** Just a block of statements. Use it as a way to keep some block attributes
+ local.
+ @plugin development guide *)
+
+ | UnspecifiedSequence of (stmt * lval list
+ * lval list * lval list * stmt ref list) list
+ (** statements whose order of execution is not specified by
+ ISO/C. This is important for the order of side effects
+ during evaluation of expressions. Each statement comes
+ together with three list of lval, in this order.
+ - lvals that are written during the sequence and whose future
+ value depends upon the statement (it is legal to read from them, but
+ not to write to them)
+ - lvals that are written during the evaluation of the statement itself
+ - lval that are read.
+ - Function calls in the corresponding statement
+ Note that this include only a subset of the affectations
+ of the statement. Namely, the
+ temporary variables generated by cil are excluded (i.e. it
+ is assumed that the "compilation" is correct). In addition,
+ side effects caused by function applications are not taken
+ into account in the list. For a single statement, the written lvals
+ are supposed to be ordered (or their order of evaluation doesn't
+ matter), so that an alarm should be emitted only if the lvals read by
+ a statement overlap with the lvals written (or read) by another
+ statement of the sequence.
+
+ At this time this feature is
+ experimental and may miss some unspecified sequences.
+
+ In case you do not care about this feature just handle it
+ like a block (see {!Cil.block_from_unspecified_sequence}).
+ @plugin development guide *)
+
+ | Throw of (exp * typ) option * location
+ (** Throws an exception, C++ style.
+ We keep the type of the expression, to match
+ it against the appropriate catch clause. A Throw node has
+ no successor, even if it is in try-catch block that will catch
+ the exception: we keep normal and exceptional control-flow
+ completely separate, as in Jo and Chang, ICSSA 2004.
+ *)
+
+ | TryCatch of block * (catch_binder * block) list * location
+
+ | TryFinally of block * block * location
+ (** On MSVC we support structured exception handling. This is what you might
+ expect. Control can get into the finally block either from the end of the
+ body block, or if an exception is thrown.
+ @plugin development guide *)
+
+ | TryExcept of block * (instr list * exp) * block * location
+(** On MSVC we support structured exception handling. The try/except
+ statement is a bit tricky:
+ {v __try \{ blk \}
+ __except (e) \{
+ handler
+ \}
+ v}
+
+ The argument to __except must be an expression. However, we keep a
+ list of instructions AND an expression in case you need to make
+ function calls. We'll print those as a comma expression. The control
+ can get to the __except expression only if an exception is thrown.
+ After that, depending on the value of the expression the control
+ goes to the handler, propagates the exception, or retries the
+ exception. The location corresponds to the try keyword.
+ @plugin development guide *)
+
+(** Kind of exceptions that are caught by a given clause. *)
+and catch_binder =
+ | Catch_exn of varinfo * (varinfo * block) list
+ (** catch exception of given type(s).
+ If the list is empty, only exceptions with the same type as the
+ varinfo can be caught. If the list is non-empty, only exceptions
+ matching one of the type of a varinfo in the list are caught.
+ The associated block contains the operations necessary to transform
+ the matched varinfo into the principal one.
+ Semantics is by value (i.e. the varinfo is bound to a copy of the
+ caught object).
+
+ This clause is a declaration point for the varinfo(s)
+ mentioned in it. More precisely, for
+ [Catch_exn(v_0,[(v_1, b_1),..., (v_n, b_n)])],
+ the [v_i] must be referenced in the [slocals] of the
+ enclosing [fundec], and _must not_ appear in any [blocals]
+ of some block. The scope of v_0 is all the [b_i] and
+ the corresponding block in the [catch_binder * block list] of the
+ [TryCatch] node the binder belongs to. The scope of the other [v_i]
+ is the corresponding [b_i].
+ *)
+ | Catch_all (** default catch clause: all exceptions are caught. *)
+
+(** Instructions. They may cause effects directly but may not have control
+ flow.*)
+and instr =
+ | Set of lval * exp * location
+ (** An assignment. A cast is present if the exp has different type from
+ lval *)
+
+ | Call of lval option * exp * exp list * location
+ (** optional: result is an lval. A cast might be necessary if the declared
+ result type of the function is not the same as that of the destination.
+ Actual arguments must have a type equivalent (i.e. {!Cil.need_cast} must
+ return [false]) to the one of the formals of the function.
+ If the type of the result variable is not the same as the declared type of
+ the function result then an implicit cast exists.
+ *)
+
+ (* See the GCC specification for the meaning of ASM.
+ If the source is MS VC then only the templates
+ are used.
+
+ [sm] I've added a notes.txt file which contains more
+ information on interpreting Asm instructions *)
+ | Asm of
+ attributes (* Really only const and volatile can appear here *)
+ * string list (* templates (CR-separated) *)
+ * extended_asm option
+ * location
+ (** An inline assembly instruction. The arguments are
+ (1) a list of attributes (only const and volatile can appear here and only
+ for GCC)
+ (2) templates (CR-separated)
+ (3) GCC extended asm information if any
+ (4) location information *)
+
+ | Skip of location
+
+ | Code_annot of code_annotation * location
+
+
+(** GNU extended-asm information:
+ - a list of outputs, each of which is an lvalue with optional names and
+ constraints.
+ - a list of input expressions along with constraints
+ - clobbered registers
+ - Possible destinations statements *)
+and extended_asm =
+ {
+ asm_outputs: (string option * string * lval) list
+ (** outputs must be lvals with optional names and constraints. I would
+ like these to be actually variables, but I run into some trouble with
+ ASMs in the Linux sources *);
+ asm_inputs: (string option * string * exp) list
+ (** inputs with optional names and constraints *);
+ asm_clobbers: string list (** register clobbers *);
+ asm_gotos: (stmt ref) list
+ (** list of statements this asm section may jump to. Destination
+ must have a label. *);
+ }
+
+(** Describes a location in a source file *)
+and location = Lexing.position * Lexing.position
+
+(** {1 Abstract syntax trees for annotations} *)
+
+and logic_constant =
+ | Integer of Integer.t * string option
+ (** Integer constant with a textual representation. *)
+ | LStr of string (** String constant. *)
+ | LWStr of int64 list (** Wide character string constant. *)
+ | LChr of char (** Character constant. *)
+ | LReal of logic_real
+ | LEnum of enumitem (** An enumeration constant.*)
+
+(** Real constants. *)
+and logic_real = {
+ r_literal : string ; (** Initial string representation [s]. *)
+ r_nearest : float ; (** Nearest approximation of [s] in double precision. *)
+ r_upper : float ; (** Smallest double [u] such that [s <= u]. *)
+ r_lower : float ; (** Greatest double [l] such that [l <= s]. *)
+}
+
+(** Types of logic terms. *)
+and logic_type =
+ | Ctype of typ (** a C type *)
+ | Ltype of logic_type_info * logic_type list
+ (** an user-defined logic type with its parameters *)
+ | Lvar of string (** a type variable. *)
+ | Linteger (** mathematical integers, {i i.e.} Z *)
+ | Lreal (** mathematical reals, {i i.e.} R *)
+ | Larrow of logic_type list * logic_type (** (n-ary) function type *)
+
+(** tsets with an unique identifier.
+ Use [Logic_const.new_location] to generate a new id. *)
+and identified_term = {
+ it_id: int; (** the identifier. *)
+ it_content: term (** the term *)
+}
+
+(** logic label referring to a particular program point. *)
+and logic_label =
+ | StmtLabel of stmt ref (** label of a C statement. *)
+ | LogicLabel of (stmt option * string) (* [JS 2011/05/13] why a tuple here? *)
+(** builtin logic label ({t Here, Pre}, ...) *)
+
+(* ************************************************************************* *)
+(** {2 Terms} *)
+(* ************************************************************************* *)
+
+(** C Expressions as logic terms follow C constructs (with prefix T) *)
+
+(** Logic terms. *)
+and term = {
+ term_node : term_node; (** kind of term. *)
+ term_loc : Lexing.position * Lexing.position;
+ (** position in the source file. *)
+ term_type : logic_type; (** type of the term. *)
+ term_name: string list;
+ (** names of the term if any. A name can be an arbitrary string, where
+ '"' and '\'' are escaped by a \, and which does not end with a \.
+ Hence, "name" and 'name' should be recognized as a unique label by most
+ tools. *)
+}
+
+(** the various kind of terms. *)
+and term_node =
+ (* same constructs as exp *)
+ | TConst of logic_constant (** a constant. *)
+ | TLval of term_lval (** an L-value *)
+ | TSizeOf of typ (** size of a given C type. *)
+ | TSizeOfE of term (** size of the type of an expression. *)
+ | TSizeOfStr of string (** size of a string constant. *)
+ | TAlignOf of typ (** alignment of a type. *)
+ | TAlignOfE of term (** alignment of the type of an expression. *)
+ | TUnOp of unop * term (** unary operator. *)
+ | TBinOp of binop * term * term (** binary operators. *)
+ | TCastE of typ * term (** cast to a C type. *)
+ | TAddrOf of term_lval (** address of a term. *)
+ | TStartOf of term_lval (** beginning of an array. *)
+
+ (* additional constructs *)
+ | Tapp of logic_info * (logic_label * logic_label) list * term list
+ (** application of a logic function. *)
+ | Tlambda of quantifiers * term (** lambda abstraction. *)
+ | TDataCons of logic_ctor_info * term list
+ (** constructor of logic sum-type. *)
+ | Tif of term * term * term
+ (** conditional operator*)
+ | Tat of term * logic_label
+ (** term refers to a particular program point. *)
+ | Tbase_addr of logic_label * term (** base address of a pointer. *)
+ | Toffset of logic_label * term (** offset from the base address of a pointer. *)
+ | Tblock_length of logic_label * term (** length of the block pointed to by the term. *)
+ | Tnull (** the null pointer. *)
+ | TLogic_coerce of logic_type * term
+ (** implicit conversion from a C type to a logic type.
+ The logic type must not be a Ctype. In particular, used to denote
+ lifting to Linteger and Lreal.
+ *)
+ | TCoerce of term * typ (** coercion to a given C type. *)
+ | TCoerceE of term * term (** coercion to the type of a given term. *)
+ | TUpdate of term * term_offset * term
+ (** functional update of a field. *)
+ | Ttypeof of term (** type tag for a term. *)
+ | Ttype of typ (** type tag for a C type. *)
+ | Tempty_set (** the empty set. *)
+ | Tunion of term list (** union of terms. *)
+ | Tinter of term list (** intersection of terms. *)
+ | Tcomprehension of
+ term * quantifiers * predicate option
+ (** set defined in comprehension ({t \{ t[i] | integer i; 0 <= i < 5\}}) *)
+ | Trange of term option * term option (** range of integers. *)
+ | Tlet of logic_info * term (** local binding *)
+
+(** lvalue: base address and offset. *)
+and term_lval =
+ term_lhost * term_offset
+
+(** base address of an lvalue. *)
+and term_lhost =
+ | TVar of logic_var (** a variable. *)
+ | TResult of typ (** value returned by a C function.
+ Only used in post-conditions or assigns
+ *)
+ | TMem of term (** memory access. *)
+
+(** model field. *)
+and model_info = {
+ mi_name: string; (** name *)
+ mi_field_type: logic_type; (** type of the field *)
+ mi_base_type: typ; (** type to which the field is associated. *)
+ mi_decl: location; (** where the field has been declared. *)
+}
+
+(** offset of an lvalue. *)
+and term_offset =
+ | TNoOffset (** no further offset. *)
+ | TField of fieldinfo * term_offset
+ (** access to the field of a compound type. *)
+ | TModel of model_info * term_offset (** access to a model field. *)
+ | TIndex of term * term_offset
+ (** index. Note that a range is denoted by [TIndex(Trange(i1,i2),ofs)] *)
+
+(** description of a logic function or predicate.
+@plugin development guide *)
+and logic_info = {
+(*
+ mutable l_name : string; (** name of the function. *)
+*)
+ mutable l_var_info : logic_var;
+ (** we use only fields lv_name and lv_id of l_var_info
+ we should factorize lv_type and l_type+l_profile below *)
+ mutable l_labels : logic_label list; (** label arguments of the function. *)
+ mutable l_tparams : string list; (** type parameters *)
+ mutable l_type : logic_type option; (** return type. None for predicates *)
+ mutable l_profile : logic_var list; (** type of the arguments. *)
+ mutable l_body : logic_body; (** body of the function. *)
+}
+
+and builtin_logic_info = {
+ mutable bl_name: string;
+ mutable bl_labels: logic_label list;
+ mutable bl_params: string list;
+ mutable bl_type: logic_type option;
+ mutable bl_profile: (string * logic_type) list;
+}
+
+and logic_body =
+ | LBnone (** no definition and no reads clause *)
+ | LBreads of identified_term list
+ (** read accesses performed by a function. *)
+ | LBterm of term (** direct definition of a function. *)
+ | LBpred of predicate (** direct definition of a predicate. *)
+ | LBinductive of
+ (string * logic_label list * string list * predicate) list
+ (** inductive definition *)
+
+(** Description of a logic type.
+ @plugin development guide *)
+and logic_type_info = {
+ lt_name: string;
+ lt_params : string list; (** type parameters*)
+ mutable lt_def: logic_type_def option
+ (** definition of the type. None for abstract types. *)
+}
+(* will be expanded when dealing with concrete types *)
+
+and logic_type_def =
+ | LTsum of logic_ctor_info list (** sum type with its constructors. *)
+ | LTsyn of logic_type (** Synonym of another type. *)
+
+(** origin of a logic variable. *)
+and logic_var_kind =
+ | LVGlobal (** global logic function or predicate. *)
+ | LVC (** Logic counterpart of a C variable. *)
+ | LVFormal (** formal parameter of a logic function / predicate
+ or \lambda abstraction *)
+ | LVQuant (** Bound by a quantifier (\exists or \forall) *)
+ | LVLocal (** local \let *)
+
+(** description of a logic variable
+@plugin development guide *)
+and logic_var = {
+ mutable lv_name : string; (** name of the variable. *)
+ mutable lv_id : int; (** unique identifier *)
+ mutable lv_type : logic_type; (** type of the variable. *)
+ mutable lv_kind: logic_var_kind; (** kind of the variable *)
+ mutable lv_origin : varinfo option
+(** when the logic variable stems from a C variable, set to the original C
+ variable. *)
+}
+
+(** Description of a constructor of a logic sum-type.
+ @plugin development guide *)
+and logic_ctor_info =
+ { ctor_name: string; (** name of the constructor. *)
+ ctor_type: logic_type_info; (** type to which the constructor belongs. *)
+ ctor_params: logic_type list
+ (** types of the parameters of the constructor. *)
+ }
+
+(* ************************************************************************* *)
+(** {2 Predicates} *)
+(* ************************************************************************* *)
+
+(** variables bound by a quantifier. *)
+and quantifiers = logic_var list
+
+(** comparison relations*)
+and relation =
+ | Rlt
+ | Rgt
+ | Rle
+ | Rge
+ | Req
+ | Rneq (** @plugin development guide *)
+
+
+(** predicates *)
+and predicate_node =
+ | Pfalse (** always-false predicate. *)
+ | Ptrue (** always-true predicate. *)
+ | Papp of logic_info * (logic_label * logic_label) list * term list
+ (** application of a predicate. *)
+ | Pseparated of term list
+ | Prel of relation * term * term (** comparison of two terms. *)
+ | Pand of predicate * predicate (** conjunction *)
+ | Por of predicate * predicate (** disjunction. *)
+ | Pxor of predicate * predicate (** logical xor. *)
+ | Pimplies of predicate * predicate (** implication. *)
+ | Piff of predicate * predicate (** equivalence. *)
+ | Pnot of predicate (** negation. *)
+ | Pif of term * predicate * predicate (** conditional *)
+ | Plet of logic_info * predicate (** definition of a local variable *)
+ | Pforall of quantifiers * predicate (** universal quantification. *)
+ | Pexists of quantifiers * predicate (** existential quantification. *)
+ | Pat of predicate * logic_label
+ (** predicate refers to a particular program point. *)
+ | Pvalid_read of logic_label * term (** the given locations are valid for reading. *)
+ | Pvalid of logic_label * term (** the given locations are valid. *)
+ | Pvalid_function of term
+ (** the pointed function has a type compatible with the one of pointer. *)
+ | Pinitialized of logic_label * term (** the given locations are initialized. *)
+ | Pdangling of logic_label * term (** the given locations contain dangling
+ adresses. *)
+ | Pallocable of logic_label * term (** the given locations can be allocated. *)
+ | Pfreeable of logic_label * term (** the given locations can be free. *)
+ | Pfresh of logic_label * logic_label * term * term
+ (** \fresh(pointer, n)
+ A memory block of n bytes is newly allocated to the pointer.*)
+ | Psubtype of term * term
+ (** First term is a type tag that is a subtype of the second. *)
+
+(** predicate with an unique identifier. Use [Logic_const.new_predicate] to
+ create fresh predicates *)
+and identified_predicate = {
+ ip_id: int; (** identifier *)
+ ip_content: predicate; (** the predicate itself*)
+}
+
+(** predicates with a location and an optional list of names *)
+and predicate = {
+ pred_name : string list; (** list of given names *)
+ pred_loc : location; (** position in the source code. *)
+ pred_content : predicate_node;(** content *)
+}
+
+(* Polymorphic types shared with parsed trees (Logic_ptree) *)
+(** variant of a loop or a recursive function. Type shared with Logic_ptree. *)
+and 'term variant = 'term * string option
+
+(** allocates and frees.
+ @since Oxygen-20120901 *)
+and 'locs allocation =
+ | FreeAlloc of 'locs list * 'locs list (** tsets. Empty list means \nothing. *)
+ | FreeAllocAny (** Nothing specified. Semantics depends on where it
+ is written. *)
+
+(** dependencies of an assigned location. Shared with Logic_ptree. *)
+and 'locs deps =
+ | From of 'locs list (** tsets. Empty list means \nothing. *)
+ | FromAny (** Nothing specified. Any location can be involved. *)
+
+and 'locs from = ('locs * 'locs deps)
+
+(** zone assigned with its dependencies. Type shared with Logic_ptree. *)
+and 'locs assigns =
+ | WritesAny (** Nothing specified. Anything can be written. *)
+ | Writes of 'locs from list
+ (** list of locations that can be written. Empty list means \nothing. *)
+
+(** Function or statement contract. This type shares the name of its
+ constructors with {!Logic_ptree.spec}. *)
+and spec = {
+ mutable spec_behavior : behavior list;
+ (** behaviors *)
+
+ mutable spec_variant : term variant option;
+ (** variant for recursive functions. *)
+
+ mutable spec_terminates: identified_predicate option;
+ (** termination condition. *)
+
+ mutable spec_complete_behaviors: string list list;
+ (** list of complete behaviors.
+ It is possible to have more than one set of complete behaviors *)
+
+ mutable spec_disjoint_behaviors: string list list;
+ (** list of disjoint behaviors.
+ It is possible to have more than one set of disjoint behaviors *)
+}
+
+
+(** extension to standard ACSL clause.
+ Each extension is associated to a keyword. An extension
+ can be registered through the following functions:
+ - {!Logic_typing.register_behavior_extension} for parsing and type-checking
+ - {!Cil_printer.register_behavior_extension} for pretty-printing an
+ extended clause
+ - {!Cil.register_behavior_extension} for visiting an extended clause
+
+ @plugin development guide *)
+and acsl_extension = string * acsl_extension_kind
+
+and acsl_extension_kind =
+ | Ext_id of int (** id used internally by the extension itself. *)
+ | Ext_terms of term list
+ | Ext_preds of predicate list
+ (** a list of predicates, the most common case of for extensions *)
+
+(** Behavior of a function or statement. This type shares the name of its
+ constructors with {!Logic_ptree.behavior}.
+ @since Oxygen-20120901 [b_allocation] has been added.
+ @since Carbon-20101201 [b_requires] has been added.
+ @modify Boron-20100401 [b_ensures] is replaced by [b_post_cond].
+ Old [b_ensures] represent the [Normal] case of [b_post_cond]. *)
+and behavior = {
+ mutable b_name : string; (** name of the behavior. *)
+ mutable b_requires : identified_predicate list; (** require clauses. *)
+ mutable b_assumes : identified_predicate list; (** assume clauses. *)
+ mutable b_post_cond : (termination_kind * identified_predicate) list
+ (** post-condition. *);
+ mutable b_assigns : identified_term assigns; (** assignments. *)
+ mutable b_allocation : identified_term allocation; (** frees, allocates. *)
+ mutable b_extended : acsl_extension list (** extensions *)
+}
+
+(** kind of termination a post-condition applies to. See ACSL manual. *)
+and termination_kind = Normal | Exits | Breaks | Continues | Returns
+
+(** Pragmas for the value analysis plugin of Frama-C.
+ Type shared with Logic_ptree.*)
+and 'term loop_pragma =
+ | Unroll_specs of 'term list
+ | Widen_hints of 'term list
+ | Widen_variables of 'term list
+
+(** Pragmas for the slicing plugin of Frama-C. Type shared with Logic_ptree.*)
+and 'term slice_pragma =
+ | SPexpr of 'term
+ | SPctrl
+ | SPstmt
+
+(** Pragmas for the impact plugin of Frama-C. Type shared with Logic_ptree.*)
+and 'term impact_pragma =
+ | IPexpr of 'term
+ | IPstmt
+
+(** The various kinds of pragmas. Type shared with Logic_ptree. *)
+and 'term pragma =
+ | Loop_pragma of 'term loop_pragma
+ | Slice_pragma of 'term slice_pragma
+ | Impact_pragma of 'term impact_pragma
+
+(** all annotations that can be found in the code.
+ This type shares the name of its constructors with
+ {!Logic_ptree.code_annot}. *)
+and code_annotation_node =
+ | AAssert of string list * predicate
+ (** assertion to be checked. The list of strings is the list of
+ behaviors to which this assertion applies. *)
+
+ | AStmtSpec of string list * spec
+ (** statement contract
+ (potentially restricted to some enclosing behaviors). *)
+
+ | AInvariant of string list * bool * predicate
+ (** loop/code invariant. The list of strings is the list of behaviors to which
+ this invariant applies. The boolean flag is true for normal loop
+ invariants and false for invariant-as-assertions. *)
+
+ | AVariant of term variant
+ (** loop variant. Note that there can be at most one variant associated to a
+ given statement *)
+
+ | AAssigns of string list * identified_term assigns
+ (** loop assigns. (see [b_assigns] in the behaviors for other assigns). At
+ most one clause associated to a given (statement, behavior) couple. *)
+
+ | AAllocation of string list * identified_term allocation
+ (** loop allocation clause. (see [b_allocation] in the behaviors for other
+ allocation clauses).
+ At most one clause associated to a given (statement, behavior) couple.
+ @since Oxygen-20120901 when [b_allocation] has been added. *)
+
+ | APragma of term pragma (** pragma. *)
+ | AExtended of string list * acsl_extension
+ (** extension in a loop annotation.
+ @since Silicon-20161101 *)
+
+(** function contract. *)
+
+and funspec = spec
+
+(** code annotation with an unique identifier.
+ Use [Logic_const.new_code_annotation] to create new code annotations with
+ a fresh id. *)
+and code_annotation = {
+ annot_id: int; (** identifier. *)
+ annot_content : code_annotation_node; (** content of the annotation. *)
+}
+
+(** behavior of a function. *)
+and funbehavior = behavior
+
+(** global annotations, not attached to a statement or a function. *)
+and global_annotation =
+ | Dfun_or_pred of logic_info * location
+ | Dvolatile of
+ identified_term list * varinfo option * varinfo option * location
+ (** associated terms, reading function, writing function *)
+ | Daxiomatic of string * global_annotation list * location
+ | Dtype of logic_type_info * location (** declaration of a logic type. *)
+ | Dlemma of
+ string * bool * logic_label list * string list *
+ predicate * location
+ (** definition of a lemma. The boolean flag is [true] if the property should
+ be taken as an axiom and [false] if it must be proved. *)
+ | Dinvariant of logic_info * location
+ (** global invariant. The predicate does not have any argument. *)
+ | Dtype_annot of logic_info * location
+ (** type invariant. The predicate has exactly one argument. *)
+ | Dmodel_annot of model_info * location
+ (** Model field for a type t, seen as a logic function with one
+ argument of type t *)
+ | Dcustom_annot of custom_tree * string* location
+ (*Custom declaration*)
+
+and custom_tree = CustomDummy
+(*
+ | CustomType of logic_type
+ | CustomLexpr of lexpr
+ | CustomOther of string * (custom_tree list)
+*)
+
+type kinstr =
+ | Kstmt of stmt
+ | Kglobal
+
+(** Internal representation of decorated C functions *)
+type cil_function =
+ | Definition of (fundec * location) (** defined function *)
+ | Declaration of (funspec * varinfo * varinfo list option * location)
+ (** Declaration(spec,f,args,loc) represents a leaf function [f] with
+ specification [spec] and arguments [args], at location [loc]. As
+ with the [TFun] constructor of {!Cil_types.typ}, the arg list is
+ optional, to distinguish [void f()] ([None]) from
+ [void f(void)] ([Some []]). *)
+
+(** Only field [fundec] can be used directly. Use {!Annotations.funspec},
+ [Annotations.add_*] and [Annotations.remove_*] to query or modify field
+ [spec]. *)
+type kernel_function = {
+ mutable fundec : cil_function;
+ mutable spec : funspec;
+}
+
+(* [VP] TODO: VLocal should be attached to a particular block, not a whole
+ function. *)
+type localisation =
+ | VGlobal
+ | VLocal of kernel_function
+ | VFormal of kernel_function
+
+type mach = {
+ sizeof_short: int; (* Size of "short" *)
+ sizeof_int: int; (* Size of "int" *)
+ sizeof_long: int ; (* Size of "long" *)
+ sizeof_longlong: int; (* Size of "long long" *)
+ sizeof_ptr: int; (* Size of pointers *)
+ sizeof_float: int; (* Size of "float" *)
+ sizeof_double: int; (* Size of "double" *)
+ sizeof_longdouble: int; (* Size of "long double" *)
+ sizeof_void: int; (* Size of "void" *)
+ sizeof_fun: int; (* Size of function *)
+ size_t: string; (* Type of "sizeof(T)" *)
+ wchar_t: string; (* Type of "wchar_t" *)
+ ptrdiff_t: string; (* Type of "ptrdiff_t" *)
+ alignof_short: int; (* Alignment of "short" *)
+ alignof_int: int; (* Alignment of "int" *)
+ alignof_long: int; (* Alignment of "long" *)
+ alignof_longlong: int; (* Alignment of "long long" *)
+ alignof_ptr: int; (* Alignment of pointers *)
+ alignof_float: int; (* Alignment of "float" *)
+ alignof_double: int; (* Alignment of "double" *)
+ alignof_longdouble: int; (* Alignment of "long double" *)
+ alignof_str: int; (* Alignment of strings *)
+ alignof_fun: int; (* Alignment of function *)
+ char_is_unsigned: bool; (* Whether "char" is unsigned *)
+ underscore_name: bool; (* If assembly names have leading underscore *)
+ const_string_literals: bool; (* Whether string literals have const chars *)
+ little_endian: bool; (* whether the machine is little endian *)
+ alignof_aligned: int (* Alignment of a type with aligned attribute *);
+ has__builtin_va_list: bool (* Whether [__builtin_va_list] is a known type *);
+ __thread_is_keyword: bool (* Whether [__thread] is a keyword *);
+ compiler: string; (* Compiler being used. Currently recognized names
+ are 'gcc', 'msvc' and 'generic'. *)
+ version: string; (* Information on this machdep *)
+}
+
+(*
+Local Variables:
+compile-command: "make -C ../../.."
+End:
+*)
diff --git a/test/cil_types_polymorphic.ml b/test/cil_types_polymorphic.ml
new file mode 100644
index 0000000..514ba4c
--- /dev/null
+++ b/test/cil_types_polymorphic.ml
@@ -0,0 +1,1780 @@
+module Integer = struct type t = int end (* fpottier/visitors *)
+(****************************************************************************)
+(* *)
+(* Copyright (C) 2001-2003 *)
+(* George C. Necula <necula@cs.berkeley.edu> *)
+(* Scott McPeak <smcpeak@cs.berkeley.edu> *)
+(* Wes Weimer <weimer@cs.berkeley.edu> *)
+(* Ben Liblit <liblit@cs.berkeley.edu> *)
+(* All rights reserved. *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in the *)
+(* documentation and/or other materials provided with the distribution. *)
+(* *)
+(* 3. The names of the contributors may not be used to endorse or *)
+(* promote products derived from this software without specific prior *)
+(* written permission. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *)
+(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *)
+(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *)
+(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *)
+(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *)
+(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *)
+(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *)
+(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *)
+(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *)
+(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *)
+(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *)
+(* POSSIBILITY OF SUCH DAMAGE. *)
+(* *)
+(* File modified by CEA (Commissariat à l'énergie atomique et aux *)
+(* énergies alternatives) *)
+(* and INRIA (Institut National de Recherche en Informatique *)
+(* et Automatique). *)
+(****************************************************************************)
+
+(** The Abstract Syntax of CIL.
+ @plugin development guide *)
+
+(**************************** WARNING ***************************************)
+(* Remember to reflect any change here into the visitor and pretty-printer *)
+(* in cil.ml. In particular, if a type becomes mutable, it is necessary to *)
+(* adapt the Cil.behavior type and the copy_behavior accordingly. *)
+(* A first test to see if something has been broken by a change is to launch*)
+(* ptests.byte -add-options '-files-debug "-check -copy"' *)
+(* In addition, it is a good idea to add some invariant checks in the *)
+(* check_file class in frama-c/src/file.ml (before lauching the tests) *)
+(****************************************************************************)
+
+(* ************************************************************************* *)
+(** {2 Root of the AST} *)
+(* ************************************************************************* *)
+
+(** In Frama-C, the whole AST is accessible through {!Ast.get}. *)
+
+(** The top-level representation of a CIL source file (and the result of the
+ parsing and elaboration). Its main contents is the list of global
+ declarations and definitions. You can iterate over the globals in a
+ {!Cil_types.file} using the following iterators: {!Cil.mapGlobals},
+ {!Cil.iterGlobals} and {!Cil.foldGlobals}. You can also use the
+ {!Cil.dummyFile} when you need a {!Cil_types.file} as a placeholder. For
+ each global item CIL stores the source location where it appears (using the
+ type {!Cil_types.location})
+ @plugin development guide *)
+type file = {
+ mutable fileName: string; (** The complete file name *)
+
+ mutable globals: global list;
+ (** List of globals as they will appear in the printed file *)
+
+ mutable globinit: fundec option;
+ (** An optional global initializer function. This is a function where you
+ can put stuff that must be executed before the program is
+ started. This function, is conceptually at the end of the file,
+ although it is not part of the globals list. Use {!Cil.getGlobInit} to
+ create/get one. *)
+
+ mutable globinitcalled: bool;
+(** Whether the global initialization function is called in main. This
+ should always be false if there is no global initializer. When you
+ create a global initialization CIL will try to insert code in main to
+ call it. *)
+}
+
+(** The main type for representing global declarations and definitions. A list
+ of these form a CIL file. The order of globals in the file is generally
+ important.
+ @plugin development guide *)
+and global =
+ | GType of typeinfo * location
+ (** A typedef. All uses of type names (through the [TNamed] constructor)
+ must be preceeded in the file by a definition of the name. The string
+ is the defined name and always not-empty. *)
+
+ | GCompTag of compinfo * location
+ (** Defines a struct/union tag with some fields. There must be one of
+ these for each struct/union tag that you use (through the [TComp]
+ constructor) since this is the only context in which the fields are
+ printed. Consequently nested structure tag definitions must be
+ broken into individual definitions with the innermost structure
+ defined first. *)
+
+ | GCompTagDecl of compinfo * location
+ (** Declares a struct/union tag. Use as a forward declaration. This is
+ printed without the fields. *)
+
+ | GEnumTag of enuminfo * location
+ (** Declares an enumeration tag with some fields. There must be one of
+ these for each enumeration tag that you use (through the [TEnum]
+ constructor) since this is the only context in which the items are
+ printed. *)
+
+ | GEnumTagDecl of enuminfo * location
+ (** Declares an enumeration tag. Use as a forward declaration. This is
+ printed without the items. *)
+
+ | GVarDecl of varinfo * location
+ (** A variable declaration (not a definition) for a variable with object
+ type. There can be several declarations and at most one definition for
+ a given variable. If both forms appear then they must share the same
+ varinfo structure. Either has storage Extern or there must be a
+ definition in this file *)
+
+ | GFunDecl of funspec * varinfo * location
+ (** A variable declaration (not a definition) for a function, i.e. a
+ prototype. There can be several declarations and at most one definition
+ for a given function. If both forms appear then they must share the same
+ varinfo structure. A prototype shares the varinfo with the fundec of the
+ definition. Either has storage Extern or there must be a definition in
+ this file. *)
+
+ | GVar of varinfo * initinfo * location
+ (** A variable definition. Can have an initializer. The initializer is
+ updateable so that you can change it without requiring to recreate the
+ list of globals. There can be at most one definition for a variable in an
+ entire program. Cannot have storage Extern or function type. *)
+
+ | GFun of fundec * location
+ (** A function definition. *)
+
+ | GAsm of string * location
+ (** Global asm statement. These ones can contain only a template *)
+
+ | GPragma of attribute * location
+ (** Pragmas at top level. Use the same syntax as attributes *)
+
+ | GText of string
+ (** Some text (printed verbatim) at top level. E.g., this way you can put
+ comments in the output. *)
+
+ | GAnnot of global_annotation * location
+(** a global annotation. Can be
+ - an axiom or a lemma
+ - a predicate declaration or definition
+ - a global type invariant
+ - a global invariant
+ - a logic function declaration or definition. *)
+
+(* ************************************************************************* *)
+(** {2 Types} *)
+(* ************************************************************************* *)
+
+(** A C type is represented in CIL using the type {!Cil_types.typ}. Among types
+ we differentiate the integral types (with different kinds denoting the sign
+ and precision), floating point types, enumeration types, array and pointer
+ types, and function types. Every type is associated with a list of
+ attributes, which are always kept in sorted order. Use {!Cil.addAttribute}
+ and {!Cil.addAttributes} to construct list of attributes. If you want to
+ inspect a type, you should use {!Cil.unrollType} or {!Cil.unrollTypeDeep} to
+ see through the uses of named types.
+
+ CIL is configured at build-time with the sizes and alignments of the
+ underlying compiler (GCC or MSVC). CIL contains functions that can compute
+ the size of a type (in bits) {!Cil.bitsSizeOf}, the alignment of a type (in
+ bytes) {!Cil.alignOf_int}, and can convert an offset into a start and width
+ (both in bits) using the function {!Cil.bitsOffset}. At the moment these
+ functions do not take into account the [packed] attributes and pragmas. *)
+
+and typ =
+ | TVoid of attributes (** Void type. Also predefined as {!Cil.voidType} *)
+
+ | TInt of ikind * attributes
+ (** An integer type. The kind specifies the sign and width. Several useful
+ variants are predefined as {!Cil.intType}, {!Cil.uintType},
+ {!Cil.longType}, {!Cil.charType}. *)
+
+ | TFloat of fkind * attributes
+ (** A floating-point type. The kind specifies the precision. You can also use
+ the predefined constant {!Cil.doubleType}. *)
+
+ | TPtr of typ * attributes
+ (** Pointer type. Several useful variants are predefined as
+ {!Cil.charPtrType}, {!Cil.charConstPtrType} (pointer to a constant
+ character), {!Cil.voidPtrType}, {!Cil.intPtrType} *)
+
+ | TArray of typ * exp option * bitsSizeofTypCache * attributes
+ (** Array type. It indicates the base type and the array length. *)
+
+ | TFun of typ * (string * typ * attributes) list option * bool * attributes
+ (** Function type. Indicates the type of the result, the name, type
+ and name attributes of the formal arguments ([None] if no arguments
+ were specified, as in a function whose definition or prototype we
+ have not seen; [Some \[\]] means void). Use {!Cil.argsToList} to
+ obtain a list of arguments. The boolean indicates if it is a
+ variable-argument function. If this is the type of a varinfo for
+ which we have a function declaration then the information for the
+ formals must match that in the function's sformals. Use
+ {!Cil.setFormals}, or {!Cil.setFunctionType}, or
+ {!Cil.makeFormalVar} for this purpose. *)
+
+ | TNamed of typeinfo * attributes
+ (** The use of a named type. All uses of the same type name must share the
+ typeinfo. Each such type name must be preceeded in the file by a [GType]
+ global. This is printed as just the type name. The actual referred type
+ is not printed here and is carried only to simplify processing. To see
+ through a sequence of named type references, use {!Cil.unrollType}. The
+ attributes are in addition to those given when the type name was
+ defined. *)
+
+ | TComp of compinfo * bitsSizeofTypCache * attributes
+ (** A reference to a struct or a union type. All references to the
+ same struct or union must share the same compinfo among them and
+ with a [GCompTag] global that preceeds all uses (except maybe
+ those that are pointers to the composite type). The attributes
+ given are those pertaining to this use of the type and are in
+ addition to the attributes that were given at the definition of
+ the type and which are stored in the compinfo. *)
+
+ | TEnum of enuminfo * attributes
+ (** A reference to an enumeration type. All such references must
+ share the enuminfo among them and with a [GEnumTag] global that
+ preceeds all uses. The attributes refer to this use of the
+ enumeration and are in addition to the attributes of the
+ enumeration itself, which are stored inside the enuminfo *)
+
+ | TBuiltin_va_list of attributes
+(** This is the same as the gcc's type with the same name *)
+
+(** Various kinds of integers *)
+and ikind =
+ IBool (** [_Bool] *)
+ | IChar (** [char] *)
+ | ISChar (** [signed char] *)
+ | IUChar (** [unsigned char] *)
+ | IInt (** [int] *)
+ | IUInt (** [unsigned int] *)
+ | IShort (** [short] *)
+ | IUShort (** [unsigned short] *)
+ | ILong (** [long] *)
+ | IULong (** [unsigned long] *)
+ | ILongLong (** [long long] (or [_int64] on Microsoft Visual C) *)
+ | IULongLong (** [unsigned long long] (or [unsigned _int64] on Microsoft
+ Visual C) *)
+
+(** Various kinds of floating-point numbers*)
+and fkind =
+ FFloat (** [float] *)
+ | FDouble (** [double] *)
+ | FLongDouble (** [long double] *)
+
+(** This is used to cache the computation of the size of types in bits. *)
+and bitsSizeofTyp =
+ | Not_Computed
+ | Computed of int
+ | Not_Computable of (string * typ) (** Explanation of the error *)
+
+and bitsSizeofTypCache = { mutable scache : bitsSizeofTyp}
+
+(* ************************************************************************* *)
+(** {2 Attributes} *)
+(* ************************************************************************* *)
+
+and attribute =
+ | Attr of string * attrparam list
+ (** An attribute has a name and some optional parameters. The name should not
+ start or end with underscore. When CIL parses attribute names it will
+ strip leading and ending underscores (to ensure that the multitude of GCC
+ attributes such as const, __const and __const__ all mean the same
+ thing.) *)
+
+ | AttrAnnot of string
+
+(** Attributes are lists sorted by the attribute name. Use the functions
+ {!Cil.addAttribute} and {!Cil.addAttributes} to insert attributes in an
+ attribute list and maintain the sortedness. *)
+and attributes = attribute list
+
+(** The type of parameters of attributes *)
+and attrparam =
+ | AInt of (Integer.t[@opaque]) (** An integer constant *)
+ | AStr of string (** A string constant *)
+ | ACons of string * attrparam list
+ (** Constructed attributes. These are printed [foo(a1,a2,...,an)]. The list
+ of parameters can be empty and in that case the parentheses are not
+ printed. *)
+ | ASizeOf of typ (** A way to talk about types *)
+ | ASizeOfE of attrparam
+ | AAlignOf of typ
+ | AAlignOfE of attrparam
+ | AUnOp of unop * attrparam
+ | ABinOp of binop * attrparam * attrparam
+ | ADot of attrparam * string (** a.foo **)
+ | AStar of attrparam (** * a *)
+ | AAddrOf of attrparam (** & a **)
+ | AIndex of attrparam * attrparam (** a1[a2] *)
+ | AQuestion of attrparam * attrparam * attrparam (** a1 ? a2 : a3 **)
+
+(* ************************************************************************* *)
+(** {2 Structures} *)
+(* ************************************************************************* *)
+
+(** The {!Cil_types.compinfo} describes the definition of a structure or union
+ type. Each such {!Cil_types.compinfo} must be defined at the top-level using
+ the [GCompTag] constructor and must be shared by all references to this type
+ (using either the [TComp] type constructor or from the definition of the
+ fields.
+
+ If all you need is to scan the definition of each composite type once, you
+ can do that by scanning all top-level [GCompTag].
+
+ Constructing a {!Cil_types.compinfo} can be tricky since it must contain
+ fields that might refer to the host {!Cil_types.compinfo} and furthermore
+ the type of the field might need to refer to the {!Cil_types.compinfo} for
+ recursive types. Use the {!Cil.mkCompInfo} function to create a
+ {!Cil_types.compinfo}. You can easily fetch the {!Cil_types.fieldinfo} for a
+ given field in a structure with {!Cil.getCompField}. *)
+
+(** The definition of a structure or union type. Use {!Cil.mkCompInfo} to make
+ one and use {!Cil.copyCompInfo} to copy one (this ensures that a new key is
+ assigned and that the fields have the right pointers to parents.).
+ @plugin development guide *)
+and compinfo = {
+ mutable cstruct: bool;
+ (** [true] if struct, [false] if union *)
+
+ corig_name: string;
+ (** Original name as found in C file. Will never be changed *)
+
+ mutable cname: string;
+ (** The name. Always non-empty. Use {!Cil.compFullName} to get the full name
+ of a comp (along with the struct or union) *)
+
+ mutable ckey: int;
+ (** A unique integer. This is assigned by {!Cil.mkCompInfo} using a global
+ variable in the Cil module. Thus two identical structs in two different
+ files might have different keys. Use {!Cil.copyCompInfo} to copy
+ structures so that a new key is assigned. *)
+
+ mutable cfields: fieldinfo list;
+ (** Information about the fields. Notice that each fieldinfo has a pointer
+ back to the host compinfo. This means that you should not share
+ fieldinfo's between two compinfo's *)
+
+ mutable cattr: attributes;
+ (** The attributes that are defined at the same time as the composite
+ type. These attributes can be supplemented individually at each
+ reference to this [compinfo] using the [TComp] type constructor. *)
+
+ mutable cdefined: bool;
+ (** This boolean flag can be used to distinguish between structures
+ that have not been defined and those that have been defined but have
+ no fields (such things are allowed in gcc). *)
+
+ mutable creferenced: bool;
+(** [true] if used. Initially set to [false]. *)
+}
+
+(* ************************************************************************* *)
+(** {2 Structure fields} *)
+(* ************************************************************************* *)
+
+(** The {!Cil_types.fieldinfo} structure is used to describe a structure or
+ union field. Fields, just like variables, can have attributes associated
+ with the field itself or associated with the type of the field (stored along
+ with the type of the field). *)
+
+(** Information about a struct/union field.
+ @plugin development guide *)
+and fieldinfo = {
+ mutable fcomp: compinfo;
+ (** The host structure that contains this field. There can be only one
+ [compinfo] that contains the field. *)
+
+ forig_name: string;
+ (** original name as found in C file. *)
+
+ mutable fname: string;
+ (** The name of the field. Might be the value of {!Cil.missingFieldName} in
+ which case it must be a bitfield and is not printed and it does not
+ participate in initialization *)
+
+ mutable ftype: typ;
+ (** The type. If the field is a bitfield, a special attribute
+ [FRAMA_C_BITFIELD_SIZE] indicating the width of the bitfield is added. *)
+
+ mutable fbitfield: int option;
+ (** If a bitfield then ftype should be an integer type and the width of the
+ bitfield must be 0 or a positive integer smaller or equal to the width of
+ the integer type. A field of width 0 is used in C to control the alignment
+ of fields. *)
+
+ mutable fattr: attributes;
+ (** The attributes for this field (not for its type) *)
+
+ mutable floc: location;
+ (** The location where this field is defined *)
+
+ mutable faddrof: bool;
+ (** Adapted from CIL [vaddrof] field for variables. Only set for non-array
+ fields. Variable whose field address is taken is not marked anymore as
+ having its own address taken. True if the address of this field is
+ taken. CIL will set these flags when it parses C, but you should make
+ sure to set the flag whenever your transformation create [AddrOf]
+ expression. *)
+
+ mutable fsize_in_bits: int option;
+ (** (Deprecated. Use {!Cil.bitsOffset} instead.) Similar to [fbitfield] for
+ all types of fields.
+ @deprecated only Jessie uses this *)
+
+ mutable foffset_in_bits: int option;
+ (** Offset at which the field starts in the structure. Do not read directly,
+ but use {!Cil.bitsOffset} instead. *)
+
+ mutable fpadding_in_bits: int option;
+(** (Deprecated.) Store the size of the padding that follows the field, if any.
+ @deprecated only Jessie uses this *)
+}
+
+(* ************************************************************************* *)
+(** {2 Enumerations} *)
+(* ************************************************************************* *)
+
+(** Information about an enumeration. This is shared by all references to an
+ enumeration. Make sure you have a [GEnumTag] for each of these. *)
+
+(** Information about an enumeration.
+ @plugin development guide *)
+and enuminfo = {
+ eorig_name: string; (** original name as found in C file. *)
+
+ mutable ename: string; (** The name. Always non-empty. *)
+
+ mutable eitems: enumitem list; (** Items. The list must be non-empty *)
+
+ mutable eattr: attributes;
+ (** The attributes that are defined at the same time as the enumeration
+ type. These attributes can be supplemented individually at each
+ reference to this [enuminfo] using the [TEnum] type constructor. *)
+
+ mutable ereferenced: bool; (** [true] if used. Initially set to [false]. *)
+ mutable ekind: ikind (** The integer kind used to represent this enum. MSVC
+ always assumes IInt but this is not the case
+ for gcc. See ISO C 6.7.2.2 *)
+}
+
+and enumitem = {
+ eiorig_name: string; (** original name as found in C file. *)
+ mutable einame: string; (** the name, always non-empty. *)
+ mutable eival: exp; (** value of the item. Must be a compile-time constant *)
+ mutable eihost: enuminfo; (** the host enumeration in which the item is
+ declared. *)
+ eiloc: location;
+}
+
+(** Information about a defined type.
+ @plugin development guide *)
+and typeinfo = {
+ torig_name: string; (** original name as found in C file. *)
+
+ mutable tname: string;
+ (** The name. Can be empty only in a [GType] when introducing a composite or
+ enumeration tag. If empty cannot be refered to from the file *)
+
+ mutable ttype: typ;
+ (** The actual type. This includes the attributes that were present in the
+ typedef *)
+
+ mutable treferenced: bool; (** [true] if used. Initially set to [false]. *)
+}
+
+(* ************************************************************************* *)
+(** {2 Variables} *)
+(* ************************************************************************* *)
+
+(** Each local or global variable is represented by a unique
+ {!Cil_types.varinfo} structure. A global {!Cil_types.varinfo} can be
+ introduced with the [GVarDecl] or [GVar], [GFunDecl] or [GFun] globals.
+ A local varinfo can be introduced as part of a function definition
+ {!Cil_types.fundec}.
+
+ All references to a given global or local variable must refer to the same
+ copy of the [varinfo]. Each [varinfo] has a globally unique identifier that
+ can be used to index maps and hashtables (the name can also be used for this
+ purpose, except for locals from different functions). This identifier is
+ constructor using a global counter.
+
+ It is very important that you construct [varinfo] structures using only one
+ of the following functions:
+ - {!Cil.makeGlobalVar} : to make a global variable
+ - {!Cil.makeTempVar} : to make a temporary local variable whose name
+ will be generated so that to avoid conflict with other locals.
+ - {!Cil.makeLocalVar} : like {!Cil.makeTempVar} but you can specify the
+ exact name to be used.
+ - {!Cil.copyVarinfo}: make a shallow copy of a varinfo assigning a new name
+ and a new unique identifier
+
+ A [varinfo] is also used in a function type to denote the list of
+ formals. *)
+
+(** Information about a variable.
+ @plugin development guide *)
+and varinfo = {
+ mutable vname: string;
+ (** The name of the variable. Cannot be empty. It is primarily your
+ responsibility to ensure the uniqueness of a variable name. For local
+ variables {!Cil.makeTempVar} helps you ensure that the name is
+ unique. *)
+
+ vorig_name: string;
+ (** the original name of the variable. Need not be unique. *)
+
+ mutable vtype: typ;
+ (** The declared type of the variable. *)
+
+ mutable vattr: attributes;
+ (** A list of attributes associated with the variable.*)
+
+ mutable vstorage: storage;
+ (** The storage-class *)
+
+ mutable vglob: bool;
+ (** True if this is a global variable*)
+
+ mutable vdefined: bool;
+ (** True if the variable or function is defined in the file. Only relevant
+ for functions and global variables. Not used in particular for local
+ variables and logic variables. *)
+
+ mutable vformal: bool;
+ (** True if the variable is a formal parameter of a function. *)
+
+ mutable vinline: bool;
+ (** Whether this varinfo is for an inline function. *)
+
+ mutable vdecl: location;
+ (** Location of variable declaration. *)
+
+ mutable vid: int;
+ (** A unique integer identifier. This field will be set for you if you use
+ one of the {!Cil.makeFormalVar}, {!Cil.makeLocalVar},
+ {!Cil.makeTempVar}, {!Cil.makeGlobalVar}, or {!Cil.copyVarinfo}. *)
+
+ mutable vaddrof: bool;
+ (** [true] if the address of this variable is taken. CIL will set these
+ flags when it parses C, but you should make sure to set the flag
+ whenever your transformation create [AddrOf] expression. *)
+
+ mutable vreferenced: bool;
+ (** [true] if this variable is ever referenced. This is computed by
+ [removeUnusedVars]. It is safe to just initialize this to [false]. *)
+
+ vtemp: bool;
+ (** [true] for temporary variables generated by CIL normalization. [false]
+ for all the other variables. *)
+
+ mutable vdescr: string option;
+ (** For most temporary variables, a description of what the var holds.
+ (e.g. for temporaries used for function call results, this string is a
+ representation of the function call.) *)
+
+ mutable vdescrpure: bool;
+ (** Indicates whether the vdescr above is a pure expression or call. True
+ for all CIL expressions and Lvals, but false for e.g. function calls.
+ Printing a non-pure vdescr more than once may yield incorrect
+ results. *)
+
+ mutable vghost: bool;
+ (** Indicates if the variable is declared in ghost code *)
+
+ vsource: bool;
+ (** [true] iff this variable appears in the source of the program, which is
+ the case of all the variables in the initial AST. Plugins may create
+ variables with [vsource=false], for example to handle dynamic allocation.
+ Those variables do *not* have an associated {!GVar} or {!GVarDecl}. *)
+
+ mutable vlogic_var_assoc: logic_var option
+ (** Logic variable representing this variable in the logic world. Do not
+ access this field directly. Instead, call {!Cil.cvar_to_lvar}. *)
+}
+
+(** Storage-class information *)
+and storage =
+ NoStorage (** The default storage. Nothing is printed *)
+ | Static
+ | Register
+ | Extern
+
+(* ************************************************************************* *)
+(** {2 Expressions} *)
+(* ************************************************************************* *)
+
+(** The CIL expression language contains only the side-effect free expressions
+ of C. They are represented as the type {!Cil_types.exp}. There are several
+ interesting aspects of CIL expressions:
+
+ Integer and floating point constants can carry their textual representation.
+ This way the integer 15 can be printed as 0xF if that is how it occurred in
+ the source.
+
+ CIL uses arbitrary precision integers
+ to represent the integer constants and also stores the
+ width of the integer type. Care must be taken to ensure that the constant is
+ representable with the given width. Use the functions {!Cil.kinteger},
+ {!Cil.kinteger64} and {!Cil.integer} to construct constant expressions. CIL
+ predefines the constants {!Cil.zero}, {!Cil.one} and {!Cil.mone} (for -1).
+
+ Use the functions {!Cil.isConstant} and {!Cil.isInteger} to test if an
+ expression is a constant and a constant integer respectively.
+
+ CIL keeps the type of all unary and binary expressions. You can think of
+ that type qualifying the operator. Furthermore there are different operators
+ for arithmetic and comparisons on arithmetic types and on pointers.
+
+ Another unusual aspect of CIL is that the implicit conversion between an
+ expression of array type and one of pointer type is made explicit, using the
+ [StartOf] expression constructor (which is not printed). If you apply the
+ [AddrOf]constructor to an lvalue of type [T] then you will be getting an
+ expression of type [TPtr(T)].
+
+ You can find the type of an expression with {!Cil.typeOf}.
+
+ You can perform constant folding on expressions using the function
+ {!Cil.constFold}. *)
+
+(** Expressions (Side-effect free)*)
+and exp = {
+ eid: int; (** unique identifier *)
+ enode: exp_node; (** the expression itself *)
+ eloc: location; (** location of the expression. *)
+}
+
+and exp_node =
+ | Const of constant (** Constant *)
+ | Lval of lval (** Lvalue *)
+ | SizeOf of typ
+ (** sizeof(<type>). Has [unsigned int] type (ISO 6.5.3.4). This is not
+ turned into a constant because some transformations might want to change
+ types *)
+
+ | SizeOfE of exp (** sizeof(<expression>) *)
+
+ | SizeOfStr of string
+ (** sizeof(string_literal). We separate this case out because this is the
+ only instance in which a string literal should not be treated as having
+ type pointer to character. *)
+
+ | AlignOf of typ
+ (** This corresponds to the GCC __alignof_. Has [unsigned int] type *)
+
+ | AlignOfE of exp
+
+ | UnOp of unop * exp * typ
+ (** Unary operation. Includes the type of the result. *)
+
+ | BinOp of binop * exp * exp * typ
+ (** Binary operation. Includes the type of the result. The arithmetic
+ conversions are made explicit for the arguments.
+ @plugin development guide *)
+
+ | CastE of typ * exp
+ (** Use {!Cil.mkCast} to make casts. *)
+
+ | AddrOf of lval
+ (** Always use {!Cil.mkAddrOf} to construct one of these. Apply to an lvalue
+ of type [T] yields an expression of type [TPtr(T)] *)
+
+ | StartOf of lval
+ (** Conversion from an array to a pointer to the beginning of the array.
+ Given an lval of type [TArray(T)] produces an expression of type
+ [TPtr(T)]. In C this operation is implicit, the [StartOf] operator is not
+ printed. We have it in CIL because it makes the typing rules simpler. *)
+
+ | Info of exp * exp_info
+(** Additional information on the underlying expression *)
+
+(** Additional information on an expression *)
+and exp_info = {
+ exp_type : logic_type; (** when used as placeholder for a term *)
+ exp_name: string list;
+}
+
+(* ************************************************************************* *)
+(** {2 Constants} *)
+(* ************************************************************************* *)
+
+(** Literal constants *)
+and constant =
+ | CInt64 of (Integer.t[@opaque]) * ikind * string option
+ (** Integer constant. Give the ikind (see ISO9899 6.1.3.2) and the
+ textual representation. Textual representation is always set to Some s
+ when it comes from user code. This allows us to print a
+ constant as it was represented in the code, for example,
+ 0xF instead of 15. It is usually None for constant generated by Cil
+ itself. Use {!Cil.integer} or {!Cil.kinteger} to create these. *)
+
+ | CStr of string
+ (** String constant. The escape characters inside the string have been already
+ interpreted. This constant has pointer to character type! The only case
+ when you would like a string literal to have an array type is when it is
+ an argument to sizeof. In that case you should use SizeOfStr. *)
+
+ | CWStr of int64 list
+ (** Wide character string constant. Note that the local interpretation of such
+ a literal depends on {!Cil.theMachine.wcharType} and
+ {!Cil.theMachine.wcharKind}. Such a constant has type pointer to
+ {!Cil.theMachine.wcharType}. The escape characters in the string have not
+ been "interpreted" in the sense that L"A\xabcd" remains "A\xabcd" rather
+ than being represented as the wide character list with two elements: 65
+ and 43981. That "interpretation" depends on the underlying wide character
+ type. *)
+
+ | CChr of char
+ (** Character constant. This has type int, so use charConstToInt to read the
+ value in case sign-extension is needed. *)
+
+ | CReal of float * fkind * string option
+ (** Floating point constant. Give the fkind (see ISO 6.4.4.2) and also the
+ textual representation, if available. *)
+
+ | CEnum of enumitem
+(** An enumeration constant. Use [Cillower.lowerEnumVisitor] to replace these
+ with integer constants. *)
+
+(** Unary operators *)
+and unop =
+ Neg (** Unary minus *)
+ | BNot (** Bitwise complement (~) *)
+ | LNot (** Logical Not (!) *)
+
+(** Binary operations *)
+and binop =
+ PlusA (** arithmetic + *)
+ | PlusPI (** pointer + integer *)
+ | IndexPI (** pointer + integer but only when it arises from an expression
+ [e\[i\]] when [e] is a pointer and
+ not an array. This is semantically
+ the same as PlusPI but CCured uses
+ this as a hint that the integer is
+ probably positive. *)
+ | MinusA (** arithmetic - *)
+ | MinusPI (** pointer - integer *)
+ | MinusPP (** pointer - pointer *)
+ | Mult (** * *)
+ | Div (** /
+ @plugin development guide *)
+ | Mod (** %
+ @plugin development guide *)
+ | Shiftlt (** shift left *)
+ | Shiftrt (** shift right *)
+
+ | Lt (** < (arithmetic comparison) *)
+ | Gt (** > (arithmetic comparison) *)
+ | Le (** <= (arithmetic comparison) *)
+ | Ge (** >= (arithmetic comparison) *)
+ | Eq (** == (arithmetic comparison) *)
+ | Ne (** != (arithmetic comparison) *)
+ | BAnd (** bitwise and *)
+ | BXor (** exclusive-or *)
+ | BOr (** inclusive-or *)
+
+ | LAnd (** logical and. Unlike other expressions this one does not always
+ evaluate both operands. If you want
+ to use these, you must set
+ {!Cil.useLogicalOperators}. *)
+ | LOr (** logical or. Unlike other expressions this one does not always
+ evaluate both operands. If you
+ want to use these, you must set
+ {!Cil.useLogicalOperators}. *)
+
+(* ************************************************************************* *)
+(** {2 Left values} *)
+(* ************************************************************************* *)
+
+(** Left values (aka Lvalues) are the sublanguage of expressions that can appear
+ at the left of an assignment or as operand to the address-of operator. In C
+ the syntax for lvalues is not always a good indication of the meaning of the
+ lvalue. For example the C value {v a[0][1][2] v} might involve 1, 2 or 3
+ memory reads when used in an expression context, depending on the declared
+ type of the variable [a]. If [a] has type [int \[4\]\[4\]\[4\]] then we have
+ one memory read from somewhere inside the area that stores the array [a]. On
+ the other hand if [a] has type [int ***] then the expression really means [*
+ ( * ( * (a + 0) + 1) + 2)], in which case it is clear that it involves three
+ separate memory operations.
+
+ An lvalue denotes the contents of a range of memory addresses. This range is
+ denoted as a host object along with an offset within the object. The host
+ object can be of two kinds: a local or global variable, or an object whose
+ address is in a pointer expression. We distinguish the two cases so that we
+ can tell quickly whether we are accessing some component of a variable
+ directly or we are accessing a memory location through a pointer. To make
+ it easy to tell what an lvalue means CIL represents lvalues as a host object
+ and an offset (see {!Cil_types.lval}). The host object (represented as
+ {!Cil_types.lhost}) can be a local or global variable or can be the object
+ pointed-to by a pointer expression. The offset (represented as
+ {!Cil_types.offset}) is a sequence of field or array index designators.
+
+ Both the typing rules and the meaning of an lvalue is very precisely
+ specified in CIL.
+
+ The following are a few useful function for operating on lvalues:
+ - {!Cil.mkMem} - makes an lvalue of [Mem] kind. Use this to ensure
+ that certain equivalent forms of lvalues are canonized.
+ For example, [*&x = x].
+ - {!Cil.typeOfLval} - the type of an lvalue
+ - {!Cil.typeOffset} - the type of an offset, given the type of the
+ host.
+ - {!Cil.addOffset} and {!Cil.addOffsetLval} - extend sequences
+ of offsets.
+ - {!Cil.removeOffset} and {!Cil.removeOffsetLval} - shrink sequences
+ of offsets.
+
+ The following equivalences hold {v
+ Mem(AddrOf(Mem a, aoff)), off = Mem a, aoff + off
+ Mem(AddrOf(Var v, aoff)), off = Var v, aoff + off
+ AddrOf (Mem a, NoOffset) = a
+ v} *)
+
+and lval = lhost * offset
+
+(** The host part of an {!Cil_types.lval}. *)
+and lhost =
+ | Var of varinfo
+ (** The host is a variable. *)
+
+ | Mem of exp
+(** The host is an object of type [T] when the expression has pointer
+ [TPtr(T)]. *)
+
+
+(** The offset part of an {!Cil_types.lval}. Each offset can be applied to
+ certain kinds of lvalues and its effect is that it advances the starting
+ address of the lvalue and changes the denoted type, essentially focussing
+ to some smaller lvalue that is contained in the original one.
+ @plugin development guide *)
+and offset =
+ | NoOffset
+ (** No offset. Can be applied to any lvalue and does not change either the
+ starting address or the type. This is used when the lval consists of just
+ a host or as a terminator in a list of other kinds of offsets. *)
+
+ | Field of fieldinfo * offset
+ (** A field offset. Can be applied only to an lvalue that denotes a structure
+ or a union that contains the mentioned field. This advances the offset to
+ the beginning of the mentioned field and changes the type to the type of
+ the mentioned field. *)
+
+ | Index of exp * offset
+(** An array index offset. Can be applied only to an lvalue that denotes an
+ array. This advances the starting address of the lval to the beginning of
+ the mentioned array element and changes the denoted type to be the type of
+ the array element *)
+
+(* ************************************************************************* *)
+(** {2 Initializers} *)
+(* ************************************************************************* *)
+
+(** A special kind of expressions are those that can appear as initializers for
+ global variables (initialization of local variables is turned into
+ assignments). The initializers are represented as type
+ {!Cil_types.init}. You can create initializers with {!Cil.makeZeroInit} and
+ you can conveniently scan compound initializers them with
+ {!Cil.foldLeftCompound}. *)
+
+(** Initializers for global variables. *)
+and init =
+ | SingleInit of exp (** A single initializer *)
+ | CompoundInit of typ * (offset * init) list
+(** Used only for initializers of structures, unions and arrays. The offsets
+ are all of the form [Field(f, NoOffset)] or [Index(i, NoOffset)] and
+ specify the field or the index being initialized. For structures all fields
+ must have an initializer (except the unnamed bitfields), in the proper
+ order. This is necessary since the offsets are not printed. For arrays the
+ list must contain a prefix of the initializers; the rest are 0-initialized.
+ For unions there must be exactly one initializer. If the initializer is not
+ for the first field then a field designator is printed, so you better be on
+ GCC since MSVC does not understand this. You can scan an initializer list
+ with {!Cil.foldLeftCompound}. *)
+
+(** We want to be able to update an initializer in a global variable, so we
+ define it as a mutable field *)
+and initinfo = { mutable init : init option }
+
+(* ************************************************************************* *)
+(** {2 Function definitions} *)
+(* ************************************************************************* *)
+
+(** A function definition is always introduced with a [GFun] constructor at the
+ top level. All the information about the function is stored into a
+ {!Cil_types.fundec}. Some of the information (e.g. its name, type, storage,
+ attributes) is stored as a {!Cil_types.varinfo} that is a field of the
+ [fundec]. To refer to the function from the expression language you must use
+ the [varinfo].
+
+ The function definition contains, in addition to the body, a list of all the
+ local variables and separately a list of the formals. Both kind of variables
+ can be referred to in the body of the function. The formals must also be
+ shared with the formals that appear in the function type. For that reason,
+ to manipulate formals you should use the provided functions
+ {!Cil.makeFormalVar} and {!Cil.setFormals}. *)
+
+(** Function definitions.
+ @plugin development guide *)
+and fundec = {
+ mutable svar: varinfo;
+ (** Holds the name and type as a variable, so we can refer to it easily
+ from the program. All references to this function either in a function
+ call or in a prototype must point to the same [varinfo]. *)
+
+ mutable sformals: varinfo list;
+ (** Formals. These must be in the same order and with the same information
+ as the formal information in the type of the function. Use
+ {!Cil.setFormals} or {!Cil.setFunctionType} to set these formals and
+ ensure that they are reflected in the function type. Do not make
+ copies of these because the body refers to them. *)
+
+ mutable slocals: varinfo list;
+ (** Locals. Does NOT include the sformals. Do not make copies of these
+ because the body refers to them. *)
+
+ mutable smaxid: int;
+ (** Max local id. Starts at 0. Used for creating the names of new
+ temporary variables. Updated by {!Cil.makeLocalVar} and
+ {!Cil.makeTempVar}. You can also use {!Cil.setMaxId} to set it after
+ you have added the formals and locals. *)
+
+ mutable sbody: block; (** The function body. *)
+
+ mutable smaxstmtid: int option;
+ (** max id of a (reachable) statement in this function, if we have
+ computed it. range = 0 ... (smaxstmtid-1). This is computed by
+ {!Cfg.computeCFGInfo}. *)
+
+ mutable sallstmts: stmt list;
+ (** After you call {!Cfg.computeCFGInfo} this field is set to contain all
+ statements in the function. *)
+
+ mutable sspec: funspec;
+}
+
+(** A block is a sequence of statements with the control falling through from
+ one element to the next *)
+and block = {
+ mutable battrs: attributes; (** Attributes for the block *)
+
+ mutable blocals: varinfo list;
+ (** variables that are local to the block. It is a subset of the slocals of
+ the enclosing function. *)
+
+ mutable bstmts: stmt list; (** The statements comprising the block. *)
+}
+
+(* ************************************************************************* *)
+(** {2 Statements} *)
+(* ************************************************************************* *)
+
+(** CIL statements are the structural elements that make the CFG. They are
+ represented using the type {!Cil_types.stmt}. Every statement has a
+ (possibly empty) list of labels. The {!Cil_types.stmtkind} field of a
+ statement indicates what kind of statement it is.
+
+ Use {!Cil.mkStmt} to make a statement and the fill-in the fields.
+
+ CIL also comes with support for control-flow graphs. The [sid] field in
+ [stmt] can be used to give unique numbers to statements, and the [succs] and
+ [preds] fields can be used to maintain a list of successors and predecessors
+ for every statement. The CFG information is not computed by default. Instead
+ you must explicitly use the functions {!Cfg.prepareCFG} and
+ {!Cfg.computeCFGInfo} to do it. *)
+
+(** Statements.
+ @plugin development guide *)
+and stmt = {
+ mutable labels: label list;
+ (** Whether the statement starts with some labels, case statements or
+ default statements. *)
+
+ mutable skind: stmtkind;
+ (** The kind of statement *)
+
+ mutable sid: int;
+ (** A number (>= 0) that is unique in a function. Filled in only after the
+ CFG is computed. *)
+
+ mutable succs: stmt list;
+ (** The successor statements. They can always be computed from the skind and
+ the context in which this statement appears. Filled in only after the CFG
+ is computed. *)
+
+ mutable preds: stmt list;
+ (** The inverse of the succs function. *)
+
+ mutable ghost : bool
+}
+
+(** Labels *)
+and label =
+ | Label of string * location * bool
+ (** A real label. If the bool is "true", the label is from the input source
+ program. If the bool is "false", the label was created by CIL or some
+ other transformation *)
+
+ | Case of exp * location
+ (** A case statement. This expression is lowered into a constant if
+ {!Cil.lowerConstants} is set to [true]. *)
+
+ | Default of location (** A default statement *)
+
+(* The various kinds of statements *)
+and stmtkind =
+ | Instr of instr
+ (** An instruction that does not contain control flow. Control implicitly
+ falls through.
+ @plugin development guide *)
+
+ | Return of exp option * location
+ (** The return statement. This is a leaf in the CFG.
+ @plugin development guide *)
+
+ | Goto of stmt ref * location
+ (** A goto statement. Appears from actual goto's in the code or from goto's
+ that have been inserted during elaboration. The reference points to the
+ statement that is the target of the Goto. This means that you have to
+ update the reference whenever you replace the target statement. The
+ target statement MUST have at least a label.
+ @plugin development guide *)
+
+ | Break of location
+ (** A break to the end of the nearest enclosing Loop or Switch.
+ @plugin development guide *)
+
+ | Continue of location
+ (** A continue to the start of the nearest enclosing [Loop].
+ @plugin development guide *)
+
+ | If of exp * block * block * location
+ (** A conditional. Two successors, the "then" and the "else" branches (in
+ this order).
+ Both branches fall-through to the successor of the If statement.
+ @plugin development guide *)
+
+ | Switch of exp * block * (stmt list) * location
+ (** A switch statement. [exp] is the index of the switch. [block] is
+ the body of the switch. [stmt list] contains the set of
+ statements whose [labels] are cases of the switch (i.e. for each
+ case, the corresponding statement is in [stmt list], a statement
+ cannot appear more than once in the list, and statements in
+ [stmt list] can have several labels corresponding to several
+ cases.
+ @plugin development guide *)
+
+ | Loop of
+ code_annotation list * block * location * (stmt option) * (stmt option)
+ (** A [while(1)] loop. The termination test is implemented in the body of a
+ loop using a [Break] statement. If {!Cfg.prepareCFG} has been called, the
+ first stmt option will point to the stmt containing the continue label
+ for this loop and the second will point to the stmt containing the break
+ label for this loop.
+ @plugin development guide *)
+
+ | Block of block
+ (** Just a block of statements. Use it as a way to keep some block attributes
+ local.
+ @plugin development guide *)
+
+ | UnspecifiedSequence of (stmt * lval list
+ * lval list * lval list * stmt ref list) list
+ (** statements whose order of execution is not specified by
+ ISO/C. This is important for the order of side effects
+ during evaluation of expressions. Each statement comes
+ together with three list of lval, in this order.
+ - lvals that are written during the sequence and whose future
+ value depends upon the statement (it is legal to read from them, but
+ not to write to them)
+ - lvals that are written during the evaluation of the statement itself
+ - lval that are read.
+ - Function calls in the corresponding statement
+ Note that this include only a subset of the affectations
+ of the statement. Namely, the
+ temporary variables generated by cil are excluded (i.e. it
+ is assumed that the "compilation" is correct). In addition,
+ side effects caused by function applications are not taken
+ into account in the list. For a single statement, the written lvals
+ are supposed to be ordered (or their order of evaluation doesn't
+ matter), so that an alarm should be emitted only if the lvals read by
+ a statement overlap with the lvals written (or read) by another
+ statement of the sequence.
+
+ At this time this feature is
+ experimental and may miss some unspecified sequences.
+
+ In case you do not care about this feature just handle it
+ like a block (see {!Cil.block_from_unspecified_sequence}).
+ @plugin development guide *)
+
+ | Throw of (exp * typ) option * location
+ (** Throws an exception, C++ style.
+ We keep the type of the expression, to match
+ it against the appropriate catch clause. A Throw node has
+ no successor, even if it is in try-catch block that will catch
+ the exception: we keep normal and exceptional control-flow
+ completely separate, as in Jo and Chang, ICSSA 2004.
+ *)
+
+ | TryCatch of block * (catch_binder * block) list * location
+
+ | TryFinally of block * block * location
+ (** On MSVC we support structured exception handling. This is what you might
+ expect. Control can get into the finally block either from the end of the
+ body block, or if an exception is thrown.
+ @plugin development guide *)
+
+ | TryExcept of block * (instr list * exp) * block * location
+(** On MSVC we support structured exception handling. The try/except
+ statement is a bit tricky:
+ {v __try \{ blk \}
+ __except (e) \{
+ handler
+ \}
+ v}
+
+ The argument to __except must be an expression. However, we keep a
+ list of instructions AND an expression in case you need to make
+ function calls. We'll print those as a comma expression. The control
+ can get to the __except expression only if an exception is thrown.
+ After that, depending on the value of the expression the control
+ goes to the handler, propagates the exception, or retries the
+ exception. The location corresponds to the try keyword.
+ @plugin development guide *)
+
+(** Kind of exceptions that are caught by a given clause. *)
+and catch_binder =
+ | Catch_exn of varinfo * (varinfo * block) list
+ (** catch exception of given type(s).
+ If the list is empty, only exceptions with the same type as the
+ varinfo can be caught. If the list is non-empty, only exceptions
+ matching one of the type of a varinfo in the list are caught.
+ The associated block contains the operations necessary to transform
+ the matched varinfo into the principal one.
+ Semantics is by value (i.e. the varinfo is bound to a copy of the
+ caught object).
+
+ This clause is a declaration point for the varinfo(s)
+ mentioned in it. More precisely, for
+ [Catch_exn(v_0,[(v_1, b_1),..., (v_n, b_n)])],
+ the [v_i] must be referenced in the [slocals] of the
+ enclosing [fundec], and _must not_ appear in any [blocals]
+ of some block. The scope of v_0 is all the [b_i] and
+ the corresponding block in the [catch_binder * block list] of the
+ [TryCatch] node the binder belongs to. The scope of the other [v_i]
+ is the corresponding [b_i].
+ *)
+ | Catch_all (** default catch clause: all exceptions are caught. *)
+
+(** Instructions. They may cause effects directly but may not have control
+ flow.*)
+and instr =
+ | Set of lval * exp * location
+ (** An assignment. A cast is present if the exp has different type from
+ lval *)
+
+ | Call of lval option * exp * exp list * location
+ (** optional: result is an lval. A cast might be necessary if the declared
+ result type of the function is not the same as that of the destination.
+ Actual arguments must have a type equivalent (i.e. {!Cil.need_cast} must
+ return [false]) to the one of the formals of the function.
+ If the type of the result variable is not the same as the declared type of
+ the function result then an implicit cast exists.
+ *)
+
+ (* See the GCC specification for the meaning of ASM.
+ If the source is MS VC then only the templates
+ are used.
+
+ [sm] I've added a notes.txt file which contains more
+ information on interpreting Asm instructions *)
+ | Asm of
+ attributes (* Really only const and volatile can appear here *)
+ * string list (* templates (CR-separated) *)
+ * extended_asm option
+ * location
+ (** An inline assembly instruction. The arguments are
+ (1) a list of attributes (only const and volatile can appear here and only
+ for GCC)
+ (2) templates (CR-separated)
+ (3) GCC extended asm information if any
+ (4) location information *)
+
+ | Skip of location
+
+ | Code_annot of code_annotation * location
+
+
+(** GNU extended-asm information:
+ - a list of outputs, each of which is an lvalue with optional names and
+ constraints.
+ - a list of input expressions along with constraints
+ - clobbered registers
+ - Possible destinations statements *)
+and extended_asm =
+ {
+ asm_outputs: (string option * string * lval) list
+ (** outputs must be lvals with optional names and constraints. I would
+ like these to be actually variables, but I run into some trouble with
+ ASMs in the Linux sources *);
+ asm_inputs: (string option * string * exp) list
+ (** inputs with optional names and constraints *);
+ asm_clobbers: string list (** register clobbers *);
+ asm_gotos: (stmt ref) list
+ (** list of statements this asm section may jump to. Destination
+ must have a label. *);
+ }
+
+(** Describes a location in a source file *)
+and location = Lexing.position * Lexing.position [@opaque]
+
+(** {1 Abstract syntax trees for annotations} *)
+
+and logic_constant =
+ | Integer of (Integer.t[@opaque]) * string option
+ (** Integer constant with a textual representation. *)
+ | LStr of string (** String constant. *)
+ | LWStr of int64 list (** Wide character string constant. *)
+ | LChr of char (** Character constant. *)
+ | LReal of logic_real
+ | LEnum of enumitem (** An enumeration constant.*)
+
+(** Real constants. *)
+and logic_real = {
+ r_literal : string ; (** Initial string representation [s]. *)
+ r_nearest : float ; (** Nearest approximation of [s] in double precision. *)
+ r_upper : float ; (** Smallest double [u] such that [s <= u]. *)
+ r_lower : float ; (** Greatest double [l] such that [l <= s]. *)
+}
+
+(** Types of logic terms. *)
+and logic_type =
+ | Ctype of typ (** a C type *)
+ | Ltype of logic_type_info * logic_type list
+ (** an user-defined logic type with its parameters *)
+ | Lvar of string (** a type variable. *)
+ | Linteger (** mathematical integers, {i i.e.} Z *)
+ | Lreal (** mathematical reals, {i i.e.} R *)
+ | Larrow of logic_type list * logic_type (** (n-ary) function type *)
+
+(** tsets with an unique identifier.
+ Use [Logic_const.new_location] to generate a new id. *)
+and identified_term = {
+ it_id: int; (** the identifier. *)
+ it_content: term (** the term *)
+}
+
+(** logic label referring to a particular program point. *)
+and logic_label =
+ | StmtLabel of stmt ref (** label of a C statement. *)
+ | LogicLabel of (stmt option * string) (* [JS 2011/05/13] why a tuple here? *)
+(** builtin logic label ({t Here, Pre}, ...) *)
+
+(* ************************************************************************* *)
+(** {2 Terms} *)
+(* ************************************************************************* *)
+
+(** C Expressions as logic terms follow C constructs (with prefix T) *)
+
+(** Logic terms. *)
+and term = {
+ term_node : term_node; (** kind of term. *)
+ term_loc : Lexing.position * Lexing.position [@opaque];
+ (** position in the source file. *)
+ term_type : logic_type; (** type of the term. *)
+ term_name: string list;
+ (** names of the term if any. A name can be an arbitrary string, where
+ '"' and '\'' are escaped by a \, and which does not end with a \.
+ Hence, "name" and 'name' should be recognized as a unique label by most
+ tools. *)
+}
+
+(** the various kind of terms. *)
+and term_node =
+ (* same constructs as exp *)
+ | TConst of logic_constant (** a constant. *)
+ | TLval of term_lval (** an L-value *)
+ | TSizeOf of typ (** size of a given C type. *)
+ | TSizeOfE of term (** size of the type of an expression. *)
+ | TSizeOfStr of string (** size of a string constant. *)
+ | TAlignOf of typ (** alignment of a type. *)
+ | TAlignOfE of term (** alignment of the type of an expression. *)
+ | TUnOp of unop * term (** unary operator. *)
+ | TBinOp of binop * term * term (** binary operators. *)
+ | TCastE of typ * term (** cast to a C type. *)
+ | TAddrOf of term_lval (** address of a term. *)
+ | TStartOf of term_lval (** beginning of an array. *)
+
+ (* additional constructs *)
+ | Tapp of logic_info * (logic_label * logic_label) list * term list
+ (** application of a logic function. *)
+ | Tlambda of quantifiers * term (** lambda abstraction. *)
+ | TDataCons of logic_ctor_info * term list
+ (** constructor of logic sum-type. *)
+ | Tif of term * term * term
+ (** conditional operator*)
+ | Tat of term * logic_label
+ (** term refers to a particular program point. *)
+ | Tbase_addr of logic_label * term (** base address of a pointer. *)
+ | Toffset of logic_label * term (** offset from the base address of a pointer. *)
+ | Tblock_length of logic_label * term (** length of the block pointed to by the term. *)
+ | Tnull (** the null pointer. *)
+ | TLogic_coerce of logic_type * term
+ (** implicit conversion from a C type to a logic type.
+ The logic type must not be a Ctype. In particular, used to denote
+ lifting to Linteger and Lreal.
+ *)
+ | TCoerce of term * typ (** coercion to a given C type. *)
+ | TCoerceE of term * term (** coercion to the type of a given term. *)
+ | TUpdate of term * term_offset * term
+ (** functional update of a field. *)
+ | Ttypeof of term (** type tag for a term. *)
+ | Ttype of typ (** type tag for a C type. *)
+ | Tempty_set (** the empty set. *)
+ | Tunion of term list (** union of terms. *)
+ | Tinter of term list (** intersection of terms. *)
+ | Tcomprehension of
+ term * quantifiers * predicate option
+ (** set defined in comprehension ({t \{ t[i] | integer i; 0 <= i < 5\}}) *)
+ | Trange of term option * term option (** range of integers. *)
+ | Tlet of logic_info * term (** local binding *)
+
+(** lvalue: base address and offset. *)
+and term_lval =
+ term_lhost * term_offset
+
+(** base address of an lvalue. *)
+and term_lhost =
+ | TVar of logic_var (** a variable. *)
+ | TResult of typ (** value returned by a C function.
+ Only used in post-conditions or assigns
+ *)
+ | TMem of term (** memory access. *)
+
+(** model field. *)
+and model_info = {
+ mi_name: string; (** name *)
+ mi_field_type: logic_type; (** type of the field *)
+ mi_base_type: typ; (** type to which the field is associated. *)
+ mi_decl: location; (** where the field has been declared. *)
+}
+
+(** offset of an lvalue. *)
+and term_offset =
+ | TNoOffset (** no further offset. *)
+ | TField of fieldinfo * term_offset
+ (** access to the field of a compound type. *)
+ | TModel of model_info * term_offset (** access to a model field. *)
+ | TIndex of term * term_offset
+ (** index. Note that a range is denoted by [TIndex(Trange(i1,i2),ofs)] *)
+
+(** description of a logic function or predicate.
+@plugin development guide *)
+and logic_info = {
+(*
+ mutable l_name : string; (** name of the function. *)
+*)
+ mutable l_var_info : logic_var;
+ (** we use only fields lv_name and lv_id of l_var_info
+ we should factorize lv_type and l_type+l_profile below *)
+ mutable l_labels : logic_label list; (** label arguments of the function. *)
+ mutable l_tparams : string list; (** type parameters *)
+ mutable l_type : logic_type option; (** return type. None for predicates *)
+ mutable l_profile : logic_var list; (** type of the arguments. *)
+ mutable l_body : logic_body; (** body of the function. *)
+}
+
+and builtin_logic_info = {
+ mutable bl_name: string;
+ mutable bl_labels: logic_label list;
+ mutable bl_params: string list;
+ mutable bl_type: logic_type option;
+ mutable bl_profile: (string * logic_type) list;
+}
+
+and logic_body =
+ | LBnone (** no definition and no reads clause *)
+ | LBreads of identified_term list
+ (** read accesses performed by a function. *)
+ | LBterm of term (** direct definition of a function. *)
+ | LBpred of predicate (** direct definition of a predicate. *)
+ | LBinductive of
+ (string * logic_label list * string list * predicate) list
+ (** inductive definition *)
+
+(** Description of a logic type.
+ @plugin development guide *)
+and logic_type_info = {
+ lt_name: string;
+ lt_params : string list; (** type parameters*)
+ mutable lt_def: logic_type_def option
+ (** definition of the type. None for abstract types. *)
+}
+(* will be expanded when dealing with concrete types *)
+
+and logic_type_def =
+ | LTsum of logic_ctor_info list (** sum type with its constructors. *)
+ | LTsyn of logic_type (** Synonym of another type. *)
+
+(** origin of a logic variable. *)
+and logic_var_kind =
+ | LVGlobal (** global logic function or predicate. *)
+ | LVC (** Logic counterpart of a C variable. *)
+ | LVFormal (** formal parameter of a logic function / predicate
+ or \lambda abstraction *)
+ | LVQuant (** Bound by a quantifier (\exists or \forall) *)
+ | LVLocal (** local \let *)
+
+(** description of a logic variable
+@plugin development guide *)
+and logic_var = {
+ mutable lv_name : string; (** name of the variable. *)
+ mutable lv_id : int; (** unique identifier *)
+ mutable lv_type : logic_type; (** type of the variable. *)
+ mutable lv_kind: logic_var_kind; (** kind of the variable *)
+ mutable lv_origin : varinfo option
+(** when the logic variable stems from a C variable, set to the original C
+ variable. *)
+}
+
+(** Description of a constructor of a logic sum-type.
+ @plugin development guide *)
+and logic_ctor_info =
+ { ctor_name: string; (** name of the constructor. *)
+ ctor_type: logic_type_info; (** type to which the constructor belongs. *)
+ ctor_params: logic_type list
+ (** types of the parameters of the constructor. *)
+ }
+
+(* ************************************************************************* *)
+(** {2 Predicates} *)
+(* ************************************************************************* *)
+
+(** variables bound by a quantifier. *)
+and quantifiers = logic_var list
+
+(** comparison relations*)
+and relation =
+ | Rlt
+ | Rgt
+ | Rle
+ | Rge
+ | Req
+ | Rneq (** @plugin development guide *)
+
+
+(** predicates *)
+and predicate_node =
+ | Pfalse (** always-false predicate. *)
+ | Ptrue (** always-true predicate. *)
+ | Papp of logic_info * (logic_label * logic_label) list * term list
+ (** application of a predicate. *)
+ | Pseparated of term list
+ | Prel of relation * term * term (** comparison of two terms. *)
+ | Pand of predicate * predicate (** conjunction *)
+ | Por of predicate * predicate (** disjunction. *)
+ | Pxor of predicate * predicate (** logical xor. *)
+ | Pimplies of predicate * predicate (** implication. *)
+ | Piff of predicate * predicate (** equivalence. *)
+ | Pnot of predicate (** negation. *)
+ | Pif of term * predicate * predicate (** conditional *)
+ | Plet of logic_info * predicate (** definition of a local variable *)
+ | Pforall of quantifiers * predicate (** universal quantification. *)
+ | Pexists of quantifiers * predicate (** existential quantification. *)
+ | Pat of predicate * logic_label
+ (** predicate refers to a particular program point. *)
+ | Pvalid_read of logic_label * term (** the given locations are valid for reading. *)
+ | Pvalid of logic_label * term (** the given locations are valid. *)
+ | Pvalid_function of term
+ (** the pointed function has a type compatible with the one of pointer. *)
+ | Pinitialized of logic_label * term (** the given locations are initialized. *)
+ | Pdangling of logic_label * term (** the given locations contain dangling
+ adresses. *)
+ | Pallocable of logic_label * term (** the given locations can be allocated. *)
+ | Pfreeable of logic_label * term (** the given locations can be free. *)
+ | Pfresh of logic_label * logic_label * term * term
+ (** \fresh(pointer, n)
+ A memory block of n bytes is newly allocated to the pointer.*)
+ | Psubtype of term * term
+ (** First term is a type tag that is a subtype of the second. *)
+
+(** predicate with an unique identifier. Use [Logic_const.new_predicate] to
+ create fresh predicates *)
+and identified_predicate = {
+ ip_id: int; (** identifier *)
+ ip_content: predicate; (** the predicate itself*)
+}
+
+(** predicates with a location and an optional list of names *)
+and predicate = {
+ pred_name : string list; (** list of given names *)
+ pred_loc : location; (** position in the source code. *)
+ pred_content : predicate_node;(** content *)
+}
+
+(* Polymorphic types shared with parsed trees (Logic_ptree) *)
+(** variant of a loop or a recursive function. Type shared with Logic_ptree. *)
+and 'term variant = 'term * string option
+
+(** allocates and frees.
+ @since Oxygen-20120901 *)
+and 'locs allocation =
+ | FreeAlloc of 'locs list * 'locs list (** tsets. Empty list means \nothing. *)
+ | FreeAllocAny (** Nothing specified. Semantics depends on where it
+ is written. *)
+
+(** dependencies of an assigned location. Shared with Logic_ptree. *)
+and 'locs deps =
+ | From of 'locs list (** tsets. Empty list means \nothing. *)
+ | FromAny (** Nothing specified. Any location can be involved. *)
+
+and 'locs from = ('locs * 'locs deps)
+
+(** zone assigned with its dependencies. Type shared with Logic_ptree. *)
+and 'locs assigns =
+ | WritesAny (** Nothing specified. Anything can be written. *)
+ | Writes of 'locs from list
+ (** list of locations that can be written. Empty list means \nothing. *)
+
+(** Function or statement contract. This type shares the name of its
+ constructors with {!Logic_ptree.spec}. *)
+and spec = {
+ mutable spec_behavior : behavior list;
+ (** behaviors *)
+
+ mutable spec_variant : term variant option;
+ (** variant for recursive functions. *)
+
+ mutable spec_terminates: identified_predicate option;
+ (** termination condition. *)
+
+ mutable spec_complete_behaviors: string list list;
+ (** list of complete behaviors.
+ It is possible to have more than one set of complete behaviors *)
+
+ mutable spec_disjoint_behaviors: string list list;
+ (** list of disjoint behaviors.
+ It is possible to have more than one set of disjoint behaviors *)
+}
+
+
+(** extension to standard ACSL clause.
+ Each extension is associated to a keyword. An extension
+ can be registered through the following functions:
+ - {!Logic_typing.register_behavior_extension} for parsing and type-checking
+ - {!Cil_printer.register_behavior_extension} for pretty-printing an
+ extended clause
+ - {!Cil.register_behavior_extension} for visiting an extended clause
+
+ @plugin development guide *)
+and acsl_extension = string * acsl_extension_kind
+
+and acsl_extension_kind =
+ | Ext_id of int (** id used internally by the extension itself. *)
+ | Ext_terms of term list
+ | Ext_preds of predicate list
+ (** a list of predicates, the most common case of for extensions *)
+
+(** Behavior of a function or statement. This type shares the name of its
+ constructors with {!Logic_ptree.behavior}.
+ @since Oxygen-20120901 [b_allocation] has been added.
+ @since Carbon-20101201 [b_requires] has been added.
+ @modify Boron-20100401 [b_ensures] is replaced by [b_post_cond].
+ Old [b_ensures] represent the [Normal] case of [b_post_cond]. *)
+and behavior = {
+ mutable b_name : string; (** name of the behavior. *)
+ mutable b_requires : identified_predicate list; (** require clauses. *)
+ mutable b_assumes : identified_predicate list; (** assume clauses. *)
+ mutable b_post_cond : (termination_kind * identified_predicate) list
+ (** post-condition. *);
+ mutable b_assigns : identified_term assigns; (** assignments. *)
+ mutable b_allocation : identified_term allocation; (** frees, allocates. *)
+ mutable b_extended : acsl_extension list (** extensions *)
+}
+
+(** kind of termination a post-condition applies to. See ACSL manual. *)
+and termination_kind = Normal | Exits | Breaks | Continues | Returns
+
+(** Pragmas for the value analysis plugin of Frama-C.
+ Type shared with Logic_ptree.*)
+and 'term loop_pragma =
+ | Unroll_specs of 'term list
+ | Widen_hints of 'term list
+ | Widen_variables of 'term list
+
+(** Pragmas for the slicing plugin of Frama-C. Type shared with Logic_ptree.*)
+and 'term slice_pragma =
+ | SPexpr of 'term
+ | SPctrl
+ | SPstmt
+
+(** Pragmas for the impact plugin of Frama-C. Type shared with Logic_ptree.*)
+and 'term impact_pragma =
+ | IPexpr of 'term
+ | IPstmt
+
+(** The various kinds of pragmas. Type shared with Logic_ptree. *)
+and 'term pragma =
+ | Loop_pragma of 'term loop_pragma
+ | Slice_pragma of 'term slice_pragma
+ | Impact_pragma of 'term impact_pragma
+
+(** all annotations that can be found in the code.
+ This type shares the name of its constructors with
+ {!Logic_ptree.code_annot}. *)
+and code_annotation_node =
+ | AAssert of string list * predicate
+ (** assertion to be checked. The list of strings is the list of
+ behaviors to which this assertion applies. *)
+
+ | AStmtSpec of string list * spec
+ (** statement contract
+ (potentially restricted to some enclosing behaviors). *)
+
+ | AInvariant of string list * bool * predicate
+ (** loop/code invariant. The list of strings is the list of behaviors to which
+ this invariant applies. The boolean flag is true for normal loop
+ invariants and false for invariant-as-assertions. *)
+
+ | AVariant of term variant
+ (** loop variant. Note that there can be at most one variant associated to a
+ given statement *)
+
+ | AAssigns of string list * identified_term assigns
+ (** loop assigns. (see [b_assigns] in the behaviors for other assigns). At
+ most one clause associated to a given (statement, behavior) couple. *)
+
+ | AAllocation of string list * identified_term allocation
+ (** loop allocation clause. (see [b_allocation] in the behaviors for other
+ allocation clauses).
+ At most one clause associated to a given (statement, behavior) couple.
+ @since Oxygen-20120901 when [b_allocation] has been added. *)
+
+ | APragma of term pragma (** pragma. *)
+ | AExtended of string list * acsl_extension
+ (** extension in a loop annotation.
+ @since Silicon-20161101 *)
+
+(** function contract. *)
+
+and funspec = spec
+
+(** code annotation with an unique identifier.
+ Use [Logic_const.new_code_annotation] to create new code annotations with
+ a fresh id. *)
+and code_annotation = {
+ annot_id: int; (** identifier. *)
+ annot_content : code_annotation_node; (** content of the annotation. *)
+}
+
+(** behavior of a function. *)
+and funbehavior = behavior
+
+(** global annotations, not attached to a statement or a function. *)
+and global_annotation =
+ | Dfun_or_pred of logic_info * location
+ | Dvolatile of
+ identified_term list * varinfo option * varinfo option * location
+ (** associated terms, reading function, writing function *)
+ | Daxiomatic of string * global_annotation list * location
+ | Dtype of logic_type_info * location (** declaration of a logic type. *)
+ | Dlemma of
+ string * bool * logic_label list * string list *
+ predicate * location
+ (** definition of a lemma. The boolean flag is [true] if the property should
+ be taken as an axiom and [false] if it must be proved. *)
+ | Dinvariant of logic_info * location
+ (** global invariant. The predicate does not have any argument. *)
+ | Dtype_annot of logic_info * location
+ (** type invariant. The predicate has exactly one argument. *)
+ | Dmodel_annot of model_info * location
+ (** Model field for a type t, seen as a logic function with one
+ argument of type t *)
+ | Dcustom_annot of custom_tree * string* location
+ (*Custom declaration*)
+
+and custom_tree = CustomDummy
+(*
+ | CustomType of logic_type
+ | CustomLexpr of lexpr
+ | CustomOther of string * (custom_tree list)
+*)
+[@@deriving visitors { variety = "iter"; polymorphic = true; concrete = true },
+ visitors { variety = "map"; polymorphic = true; concrete = true },
+ visitors { variety = "endo"; polymorphic = true; concrete = true },
+ visitors { variety = "reduce"; polymorphic = true; concrete = true; ancestors = ["VisitorsRuntime.addition_monoid"] },
+ visitors { variety = "mapreduce"; polymorphic = true; concrete = true; ancestors = ["VisitorsRuntime.addition_monoid"] },
+ visitors { variety = "iter2"; polymorphic = true; concrete = true },
+ visitors { variety = "map2"; polymorphic = true; concrete = true },
+ visitors { variety = "reduce2"; polymorphic = true; concrete = true; ancestors = ["VisitorsRuntime.addition_monoid"] },
+ visitors { variety = "mapreduce2"; polymorphic = true; concrete = true; ancestors = ["VisitorsRuntime.addition_monoid"] }
+]
+
+type kinstr =
+ | Kstmt of stmt
+ | Kglobal
+
+(** Internal representation of decorated C functions *)
+type cil_function =
+ | Definition of (fundec * location) (** defined function *)
+ | Declaration of (funspec * varinfo * varinfo list option * location)
+ (** Declaration(spec,f,args,loc) represents a leaf function [f] with
+ specification [spec] and arguments [args], at location [loc]. As
+ with the [TFun] constructor of {!Cil_types.typ}, the arg list is
+ optional, to distinguish [void f()] ([None]) from
+ [void f(void)] ([Some []]). *)
+
+(** Only field [fundec] can be used directly. Use {!Annotations.funspec},
+ [Annotations.add_*] and [Annotations.remove_*] to query or modify field
+ [spec]. *)
+type kernel_function = {
+ mutable fundec : cil_function;
+ mutable spec : funspec;
+}
+
+(* [VP] TODO: VLocal should be attached to a particular block, not a whole
+ function. *)
+type localisation =
+ | VGlobal
+ | VLocal of kernel_function
+ | VFormal of kernel_function
+
+type mach = {
+ sizeof_short: int; (* Size of "short" *)
+ sizeof_int: int; (* Size of "int" *)
+ sizeof_long: int ; (* Size of "long" *)
+ sizeof_longlong: int; (* Size of "long long" *)
+ sizeof_ptr: int; (* Size of pointers *)
+ sizeof_float: int; (* Size of "float" *)
+ sizeof_double: int; (* Size of "double" *)
+ sizeof_longdouble: int; (* Size of "long double" *)
+ sizeof_void: int; (* Size of "void" *)
+ sizeof_fun: int; (* Size of function *)
+ size_t: string; (* Type of "sizeof(T)" *)
+ wchar_t: string; (* Type of "wchar_t" *)
+ ptrdiff_t: string; (* Type of "ptrdiff_t" *)
+ alignof_short: int; (* Alignment of "short" *)
+ alignof_int: int; (* Alignment of "int" *)
+ alignof_long: int; (* Alignment of "long" *)
+ alignof_longlong: int; (* Alignment of "long long" *)
+ alignof_ptr: int; (* Alignment of pointers *)
+ alignof_float: int; (* Alignment of "float" *)
+ alignof_double: int; (* Alignment of "double" *)
+ alignof_longdouble: int; (* Alignment of "long double" *)
+ alignof_str: int; (* Alignment of strings *)
+ alignof_fun: int; (* Alignment of function *)
+ char_is_unsigned: bool; (* Whether "char" is unsigned *)
+ underscore_name: bool; (* If assembly names have leading underscore *)
+ const_string_literals: bool; (* Whether string literals have const chars *)
+ little_endian: bool; (* whether the machine is little endian *)
+ alignof_aligned: int (* Alignment of a type with aligned attribute *);
+ has__builtin_va_list: bool (* Whether [__builtin_va_list] is a known type *);
+ __thread_is_keyword: bool (* Whether [__thread] is a keyword *);
+ compiler: string; (* Compiler being used. Currently recognized names
+ are 'gcc', 'msvc' and 'generic'. *)
+ version: string; (* Information on this machdep *)
+}
diff --git a/test/cloud.cppo.ml b/test/cloud.cppo.ml
new file mode 100644
index 0000000..d3ebc95
--- /dev/null
+++ b/test/cloud.cppo.ml
@@ -0,0 +1,22 @@
+class ['self] base = object (_ : 'self)
+ method visit_real _env x = x
+end
+
+type cloud =
+ | Point of (float[@name "real"]) * (float[@name "real"])
+ | Clouds of cloud list
+ [@@name "nuage"]
+ [@@deriving visitors { variety = "map"; ancestors = ["base"] }]
+
+#if OCAML_VERSION >= (4, 03, 0)
+
+module List = struct
+
+ type 'a mylist = 'a list =
+ | [] [@name "nil"]
+ | (::) of 'a * 'a mylist [@name "cons"]
+ [@@deriving visitors { variety = "map" }]
+
+end
+
+#endif
diff --git a/test/delayed_tree.ml b/test/delayed_tree.ml
new file mode 100644
index 0000000..3093e8f
--- /dev/null
+++ b/test/delayed_tree.ml
@@ -0,0 +1,435 @@
+(* To play with this code in an OCaml toplevel, launch [ocaml] and type this:
+ #use "topfind";;
+ #require "visitors.ppx";;
+ #require "visitors.runtime";;
+ *)
+
+(* -------------------------------------------------------------------------- *)
+
+(* Suppose we have an arbitrary data structure that contains elements
+ of type ['a]. Here, it is a binary tree, but it could be anything: *)
+
+type 'a sometree =
+ | Leaf
+ | Node of 'a sometree * 'a * 'a sometree
+
+(* This annotation is used only at the very end and can be ignored upon
+ first reading: *)
+
+[@@deriving visitors { variety = "reduce"; polymorphic = true;
+ name = "sometree_reduce" }]
+
+(* We would like to enumerate the elements of this data structure.
+ More precisely, we would like to construct an iterator, that is,
+ an on-demand producer of elements. Here is a simple definition
+ of a stateful iterator: *)
+
+type 'a iterator =
+ unit -> 'a option
+
+(* The question is, can we construct an iterator for the type ['a sometree],
+ based on an automatically-generated visitor, so that the construction is
+ entirely independent of the type ['a sometree]? *)
+
+(* -------------------------------------------------------------------------- *)
+
+(* For starters, let us define cascades, which are a more pleasant kind of
+ iterators. A cascade is a persistent (stateless) iterator. It can be
+ thought of as a delayed list, that is, a list whose elements are computed
+ only on demand. *)
+
+(* Cascades could (should) be part of a separate library. There is in fact a
+ proposal to add them to OCaml's standard library: see the discussion at
+ https://github.com/ocaml/ocaml/pull/1002 *)
+
+type 'a cascade =
+ unit -> 'a head
+
+and 'a head =
+ | Nil
+ | Cons of 'a * 'a cascade
+
+(* A delayed computation is represented as a function of type [unit -> _].
+ Thus, no memoization takes place. It is easy to implement a function
+ [memo: 'a cascade -> 'a cascade] that turns a nonmemoizing cascade into
+ a memoizing one, so memoization can be requested a posteriori, if
+ desired. *)
+
+(* The empty cascade. *)
+
+let nil : 'a cascade =
+ fun () -> Nil
+
+let cons (x : 'a) (xs : 'a cascade) : 'a cascade =
+ fun () -> Cons (x, xs)
+
+(* Forcing a cascade reveals its head. *)
+
+let force xs =
+ xs()
+
+(* A cascade can be easily converted to a stateful iterator. *)
+
+let cascade_to_iterator (xs : 'a cascade) : 'a iterator =
+ let s = ref xs in
+ fun () ->
+ match force !s with
+ | Nil ->
+ (* Writing [nil] into [s] may seem superfluous, but is in fact
+ necessary to guarantee that the computation that just led to
+ a [Nil] outcome is not repeated in the future. *)
+ s := nil;
+ None
+ | Cons (x, xs) ->
+ s := xs;
+ Some x
+
+(* Because cascades are close cousins of lists, they are easy to work with.
+ Constructing a cascade for a tree-like data structure is straightforward,
+ whereas directly constructing a stateful iterator would be more involved. *)
+
+(* -------------------------------------------------------------------------- *)
+
+(* Now, can we use some kind of visitor to turn a tree of type ['a sometree]
+ into a cascade of type ['a cascade]? *)
+
+(* At first sight, this does not seem very easy, for two reasons: 1- a visitor
+ usually traverses a tree in an eager manner, whereas we need the traversal
+ to make progress only as cascade elements are demanded; and 2- a visitor
+ performs a bottom-up computation, without a left-to-right bias (assuming
+ mutable state is not used), whereas a cascade enumerates elements in a
+ left-to-right manner. (Or in a right-to-left manner. As will be apparent
+ below, both directions are possible.) *)
+
+(* The trick is to use another intermediate step. Instead of turning a tree
+ directly into a cascade, we first transform it into a generic tree-like
+ structure: a *delayed tree*. Problem 1 is solved because, by introducing
+ delays into the new tree, we allow its construction to be carried out on
+ demand. Problem 2 is solved because this tree-to-tree transformation can be
+ carried out in a purely bottom-up manner by a [reduce] visitor. Then,
+ finally, it is straightforward to transform a delayed tree into a
+ cascade. *)
+
+(* -------------------------------------------------------------------------- *)
+
+(* A delayed tree contains ordinary nodes of arity 0, 1, and 2. Furthermore,
+ it contains [DTDelay] nodes, of arity 1, whose child is delayed, that is,
+ computed only on demand. *)
+
+type 'a delayed_tree =
+ | DTZero
+ | DTOne of 'a
+ | DTTwo of 'a delayed_tree * 'a delayed_tree
+ | DTDelay of (unit -> 'a delayed_tree)
+
+(* A delayed tree is converted to a cascade as follows. We may choose, at this
+ point, between left-to-right and right-to-left traversals. As usual, when
+ building a cascade, one must take a continuation [k] as an argument, so as
+ to avoid naive and costly cascade concatenation operations. *)
+
+let rec delayed_tree_to_cascade (dt : 'a delayed_tree) (k : 'a cascade)
+: 'a cascade =
+ fun () -> delayed_tree_to_head dt k
+
+and delayed_tree_to_head (dt : 'a delayed_tree) (k : 'a cascade) : 'a head =
+ match dt with
+ | DTZero ->
+ force k
+ | DTOne x ->
+ Cons (x, k)
+ | DTTwo (dt1, dt2) ->
+ delayed_tree_to_head dt1 (delayed_tree_to_cascade dt2 k)
+ | DTDelay dt ->
+ delayed_tree_to_head (force dt) k
+
+let delayed_tree_to_cascade (dt : 'a delayed_tree) : 'a cascade =
+ delayed_tree_to_cascade dt nil
+
+let delayed_tree_to_iterator (dt : 'a delayed_tree) : 'a iterator =
+ cascade_to_iterator (delayed_tree_to_cascade dt)
+
+(* -------------------------------------------------------------------------- *)
+
+(* We now set up four constructor functions and constructor methods, which
+ construct delayed trees, and which we will use in a [reduce] visitor. *)
+
+(* The type ['a delay] is a synonym for ['a]. It is used as a decoration, in a
+ type definition, to indicate that a call to the method [visit_delay] is
+ desired. *)
+
+type 'a delay = 'a
+
+class ['self] delayed_tree_monoid = object (_ : 'self)
+
+ (* Delayed trees form a monoid, in the sense that we concatenate them using
+ [DTTwo], and the neutral element is [DTZero]. We package these two data
+ constructors in the methods [zero] and [plus], which are automatically
+ called in an automatically-generated [reduce] visitor. *)
+
+ method zero =
+ DTZero
+
+ method plus s1 s2 =
+ match s1, s2 with
+ | DTZero, s
+ | s, DTZero ->
+ (* This optimization is not mandatory. It helps allocate fewer nodes. *)
+ s
+ | (DTOne _ | DTTwo _ | DTDelay _), _ ->
+ DTTwo (s1, s2)
+
+ (* The visitor method [visit_delay] delays the visit of a subtree by
+ constructing and returning a [DTDelay] node, which carries a delayed
+ recursive call to a visitor. *)
+
+ method visit_delay: 'env 'a .
+ ('env -> 'a -> 'b delayed_tree) ->
+ 'env -> 'a delay -> 'b delayed_tree
+ = fun visit_'a env x ->
+ DTDelay (fun () -> visit_'a env x)
+
+end
+
+(* The visitor function [yield] will be invoked at elements of type ['a].
+ It constructs a one-element delayed tree. *)
+
+let yield _env x =
+ DTOne x
+
+(* -------------------------------------------------------------------------- *)
+
+(* It is now time to generate a [reduce] visitor for the type ['a sometree].
+ This is the only part of the code which is specific of [sometree].
+ Everything else is generic. *)
+
+(* We must insert [delay]s into the structure of the type ['a sometree] so as
+ to indicate where [visit_delay] should be called and (therefore) where
+ [DTDelay] nodes should be allocated. To do this, we write a copy of the
+ definition of the type ['a sometree], with extra delays in it. The new type
+ is actually considered equal to ['a sometree] by OCaml. Its role is purely
+ to carry a [@@deriving visitors] annotation. *)
+
+(* In the data constructor [Node], the left-hand [delay] is in fact
+ superfluous. With or without it, our iterators will eagerly descend along
+ the leftmost branch of a tree, anyway. *)
+
+type 'a mytree = 'a sometree =
+ | Leaf
+ | Node of 'a mytree delay * 'a * 'a mytree delay
+
+and 'a mytree_delay =
+ 'a mytree delay
+
+[@@deriving visitors { variety = "reduce"; polymorphic = true;
+ concrete = true; ancestors = ["delayed_tree_monoid"] }]
+
+(* -------------------------------------------------------------------------- *)
+
+(* For demonstration purposes, let us make our visitor verbose. *)
+
+class ['self] verbose_reduce = object (_ : 'self)
+ inherit [_] reduce as super
+ method! visit_Leaf visit_'a env =
+ Printf.printf "Visiting a leaf.\n%!";
+ super#visit_Leaf visit_'a env
+ method! visit_Node visit_'a env t1 x t2 =
+ Printf.printf "Visiting a node.\n%!";
+ super#visit_Node visit_'a env t1 x t2
+end
+
+(* In production, one should remove [verbose_reduce] and use [reduce]
+ instead. *)
+
+let sometree_to_delayed_tree (t : 'a sometree) =
+ new verbose_reduce # visit_mytree_delay yield () t
+ (* We use [visit_mytree_delay], even though [visit_mytree] would work
+ just as well, so as to ensure that we get a delayed tree whose root
+ is a [DTDelay] node. *)
+
+(* Problem solved! *)
+
+let sometree_to_iterator (t : 'a sometree) : 'a iterator =
+ delayed_tree_to_iterator (sometree_to_delayed_tree t)
+
+(* -------------------------------------------------------------------------- *)
+
+(* Demo. *)
+
+let t : int sometree =
+ Node (Node (Leaf, 1, Leaf), 2, Node (Leaf, 3, Leaf))
+
+let i : int iterator =
+ sometree_to_iterator t
+
+(* Transcript of an OCaml toplevel session:
+
+ # i();;
+ Visiting a node.
+ Visiting a node.
+ Visiting a leaf.
+ - : int option = Some 1
+ # i();;
+ Visiting a leaf.
+ - : int option = Some 2
+ # i();;
+ Visiting a node.
+ Visiting a leaf.
+ - : int option = Some 3
+ # i();;
+ Visiting a leaf.
+ - : int option = None
+ # i();;
+ - : int option = None
+
+ *)
+
+(* -------------------------------------------------------------------------- *)
+
+(* Variant: it is possible to use the visitor [sometree_reduce] which was
+ generated at the very beginning. This removes the need for defining the
+ type [mytree]. The trick is to override the method [visit_sometree] so as
+ to insert a delay at every tree node. *)
+
+module Variant1 = struct
+
+ class ['self] reduce = object (self : 'self)
+ inherit [_] sometree_reduce as super
+ inherit [_] delayed_tree_monoid
+ method! visit_sometree visit_'a env t =
+ self#visit_delay (super#visit_sometree visit_'a) env t
+ end
+
+ (* The rest of the code is unchanged. It is reproduced here for testing. *)
+
+ class ['self] verbose_reduce = object (_ : 'self)
+ inherit [_] reduce as super
+ method! visit_Leaf visit_'a env =
+ Printf.printf "Visiting a leaf.\n%!";
+ super#visit_Leaf visit_'a env
+ method! visit_Node visit_'a env t1 x t2 =
+ Printf.printf "Visiting a node.\n%!";
+ super#visit_Node visit_'a env t1 x t2
+ end
+
+ let sometree_to_delayed_tree (t : 'a sometree) =
+ new verbose_reduce # visit_sometree yield () t
+
+ let sometree_to_iterator (t : 'a sometree) : 'a iterator =
+ delayed_tree_to_iterator (sometree_to_delayed_tree t)
+
+ let t : int sometree =
+ Node (Node (Leaf, 1, Leaf), 2, Node (Leaf, 3, Leaf))
+
+ let i : int iterator =
+ sometree_to_iterator t
+
+end
+
+(* -------------------------------------------------------------------------- *)
+
+module Variant2 = struct
+
+ (* The function [delayed_tree_to_cascade] could have been written directly
+ as follows, without the auxiliary function [delayed_tree_to_head]: *)
+
+ let rec _delayed_tree_to_cascade (dt : 'a delayed_tree) (k : 'a cascade)
+ : 'a cascade =
+ match dt with
+ | DTZero ->
+ k
+ | DTOne x ->
+ cons x k
+ | DTTwo (dt1, dt2) ->
+ _delayed_tree_to_cascade dt1 (_delayed_tree_to_cascade dt2 k)
+ | DTDelay dt ->
+ fun () -> _delayed_tree_to_cascade (force dt) k ()
+
+ (* In this form, [delayed_tree_to_cascade] is the only operation that is
+ ever applied to a delayed tree, so we can refunctionalize delayed trees,
+ that is, wherever we used to build a delayed tree [t], we now directly
+ build a closure that is equivalent to [delayed_tree_to_cascade t]. *)
+
+ type 'a producer =
+ 'a cascade -> 'a cascade
+
+ type 'a delayed_tree =
+ 'a producer
+
+ let _DTZero k =
+ k
+
+ let _DTOne x k =
+ cons x k
+
+ let _DTTwo dt1 dt2 k =
+ dt1 (dt2 k)
+
+ let _DTDelay dt k =
+ fun () -> force dt k ()
+
+ let (_ : 'a delayed_tree) = _DTZero
+ let (_ : 'a -> 'a delayed_tree) = _DTOne
+ let (_ : 'a delayed_tree -> 'a delayed_tree -> 'a delayed_tree) = _DTTwo
+ let (_ : (unit -> 'a delayed_tree) -> 'a delayed_tree) = _DTDelay
+
+ let delayed_tree_to_cascade (dt : 'a delayed_tree) : 'a cascade =
+ dt nil
+
+ let delayed_tree_to_iterator (dt : 'a delayed_tree) : 'a iterator =
+ cascade_to_iterator (delayed_tree_to_cascade dt)
+
+ (* The delayed monoid uses the new constructors. In [plus], we lose the
+ little optimization whereby [DTZero] were recognized and eliminated on
+ the fly. *)
+
+ class ['self] delayed_tree_monoid = object (_ : 'self)
+
+ method zero =
+ _DTZero
+
+ method plus =
+ _DTTwo
+
+ method visit_delay: 'env 'a .
+ ('env -> 'a -> 'b delayed_tree) ->
+ 'env -> 'a delay -> 'b delayed_tree
+ = fun visit_'a env x ->
+ _DTDelay (fun () -> visit_'a env x)
+
+ end
+
+ let yield _env x =
+ _DTOne x
+
+ (* The rest of the code is as before. It is reproduced here for testing. *)
+
+ class ['self] reduce = object (self : 'self)
+ inherit [_] sometree_reduce as super
+ inherit [_] delayed_tree_monoid
+ method! visit_sometree visit_'a env t =
+ self#visit_delay (super#visit_sometree visit_'a) env t
+ end
+
+ class ['self] verbose_reduce = object (_ : 'self)
+ inherit [_] reduce as super
+ method! visit_Leaf visit_'a env =
+ Printf.printf "Visiting a leaf.\n%!";
+ super#visit_Leaf visit_'a env
+ method! visit_Node visit_'a env t1 x t2 =
+ Printf.printf "Visiting a node.\n%!";
+ super#visit_Node visit_'a env t1 x t2
+ end
+
+ let sometree_to_delayed_tree (t : 'a sometree) =
+ new verbose_reduce # visit_sometree yield () t
+
+ let sometree_to_iterator (t : 'a sometree) : 'a iterator =
+ delayed_tree_to_iterator (sometree_to_delayed_tree t)
+
+ let t : int sometree =
+ Node (Node (Leaf, 1, Leaf), 2, Node (Leaf, 3, Leaf))
+
+ let i : int iterator =
+ sometree_to_iterator t
+
+end
diff --git a/test/dictionary.ml b/test/dictionary.ml
new file mode 100644
index 0000000..afd4fd7
--- /dev/null
+++ b/test/dictionary.ml
@@ -0,0 +1,14 @@
+(* Examples of mixing the monomorphic and polymorphic modes. *)
+
+(* with a monomorphic 'env : *)
+type ('a, 'b) dictionary =
+ | Empty
+ | NonEmpty of 'a * 'b * ('a, 'b) dictionary
+[@@deriving visitors { variety = "map"; polymorphic = ["'b"] }]
+
+(* with a polymorphic 'env : *)
+(* dubious though, since the method [visit_'a] cannot use [env] *)
+type ('a, 'b) dictionary2 =
+ | Empty
+ | NonEmpty of 'a * 'b * ('a, 'b) dictionary2
+[@@deriving visitors { name = "map2"; variety = "map"; polymorphic = ["'b"; "'env"] }]
diff --git a/test/dune b/test/dune
new file mode 100644
index 0000000..4778e54
--- /dev/null
+++ b/test/dune
@@ -0,0 +1,115 @@
+;; Some files must be preprocessed by cppo.
+(rule
+ (targets cloud.ml)
+ (deps cloud.cppo.ml)
+ (action (run %{bin:cppo} -V OCAML:%{ocaml_version} %{deps} -o %{targets})))
+(rule
+ (targets test02.ml)
+ (deps test02.cppo.ml)
+ (action (run %{bin:cppo} -V OCAML:%{ocaml_version} %{deps} -o %{targets})))
+(rule
+ (targets testallprims.ml)
+ (deps testallprims.cppo.ml)
+ (action (run %{bin:cppo} -V OCAML:%{ocaml_version} %{deps} -o %{targets})))
+(rule
+ (targets VisitorsRuntimeBootstrap.ml)
+ (deps VisitorsRuntimeBootstrap.cppo.ml)
+ (action (run %{bin:cppo} -V OCAML:%{ocaml_version} %{deps} -o %{targets})))
+
+(executable
+ (name bench)
+ (modules bench)
+ (preprocess (pps visitors.ppx))
+ (libraries core_bench)
+)
+
+(library
+ (name snippets_basic)
+ (preprocess (pps visitors.ppx))
+ (flags -w A-4-34-44)
+ (modules
+ point build
+ cloud
+ delayed_tree
+ dictionary
+ expr00
+ expr00endo
+ expr00fold
+ expr00fold2
+ expr01
+ expr01use
+ expr01use_variant
+ expr02
+ expr03
+ expr04
+ expr05lexico
+ expr05lexico_test
+ expr05
+ expr06
+ expr11
+ expr15b
+ expr15c
+ expr15
+ expr16
+ expr17
+ expr_info_mapreduce
+ expr_info_mapreduce_test
+ expr_info_mapreduce_use
+ expr_info
+ expr_info_polymorphic
+ expr_info_polymorphic_use
+ expr_info_polymorphic_use_test
+ expr_info_use
+ expr
+ expr_redef
+ fold
+ map_from_fold
+ mapReduce
+ monomorphic
+ monopoly
+ oexpr_polymorphic
+ OOinferfixedagaincheck
+ OOinferfixedagain
+ OOinferfixed
+ OOinfer
+ OOinferself
+ OOinfervirtual
+ opaque
+ polyclass
+ prefixes
+ test00
+ test01
+ test02
+ test03
+ test04
+ test05
+ test06
+ test07
+ testallprims
+ VisitorsRuntimeBootstrap
+ )
+)
+
+(library
+ (name snippets_that_need_hashcons)
+ (preprocess (pps visitors.ppx))
+ (flags -w A-4-34-44)
+ (libraries hashcons)
+ (modules
+ expr08
+ expr08double
+ expr08extra
+ expr12
+ expr13double
+ expr13extra
+ expr13
+ expr14
+ hexpr_polymorphic
+ )
+)
+
+(library
+ (name cil)
+ (modules cil_types cil_types_polymorphic)
+ (preprocess (pps visitors.ppx))
+)
diff --git a/test/expr.ml b/test/expr.ml
new file mode 100644
index 0000000..3d11133
--- /dev/null
+++ b/test/expr.ml
@@ -0,0 +1,3 @@
+type expr =
+ | EConst of int
+ | EAdd of expr * expr
diff --git a/test/expr00.ml b/test/expr00.ml
new file mode 100644
index 0000000..0867bcd
--- /dev/null
+++ b/test/expr00.ml
@@ -0,0 +1,4 @@
+type expr =
+ | EConst of int
+ | EAdd of expr * expr
+ [@@deriving visitors { variety = "iter" }]
diff --git a/test/expr00.mli b/test/expr00.mli
new file mode 100644
index 0000000..2c5c2ed
--- /dev/null
+++ b/test/expr00.mli
@@ -0,0 +1,9 @@
+type expr =
+ | EConst of int
+ | EAdd of expr * expr
+
+class virtual ['self] iter : object ('self)
+ method visit_EAdd : 'monomorphic. 'env -> expr -> expr -> unit
+ method visit_EConst : 'monomorphic. 'env -> int -> unit
+ method visit_expr : 'monomorphic. 'env -> expr -> unit
+end
diff --git a/test/expr00endo.ml b/test/expr00endo.ml
new file mode 100644
index 0000000..6b8ecde
--- /dev/null
+++ b/test/expr00endo.ml
@@ -0,0 +1,4 @@
+type expr =
+ | EConst of int
+ | EAdd of expr * expr
+ [@@deriving visitors { variety = "endo" }]
diff --git a/test/expr00fold.ml b/test/expr00fold.ml
new file mode 100644
index 0000000..0d87d9f
--- /dev/null
+++ b/test/expr00fold.ml
@@ -0,0 +1,4 @@
+type expr =
+ | EConst of (int[@opaque])
+ | EAdd of expr * expr
+ [@@deriving visitors { variety = "fold" }]
diff --git a/test/expr00fold2.ml b/test/expr00fold2.ml
new file mode 100644
index 0000000..7a01203
--- /dev/null
+++ b/test/expr00fold2.ml
@@ -0,0 +1,4 @@
+type expr =
+ | EConst of (int[@opaque])
+ | EAdd of expr * expr
+ [@@deriving visitors { variety = "fold2" }]
diff --git a/test/expr01.ml b/test/expr01.ml
new file mode 100644
index 0000000..7c6fec0
--- /dev/null
+++ b/test/expr01.ml
@@ -0,0 +1,4 @@
+type expr =
+ | EConst of int
+ | EAdd of expr * expr
+ [@@deriving visitors { variety = "map" }]
diff --git a/test/expr01use.ml b/test/expr01use.ml
new file mode 100644
index 0000000..557e19c
--- /dev/null
+++ b/test/expr01use.ml
@@ -0,0 +1,25 @@
+open Expr01
+
+let add e1 e2 =
+ match e1, e2 with
+ | EConst 0, e
+ | e, EConst 0 -> e
+ | _, _ -> EAdd (e1, e2)
+
+let optimize : expr -> expr =
+ let o = object (self)
+ inherit [_] map
+ method! visit_EAdd env e1 e2 =
+ add
+ (self#visit_expr env e1)
+ (self#visit_expr env e2)
+ end in
+ o # visit_expr ()
+
+let z e = EAdd (e, EConst 0)
+
+let () =
+ assert (optimize (z (EConst 1)) = EConst 1);
+ assert (optimize (z (z (EConst 1))) = EConst 1);
+ assert (optimize (EAdd (EConst 1, EConst 1)) = EAdd (EConst 1, EConst 1));
+ assert (optimize (EAdd (z (EConst 1), EConst 1)) = EAdd (EConst 1, EConst 1));
diff --git a/test/expr01use_variant.ml b/test/expr01use_variant.ml
new file mode 100644
index 0000000..42561f0
--- /dev/null
+++ b/test/expr01use_variant.ml
@@ -0,0 +1,20 @@
+open Expr01
+
+let optimize : expr -> expr =
+ let o = object(self)
+ inherit [_] map
+ method! visit_EAdd env e1 e2 =
+ match self#visit_expr env e1, self#visit_expr env e2 with
+ | EConst 0, e
+ | e, EConst 0 -> e
+ | e1, e2 -> EAdd (e1, e2)
+ end in
+ o # visit_expr ()
+
+let z e = EAdd (e, EConst 0)
+
+let () =
+ assert (optimize (z (EConst 1)) = EConst 1);
+ assert (optimize (z (z (EConst 1))) = EConst 1);
+ assert (optimize (EAdd (EConst 1, EConst 1)) = EAdd (EConst 1, EConst 1));
+ assert (optimize (EAdd (z (EConst 1), EConst 1)) = EAdd (EConst 1, EConst 1));
diff --git a/test/expr02.ml b/test/expr02.ml
new file mode 100644
index 0000000..05270da
--- /dev/null
+++ b/test/expr02.ml
@@ -0,0 +1,4 @@
+type expr =
+ | EConst of int
+ | EAdd of expr * expr
+ [@@deriving visitors { variety = "iter2"; concrete = true }]
diff --git a/test/expr03.ml b/test/expr03.ml
new file mode 100644
index 0000000..a20f164
--- /dev/null
+++ b/test/expr03.ml
@@ -0,0 +1,4 @@
+type expr =
+ | EConst of int
+ | EAdd of expr * expr
+ [@@deriving visitors { variety = "map2" }]
diff --git a/test/expr04.ml b/test/expr04.ml
new file mode 100644
index 0000000..b1815cb
--- /dev/null
+++ b/test/expr04.ml
@@ -0,0 +1,13 @@
+open Expr00
+
+let count (e : expr) : int =
+ let v = object
+ val mutable count = 0
+ method count = count
+ inherit [_] iter as super
+ method! visit_EAdd env e0 e1 =
+ count <- count + 1;
+ super#visit_EAdd env e0 e1
+ end in
+ v#visit_expr () e;
+ v#count
diff --git a/test/expr05.ml b/test/expr05.ml
new file mode 100644
index 0000000..e0d7e2e
--- /dev/null
+++ b/test/expr05.ml
@@ -0,0 +1,4 @@
+open Expr02
+
+let equal : expr -> expr -> bool =
+ VisitorsRuntime.wrap2 (new iter2 # visit_expr ())
diff --git a/test/expr05lexico.ml b/test/expr05lexico.ml
new file mode 100644
index 0000000..bb8c3cc
--- /dev/null
+++ b/test/expr05lexico.ml
@@ -0,0 +1,20 @@
+open Expr02
+
+let tag : expr -> int = function
+ | EConst _ -> 0
+ | EAdd _ -> 1
+
+exception Different of int
+
+let compare (i1 : int) (i2 : int) : unit =
+ if i1 <> i2 then
+ raise (Different (if i1 < i2 then -1 else 1))
+
+class compare = object
+ inherit [_] iter2
+ method! visit_int _ i1 i2 = compare i1 i2
+ method! fail_expr () e1 e2 = compare (tag e1) (tag e2)
+end
+
+let compare (e1 : expr) (e2 : expr) : int =
+ try new compare # visit_expr () e1 e2; 0 with Different c -> c
diff --git a/test/expr05lexico_test.ml b/test/expr05lexico_test.ml
new file mode 100644
index 0000000..3ed4385
--- /dev/null
+++ b/test/expr05lexico_test.ml
@@ -0,0 +1,11 @@
+open Expr02
+open Expr05lexico
+
+let () =
+ assert (compare (EConst 1) (EConst 2) = -1);
+ assert (compare (EConst 1) (EAdd (EConst 0, EConst 0)) = -1);
+ assert (compare (EAdd (EConst 0, EConst 0)) (EConst 1) = +1);
+ assert (compare (EAdd (EConst 0, EConst 0)) (EAdd (EConst 0, EConst 0)) = 0);
+ assert (compare (EAdd (EConst 0, EConst 0)) (EAdd (EConst 0, EConst 1)) = -1);
+ assert (compare (EAdd (EConst 1, EConst 0)) (EAdd (EConst 0, EConst 1)) = +1);
+ ()
diff --git a/test/expr06.ml b/test/expr06.ml
new file mode 100644
index 0000000..966079f
--- /dev/null
+++ b/test/expr06.ml
@@ -0,0 +1,16 @@
+type unop =
+ | UnaryMinus
+
+and binop =
+ | BinaryMinus
+ | BinaryAdd
+ | BinaryMul
+ | BinaryDiv
+
+and expr =
+ | EConst of int
+ | EUnOp of unop * expr
+ | EBinOp of expr * binop * expr
+
+[@@deriving visitors { variety = "iter" },
+ visitors { variety = "map" }]
diff --git a/test/expr08.ml b/test/expr08.ml
new file mode 100644
index 0000000..ea885f0
--- /dev/null
+++ b/test/expr08.ml
@@ -0,0 +1,18 @@
+open Expr12 (* oexpr *)
+
+open Hashcons
+
+type hexpr =
+ H of hexpr oexpr hash_consed [@@unboxed]
+
+let table =
+ create 128
+
+let h (e : hexpr oexpr) : hexpr =
+ H (hashcons table e)
+
+class ['self] hmap = object (self : 'self)
+ inherit [_] omap
+ method visit_'expr env (H { node = e; _ }) =
+ h (self#visit_oexpr env e)
+end
diff --git a/test/expr08double.ml b/test/expr08double.ml
new file mode 100644
index 0000000..35ec2b3
--- /dev/null
+++ b/test/expr08double.ml
@@ -0,0 +1,10 @@
+open Expr12 (* [oexpr] *)
+open Expr08 (* [hexpr] *)
+
+let double : hexpr -> hexpr =
+ let v = object
+ inherit [_] hmap
+ method! visit_EConst _env k =
+ EConst (2 * k)
+ end in
+ v # visit_'expr ()
diff --git a/test/expr08extra.ml b/test/expr08extra.ml
new file mode 100644
index 0000000..4890675
--- /dev/null
+++ b/test/expr08extra.ml
@@ -0,0 +1,15 @@
+open Expr12
+open Expr08
+open Expr08double
+
+let econst e = h (EConst e)
+let eadd e1 e2 = h (EAdd (e1, e2))
+
+let e1 : hexpr = eadd (econst 0) (econst 1)
+let e2 : hexpr = new hmap # visit_'expr () e1 (* identity *)
+let () =
+ Printf.printf "%b\n%!" (e1 == e2) (* should print true *)
+let e3 : hexpr = eadd (econst 0) (econst 2)
+let e4 : hexpr = double e1 (* should produce [e3] *)
+let () =
+ Printf.printf "%b\n%!" (e3 == e4) (* should print true *)
diff --git a/test/expr11.ml b/test/expr11.ml
new file mode 100644
index 0000000..3794b68
--- /dev/null
+++ b/test/expr11.ml
@@ -0,0 +1,4 @@
+type expr =
+ | EConst of int
+ | EAdd of expr list
+ [@@deriving visitors { variety = "iter" }]
diff --git a/test/expr12.ml b/test/expr12.ml
new file mode 100644
index 0000000..9c56040
--- /dev/null
+++ b/test/expr12.ml
@@ -0,0 +1,4 @@
+type 'expr oexpr =
+ | EConst of int
+ | EAdd of 'expr * 'expr
+ [@@deriving visitors { name = "omap"; variety = "map" }]
diff --git a/test/expr13.ml b/test/expr13.ml
new file mode 100644
index 0000000..cd8e3ba
--- /dev/null
+++ b/test/expr13.ml
@@ -0,0 +1,10 @@
+open Expr12
+
+type expr =
+ E of expr oexpr [@@unboxed]
+
+class ['self] map = object (self : 'self)
+ inherit [_] omap
+ method visit_'expr env (E e) =
+ E (self#visit_oexpr env e)
+end
diff --git a/test/expr13double.ml b/test/expr13double.ml
new file mode 100644
index 0000000..17fa976
--- /dev/null
+++ b/test/expr13double.ml
@@ -0,0 +1,10 @@
+open Expr12
+open Expr13
+
+let double : expr -> expr =
+ let v = object
+ inherit [_] map
+ method! visit_EConst _env k =
+ EConst (2 * k)
+ end in
+ v # visit_'expr ()
diff --git a/test/expr13extra.ml b/test/expr13extra.ml
new file mode 100644
index 0000000..05304c5
--- /dev/null
+++ b/test/expr13extra.ml
@@ -0,0 +1,26 @@
+open Expr12
+open Expr13
+open Expr13double
+
+let const k = E (EConst k)
+let add e1 e2 = E (EAdd (e1, e2))
+
+let rec eval (E e) =
+ match e with
+ | EConst k -> k
+ | EAdd (e1, e2) -> eval e1 + eval e2
+
+let e : expr =
+ add (const 1) (const 2)
+
+let () =
+ (* should print: 3 then 6 *)
+ Printf.printf "%d\n%d\n%!" (eval e) (eval (double e))
+
+let omap : 'expr1 'expr2 . ('expr1 -> 'expr2) -> 'expr1 oexpr -> 'expr2 oexpr =
+ fun f e ->
+ let v = object
+ inherit [_] omap
+ method visit_'expr _env e = f e
+ end in
+ v # visit_oexpr () e
diff --git a/test/expr14.ml b/test/expr14.ml
new file mode 100644
index 0000000..e5700b0
--- /dev/null
+++ b/test/expr14.ml
@@ -0,0 +1,20 @@
+open Hashcons
+open Expr12 (* [oexpr] *)
+open Expr13 (* [expr] *)
+open Expr08 (* [hexpr] *)
+
+let import : expr -> hexpr =
+ let v = object (self)
+ inherit [_] omap
+ method visit_'expr _env (E e) =
+ h (self#visit_oexpr _env e)
+ end in
+ v # visit_'expr ()
+
+let export : hexpr -> expr =
+ let v = object (self)
+ inherit [_] omap
+ method visit_'expr _env (H { node = e; _ }) =
+ E (self#visit_oexpr _env e)
+ end in
+ v # visit_'expr ()
diff --git a/test/expr15.ml b/test/expr15.ml
new file mode 100644
index 0000000..a20c709
--- /dev/null
+++ b/test/expr15.ml
@@ -0,0 +1,4 @@
+type expr =
+ | EConst of (int[@opaque])
+ | EAdd of expr * expr
+ [@@deriving visitors { variety = "reduce" }]
diff --git a/test/expr15b.ml b/test/expr15b.ml
new file mode 100644
index 0000000..b4adcc1
--- /dev/null
+++ b/test/expr15b.ml
@@ -0,0 +1,10 @@
+open Expr15
+
+let size : expr -> int =
+ let v = object
+ inherit [_] reduce as super
+ inherit [_] VisitorsRuntime.addition_monoid
+ method! visit_expr env e =
+ 1 + super # visit_expr env e
+ end in
+ v # visit_expr ()
diff --git a/test/expr15c.ml b/test/expr15c.ml
new file mode 100644
index 0000000..18204a5
--- /dev/null
+++ b/test/expr15c.ml
@@ -0,0 +1,5 @@
+open Expr15
+open Expr15b
+
+let () =
+ Printf.printf "%d\n" (size (EAdd (EConst 22, EConst 11)))
diff --git a/test/expr16.ml b/test/expr16.ml
new file mode 100644
index 0000000..bba189c
--- /dev/null
+++ b/test/expr16.ml
@@ -0,0 +1,4 @@
+type expr =
+ | EConst of int
+ | EAdd of expr * expr
+ [@@deriving visitors { variety = "iter"; public = ["visit_expr"] }]
diff --git a/test/expr17.ml b/test/expr17.ml
new file mode 100644
index 0000000..8dcb51f
--- /dev/null
+++ b/test/expr17.ml
@@ -0,0 +1,4 @@
+type expr =
+ | EConst of (int[@opaque])
+ | EAdd of expr * expr
+[@@deriving visitors { variety = "mapreduce" }]
diff --git a/test/expr_info.ml b/test/expr_info.ml
new file mode 100644
index 0000000..a07d126
--- /dev/null
+++ b/test/expr_info.ml
@@ -0,0 +1,8 @@
+type 'info expr_node =
+ | EConst of int
+ | EAdd of 'info expr * 'info expr
+
+and 'info expr =
+ { info: 'info; node: 'info expr_node }
+
+[@@deriving visitors { variety = "map" }]
diff --git a/test/expr_info_mapreduce.ml b/test/expr_info_mapreduce.ml
new file mode 100644
index 0000000..05ee19e
--- /dev/null
+++ b/test/expr_info_mapreduce.ml
@@ -0,0 +1,8 @@
+type 'info expr_node =
+ | EConst of int
+ | EAdd of 'info expr * 'info expr
+
+and 'info expr =
+ { info: 'info; node: 'info expr_node }
+
+[@@deriving visitors { variety = "mapreduce" }]
diff --git a/test/expr_info_mapreduce_test.ml b/test/expr_info_mapreduce_test.ml
new file mode 100644
index 0000000..e92f521
--- /dev/null
+++ b/test/expr_info_mapreduce_test.ml
@@ -0,0 +1,29 @@
+open Expr_info_mapreduce
+open Expr_info_mapreduce_use
+
+let mk node = { info = (); node }
+
+let const i =
+ mk (EConst i)
+
+let add e1 e2 =
+ mk (EAdd (e1, e2))
+
+let e =
+ add (const 1) (add (const 0) (const 3))
+
+let (e : int expr) =
+ annotate e
+
+let () =
+ assert (e.info = 5);
+ begin match e.node with
+ | EAdd (e1, e2) ->
+ assert (e1.info = 1);
+ assert (e2.info = 3);
+ ()
+ | EConst _ ->
+ assert false
+ end;
+ Printf.printf "OK\n%!";
+ ()
diff --git a/test/expr_info_mapreduce_use.ml b/test/expr_info_mapreduce_use.ml
new file mode 100644
index 0000000..8442b88
--- /dev/null
+++ b/test/expr_info_mapreduce_use.ml
@@ -0,0 +1,15 @@
+open Expr_info_mapreduce
+
+let annotate (e : _ expr) : int expr =
+ let v = object
+ inherit [_] mapreduce as super
+ inherit [_] VisitorsRuntime.addition_monoid
+ method! visit_expr env { info = _; node } =
+ let node, size = super#visit_expr_node env node in
+ let size = size + 1 in
+ { info = size; node }, size
+ method visit_'info _env _info =
+ assert false (* never called *)
+ end in
+ let e, _ = v # visit_expr () e in
+ e
diff --git a/test/expr_info_polymorphic.ml b/test/expr_info_polymorphic.ml
new file mode 100644
index 0000000..22d3167
--- /dev/null
+++ b/test/expr_info_polymorphic.ml
@@ -0,0 +1,9 @@
+type 'info expr_node =
+ | EConst of int
+ | EAdd of 'info expr * 'info expr
+
+and 'info expr =
+ { info: 'info; node: 'info expr_node }
+
+[@@deriving visitors { variety = "map"; polymorphic = true;
+ concrete = true; data = false }]
diff --git a/test/expr_info_polymorphic_use.ml b/test/expr_info_polymorphic_use.ml
new file mode 100644
index 0000000..8680910
--- /dev/null
+++ b/test/expr_info_polymorphic_use.ml
@@ -0,0 +1,15 @@
+open Expr_info_polymorphic
+
+let v = new map
+
+let strip : _ expr -> unit expr =
+ let visit_'info _env _info = () in
+ fun e ->
+ v # visit_expr visit_'info () e
+
+let number : _ expr -> int expr =
+ let visit_'info count _info =
+ let c = !count in count := c + 1; c in
+ fun e ->
+ let count = ref 0 in
+ v # visit_expr visit_'info count e
diff --git a/test/expr_info_polymorphic_use_test.ml b/test/expr_info_polymorphic_use_test.ml
new file mode 100644
index 0000000..a415811
--- /dev/null
+++ b/test/expr_info_polymorphic_use_test.ml
@@ -0,0 +1,27 @@
+open Expr_info_polymorphic
+open Expr_info_polymorphic_use
+
+let strip : 'a . 'a expr -> unit expr = strip
+let number : 'a . 'a expr -> int expr = number
+
+let mk node = { info = (); node }
+
+let const i =
+ mk (EConst i)
+
+let add e1 e2 =
+ mk (EAdd (e1, e2))
+
+let e =
+ add (const 1) (add (const 0) (const 3))
+
+let e = number (strip e)
+
+let () =
+ assert (e.info = 0);
+ match e.node with
+ | EAdd (e1, e2) ->
+ assert (e1.info = 1);
+ assert (e2.info = 2)
+ | _ ->
+ assert false
diff --git a/test/expr_info_use.ml b/test/expr_info_use.ml
new file mode 100644
index 0000000..c82d224
--- /dev/null
+++ b/test/expr_info_use.ml
@@ -0,0 +1,17 @@
+open Expr_info
+
+let strip (e : _ expr) : unit expr =
+ let v = object
+ inherit [_] map
+ method visit_'info _env _info = ()
+ end in
+ v # visit_expr () e
+
+let number (e : _ expr) : int expr =
+ let v = object
+ inherit [_] map
+ val mutable count = 0
+ method visit_'info _env _info =
+ let c = count in count <- c + 1; c
+ end in
+ v # visit_expr () e
diff --git a/test/expr_redef.ml b/test/expr_redef.ml
new file mode 100644
index 0000000..aef646f
--- /dev/null
+++ b/test/expr_redef.ml
@@ -0,0 +1,4 @@
+type expr = Expr.expr =
+ | EConst of int
+ | EAdd of expr * expr
+ [@@deriving visitors { variety = "iter" }]
diff --git a/test/fold.ml b/test/fold.ml
new file mode 100644
index 0000000..713c312
--- /dev/null
+++ b/test/fold.ml
@@ -0,0 +1,18 @@
+type person = {
+ firstname: string[@opaque];
+ surname: string[@opaque]
+}
+
+and crowd =
+ | Nobody
+ | Someone of person * crowd
+[@@deriving visitors { variety = "fold" }]
+
+let convert : crowd -> (string * string) list =
+ let v = object
+ inherit [_] fold
+ method build_person () f s = (f, s)
+ method build_Nobody () = []
+ method build_Someone () p c = p :: c
+ end
+ in v # visit_crowd ()
diff --git a/test/hexpr_polymorphic.ml b/test/hexpr_polymorphic.ml
new file mode 100644
index 0000000..74e2531
--- /dev/null
+++ b/test/hexpr_polymorphic.ml
@@ -0,0 +1,52 @@
+open Hashcons
+
+module VisitorsHashcons = struct
+
+ (* We CAN implement the method [visit_hash_consed], but this method requires
+ a hash-consing table. We assume that this table is stored in the field
+ [_table], which we declare virtual. *)
+
+ (* A key subtlety is that the method [visit_hash_consed] must be monomorphic
+ in ['b]. Indeed, we cannot hope to build values of type ['b hash_consed]
+ for every ['b]. We can only hope to build values of type ['b hash_consed]
+ for a fixed ['b], where the hash-consing table has type ['b Hashcons.t].
+ For now, the type ['b] is undetermined. It will be fixed in a subclass,
+ where the field [_table] is initialized. *)
+
+ class virtual ['self] map = object (_ : 'self)
+ val virtual _table: 'b Hashcons.t
+ method visit_hash_consed: 'env 'a .
+ ('env -> 'a -> 'b) ->
+ 'env -> 'a hash_consed -> 'b hash_consed
+ = fun visit_'a env { node = e; _ } ->
+ hashcons _table (visit_'a env e)
+ end
+
+end
+
+(* This allows us to define the types [expr] and [hexpr] and generate a
+ visitor class for them. *)
+
+type 'expr oexpr =
+ | EConst of int
+ | EAdd of 'expr * 'expr
+
+and hexpr =
+ H of hexpr oexpr hash_consed [@@unboxed]
+
+[@@deriving visitors { variety = "map"; polymorphic = ["'expr"];
+ ancestors = ["VisitorsHashcons.map"] }]
+
+(* Once the type [hexpr] is defined, we can allocate a table. *)
+
+let table : hexpr oexpr Hashcons.t =
+ Hashcons.create 128
+
+(* Inheriting [map] and defining [_table] yields a working visitor. *)
+
+let id : hexpr -> hexpr =
+ let o = object
+ inherit [_] map
+ val _table = table
+ end in
+ o # visit_hexpr ()
diff --git a/test/mapReduce.ml b/test/mapReduce.ml
new file mode 100644
index 0000000..fc59730
--- /dev/null
+++ b/test/mapReduce.ml
@@ -0,0 +1,9 @@
+type t = int * bool
+
+and u = { x: t; y: t }
+
+and expr =
+ | A
+ | B of t
+[@@deriving visitors { variety = "mapreduce" },
+ visitors { variety = "mapreduce2" }]
diff --git a/test/map_from_fold.ml b/test/map_from_fold.ml
new file mode 100644
index 0000000..dab99ad
--- /dev/null
+++ b/test/map_from_fold.ml
@@ -0,0 +1,37 @@
+(* Direct definitions of [map], [reduce], and [fold]. *)
+class virtual ['self] reduce = object (self: 'self)
+ method private visit_option: 'a .
+ ('env -> 'a -> 'z) -> 'env -> 'a option -> 'z
+ = fun f env ox ->
+ match ox with None -> self#zero | Some x -> f env x
+ method private virtual zero: 'z
+end
+class ['self] map = object (_ : 'self)
+ method private visit_option: 'a 'b .
+ ('env -> 'a -> 'b) -> 'env -> 'a option -> 'b option
+ = fun f env ox ->
+ match ox with None -> None | Some x -> Some (f env x)
+end
+class virtual ['self] fold = object (self : 'self)
+ method private visit_option: 'a .
+ ('env -> 'a -> 'r) -> 'env -> 'a option -> 's
+ = fun f env ox ->
+ match ox with
+ | None -> self#build_None env
+ | Some x -> self#build_Some env (f env x)
+ method private virtual build_None: 'env -> 's
+ method private virtual build_Some: 'env -> 'r -> 's
+end
+(* A successful definition of [reduce] in terms of [fold]. *)
+class virtual ['self] reduce_from_fold = object (self : 'self)
+ inherit [_] fold
+ method private build_None _env = self#zero
+ method private build_Some _env z = z
+ method private virtual zero: 'z
+end
+(* An unsatisfactory definition of [map] in terms of [fold]. *)
+class ['self] map_from_fold = object (_ : 'self)
+ inherit [_] fold
+ method private build_None _env = None
+ method private build_Some _env x = Some x
+end
diff --git a/test/map_from_fold.mli b/test/map_from_fold.mli
new file mode 100644
index 0000000..9c6263d
--- /dev/null
+++ b/test/map_from_fold.mli
@@ -0,0 +1,6 @@
+class ['self] map_from_fold : object ('self)
+ method private visit_option : 'a .
+ ('env -> 'a -> 'b) -> 'env -> 'a option -> 'b option
+ method private build_None : 'env -> 'b option
+ method private build_Some : 'env -> 'b -> 'b option
+end
diff --git a/test/monomorphic.ml b/test/monomorphic.ml
new file mode 100644
index 0000000..553a0f1
--- /dev/null
+++ b/test/monomorphic.ml
@@ -0,0 +1,11 @@
+type 'a t =
+ | Leaf of 'a
+ | Node of 'a t * ('a * 'a) t
+[@@deriving visitors { variety = "map"; monomorphic = ["'env"] }]
+
+let o = object
+ inherit [_] map
+ method! visit_Leaf visit_'a env x =
+ let env = (env : int) in (* check that ['env] is not quantified *)
+ Leaf (visit_'a env x)
+end
diff --git a/test/monopoly.ml b/test/monopoly.ml
new file mode 100644
index 0000000..67fd9f1
--- /dev/null
+++ b/test/monopoly.ml
@@ -0,0 +1,18 @@
+type ('a, 'b) data =
+ | DataNil
+ | DataCons of 'a * 'b * ('a, 'b) data
+
+and 'a seq =
+| Nil
+| Zero of ('a * 'a) seq
+| One of 'a * ('a * 'a) seq
+
+[@@deriving visitors { variety = "iter"; polymorphic = ["a"] },
+ visitors { variety = "map"; polymorphic = ["a"] },
+ visitors { variety = "endo"; polymorphic = ["a"] },
+ visitors { variety = "reduce"; polymorphic = ["a"] },
+ visitors { variety = "mapreduce"; polymorphic = ["a"] },
+ visitors { variety = "iter2"; polymorphic = ["a"] },
+ visitors { variety = "map2"; polymorphic = ["a"] },
+ visitors { variety = "reduce2"; polymorphic = ["a"] },
+ visitors { variety = "mapreduce2"; polymorphic = ["a"] }]
diff --git a/test/oexpr_polymorphic.ml b/test/oexpr_polymorphic.ml
new file mode 100644
index 0000000..585ed4d
--- /dev/null
+++ b/test/oexpr_polymorphic.ml
@@ -0,0 +1,21 @@
+(* Defining open expressions
+ and closing them,
+ in one go,
+ in [polymorphic] mode. *)
+
+type 'expr oexpr =
+ | EConst of int
+ | EAdd of 'expr * 'expr
+
+and expr =
+ E of expr oexpr [@@unboxed]
+
+[@@deriving visitors { variety = "map"; polymorphic = true; concrete = true }]
+
+let double : expr -> expr =
+ let v = object
+ inherit [_] map
+ method! visit_EConst _ _env k =
+ EConst (2 * k)
+ end in
+ v # visit_expr ()
diff --git a/test/opaque.ml b/test/opaque.ml
new file mode 100644
index 0000000..d59f499
--- /dev/null
+++ b/test/opaque.ml
@@ -0,0 +1,21 @@
+type hop = position[@opaque]
+
+and position = {
+ pos_fname : string[@opaque];
+ pos_lnum : int * (int[@opaque]);
+ pos_bol : int;
+ pos_cnum : int;
+ foo: (int[@opaque]) list;
+ }
+and foo =
+ | A of (int[@opaque]) * int
+ | B of bool
+[@@deriving
+ visitors { variety = "iter" },
+ visitors { variety = "map" },
+ visitors { variety = "reduce" },
+ visitors { variety = "endo" },
+ visitors { variety = "iter2" },
+ visitors { variety = "map2" },
+ visitors { variety = "reduce2" }
+]
diff --git a/test/point.ml b/test/point.ml
new file mode 100644
index 0000000..151ac5d
--- /dev/null
+++ b/test/point.ml
@@ -0,0 +1,4 @@
+type point =
+ { x: int; y: int }
+
+let make x y = { x; y }
diff --git a/test/point.mli b/test/point.mli
new file mode 100644
index 0000000..dca6c3e
--- /dev/null
+++ b/test/point.mli
@@ -0,0 +1,2 @@
+type point = private { x: int; y: int }
+val make: int -> int -> point
diff --git a/test/polyclass.ml b/test/polyclass.ml
new file mode 100644
index 0000000..4f7772e
--- /dev/null
+++ b/test/polyclass.ml
@@ -0,0 +1,8 @@
+class ['self] c = object (_ : 'self)
+ method identity (x : 'a) : 'a = x
+end
+
+let b : bool =
+ new c # identity true
+let i : int =
+ new c # identity 0
diff --git a/test/ppx_import/dune b/test/ppx_import/dune
new file mode 100644
index 0000000..22320bf
--- /dev/null
+++ b/test/ppx_import/dune
@@ -0,0 +1,11 @@
+(library
+ (name snippets_that_need_ppx_import)
+ (preprocess (staged_pps ppx_import visitors.ppx))
+ (flags -w A-4-34-44)
+ (libraries ppx_import)
+ (modules
+ expr
+ expr_import
+ expr_import_opaque
+ )
+)
diff --git a/test/ppx_import/expr.ml b/test/ppx_import/expr.ml
new file mode 100644
index 0000000..3d11133
--- /dev/null
+++ b/test/ppx_import/expr.ml
@@ -0,0 +1,3 @@
+type expr =
+ | EConst of int
+ | EAdd of expr * expr
diff --git a/test/ppx_import/expr_import.ml b/test/ppx_import/expr_import.ml
new file mode 100644
index 0000000..ef3acc8
--- /dev/null
+++ b/test/ppx_import/expr_import.ml
@@ -0,0 +1,3 @@
+type expr =
+ [%import: Expr.expr]
+ [@@deriving visitors { variety = "iter" }]
diff --git a/test/ppx_import/expr_import_opaque.ml b/test/ppx_import/expr_import_opaque.ml
new file mode 100644
index 0000000..966949a
--- /dev/null
+++ b/test/ppx_import/expr_import_opaque.ml
@@ -0,0 +1,3 @@
+type expr =
+ [%import: Expr.expr [@with int := int[@opaque]]]
+ [@@deriving visitors { variety = "iter" }]
diff --git a/test/prefixes.ml b/test/prefixes.ml
new file mode 100644
index 0000000..5705855
--- /dev/null
+++ b/test/prefixes.ml
@@ -0,0 +1,23 @@
+class ['self] base = object(_ : 'self)
+ method on_int () i j = i + j
+end
+
+type inttree = Node of (int * inttree * inttree) | Leaf of int
+[@@deriving visitors { variety = "fold2"; visit_prefix = "on_";
+ build_prefix = "mk_"; fail_prefix = "err_";
+ nude = true; ancestors = ["base"]}]
+
+let add_inttree : inttree -> inttree -> int =
+ let v = object
+ inherit [_] fold2 as super
+ method mk_Node () (i, l, r) = i + l + r
+ method mk_Leaf () i = i
+ method! err_inttree () _l _r = 0
+ method! on_inttree = super # on_inttree
+ end
+ in v # on_inttree ()
+
+let t = Node (1, Leaf 2, Leaf 3)
+
+let (_i : int) =
+ add_inttree t t
diff --git a/test/test00.ml b/test/test00.ml
new file mode 100644
index 0000000..f2a84c1
--- /dev/null
+++ b/test/test00.ml
@@ -0,0 +1,11 @@
+type u = Uber
+ and point = u * u
+[@@deriving
+ visitors { variety = "iter" },
+ visitors { variety = "map" },
+ visitors { variety = "reduce" },
+ visitors { variety = "endo" },
+ visitors { variety = "iter2" },
+ visitors { variety = "map2" },
+ visitors { variety = "reduce2" }
+]
diff --git a/test/test01.ml b/test/test01.ml
new file mode 100644
index 0000000..dba7ac0
--- /dev/null
+++ b/test/test01.ml
@@ -0,0 +1,11 @@
+type point =
+ { x: int; y: int; mutable color: bool }
+[@@deriving
+ visitors { variety = "iter" },
+ visitors { variety = "map" },
+ visitors { variety = "reduce" },
+ visitors { variety = "endo" },
+ visitors { variety = "iter2" },
+ visitors { variety = "map2" },
+ visitors { variety = "reduce2" }
+]
diff --git a/test/test02.cppo.ml b/test/test02.cppo.ml
new file mode 100644
index 0000000..d2e4605
--- /dev/null
+++ b/test/test02.cppo.ml
@@ -0,0 +1,33 @@
+type term =
+ | TUnit
+ | TIntLiteral of int
+ | TVar of string
+ | TLambda of string * term
+ | TApp of term * term
+#if OCAML_VERSION >= (4, 03, 0)
+ | TPair of { fst: term; snd: term }
+#endif
+ | TTuple of term_list
+
+and term_list =
+ | TLNil
+ | TLCons of (term * term_list)
+
+[@@deriving
+ visitors { variety = "iter"; concrete = true },
+ visitors { variety = "map"; concrete = true },
+ visitors { variety = "reduce"; concrete = true; ancestors = ["VisitorsRuntime.addition_monoid"] },
+ visitors { variety = "endo"; concrete = true },
+ visitors { variety = "iter2"; concrete = true },
+ visitors { variety = "map2"; concrete = true },
+ visitors { variety = "reduce2"; concrete = true; ancestors = ["VisitorsRuntime.addition_monoid"] }
+]
+
+let identity : term =
+ TLambda ("x", TVar "x")
+
+let () =
+ new iter#visit_term 33 identity
+
+let () =
+ new iter#visit_term 33 (new map#visit_term () identity)
diff --git a/test/test03.ml b/test/test03.ml
new file mode 100644
index 0000000..064f627
--- /dev/null
+++ b/test/test03.ml
@@ -0,0 +1,63 @@
+type ('var, 'binder) term =
+ | TVar of 'var
+ | TAbs of 'binder * ('var, 'binder) term
+ | TApp of ('var, 'binder) term * ('var, 'binder) term
+[@@deriving
+ visitors { variety = "iter" },
+ visitors { variety = "map" },
+ visitors { variety = "reduce" },
+ visitors { variety = "endo" },
+ visitors { variety = "iter2" },
+ visitors { variety = "map2" },
+ visitors { variety = "reduce2" }
+]
+
+(* Nominal. *)
+
+module StringSet = Set.Make(String)
+
+let iter = object(self)
+ inherit [_] iter
+ (* Descending methods for local types. *)
+ method! visit_TAbs env x t =
+ let env = StringSet.add x env in
+ self#visit_term env t
+ (* Descending methods for nonlocal types. *)
+ method visit_'binder _env _x = ()
+ method visit_'var env x =
+ if StringSet.mem x env then
+ Printf.printf "%s is a bound variable.\n%!" x
+ else
+ Printf.printf "%s is a free variable.\n%!" x
+
+end
+
+let t : (_, _) term =
+ TAbs ("x", TApp (TVar "x", TVar "y"))
+
+let () =
+ iter#visit_term StringSet.empty t
+
+(* De Bruijn. *)
+
+let iter = object(self)
+ inherit [_] iter
+ (* Descending methods for local types. *)
+ method! visit_TAbs env _x t =
+ let env = 1 + env in
+ self#visit_term env t
+ (* Descending methods for nonlocal types. *)
+ method visit_'binder _env _x = ()
+ method visit_'var env x =
+ if x < env then
+ Printf.printf "%d is a bound variable.\n%!" x
+ else
+ Printf.printf "%d is a free variable.\n%!" x
+
+end
+
+let t : (_, _) term =
+ TAbs ((), TApp (TVar 0, TVar 1))
+
+let () =
+ iter#visit_term 0 t
diff --git a/test/test04.ml b/test/test04.ml
new file mode 100644
index 0000000..9f64099
--- /dev/null
+++ b/test/test04.ml
@@ -0,0 +1,16 @@
+type 'info expr_node =
+ | EConst of int
+ | EAdd of 'info expr * 'info expr
+
+and 'info expr =
+ { info: 'info; node: 'info expr_node }
+
+[@@deriving visitors { variety = "iter"; polymorphic = true },
+ visitors { variety = "map"; polymorphic = true },
+ visitors { variety = "endo"; polymorphic = true },
+ visitors { variety = "reduce"; polymorphic = true },
+ visitors { variety = "mapreduce"; polymorphic = true },
+ visitors { variety = "iter2"; polymorphic = true },
+ visitors { variety = "map2"; polymorphic = true },
+ visitors { variety = "reduce2"; polymorphic = true },
+ visitors { variety = "mapreduce2"; polymorphic = true }]
diff --git a/test/test05.ml b/test/test05.ml
new file mode 100644
index 0000000..baf60ae
--- /dev/null
+++ b/test/test05.ml
@@ -0,0 +1,16 @@
+(* Testing that @opaque is properly detected. *)
+
+module T = struct
+ type t = A of ((int -> int)[@deriving.visitors.opaque])
+ [@@deriving visitors { variety = "map" }]
+end
+
+module U = struct
+ type u = B of ((int -> int)[@visitors.opaque])
+ [@@deriving visitors { variety = "map" }]
+end
+
+module V = struct
+ type w = C of ((int -> int)[@opaque])
+ [@@deriving visitors { variety = "map" }]
+end
diff --git a/test/test06.ml b/test/test06.ml
new file mode 100644
index 0000000..21d4424
--- /dev/null
+++ b/test/test06.ml
@@ -0,0 +1,38 @@
+(* Testing @name attributes on data constructors. *)
+
+type foo =
+ | A [@name "TA"]
+ | B of int [@name "TB"]
+ | C of int * int [@name "TC"]
+[@@deriving visitors { variety = "map"; concrete = true },
+ visitors { variety = "fold"; ancestors = ["VisitorsRuntime.map"] }]
+
+let f (x : foo) =
+ let o = object
+ inherit [_] map
+ method! visit_TA _env = B 0
+ method! visit_TB _env x = B (x + 1)
+ method! visit_TC _env x y = C (x, x + y)
+ end in
+ o # visit_foo () x
+
+let () =
+ assert (f A = B 0);
+ assert (f (B 0) = B 1);
+ assert (f (C (1, 1)) = C (1, 2));
+ ()
+
+let g (x : foo) : int =
+ let o = object
+ inherit [_] fold
+ method build_TA _env = 42
+ method build_TB _env x = x
+ method build_TC _env x y = x + y
+ end in
+ o # visit_foo () x
+
+let () =
+ assert (g A = 42);
+ assert (g (B 12) = 12);
+ assert (g (C (1, 1)) = 2);
+ ()
diff --git a/test/test07.ml b/test/test07.ml
new file mode 100644
index 0000000..5e9f109
--- /dev/null
+++ b/test/test07.ml
@@ -0,0 +1,49 @@
+(* Testing @name attributes on data types. *)
+
+(* Testing local types decorated with [@@name]. *)
+
+module Point = struct
+
+ type point = { x : coordinate; y : coordinate } [@@name "foo"]
+
+ and coordinate = float [@@name "coord"]
+
+ [@@deriving visitors { variety = "map"; concrete = true },
+ visitors { variety = "fold"; ancestors = ["VisitorsRuntime.map"]}]
+
+ let f (p : point) =
+ let o = new map in
+ o # visit_foo () p
+
+ let () =
+ assert (f { x = 0.; y = 0. } = { x = 0.; y = 0. });
+ ()
+
+ let g (p : point) : float =
+ let o = object
+ inherit [_] fold
+ method build_coord _env x = x
+ method build_foo _env x y = x +. y
+ end in
+ o # visit_foo () p
+
+ let () =
+ assert (g { x = 1.; y = 2. } = 3.);
+ ()
+
+end
+
+type boolean = Vrai | Faux [@@name "condition"]
+[@@deriving visitors { variety = "iter2"; concrete = true }]
+
+let () =
+ try
+ new iter2 # fail_condition () Vrai Faux;
+ assert false
+ with VisitorsRuntime.StructuralMismatch ->
+ ()
+
+(* Testing nonlocal types decorated with [@name]. *)
+
+type segment = { source: Point.point[@name "foo"]; destination: Point.point[@name "foo"] }
+[@@deriving visitors { variety = "map"; concrete = true; nude = true; ancestors = ["Point.map"] }]
diff --git a/test/testallprims.cppo.ml b/test/testallprims.cppo.ml
new file mode 100644
index 0000000..238c4b8
--- /dev/null
+++ b/test/testallprims.cppo.ml
@@ -0,0 +1,30 @@
+type t =
+ | Array of t array
+ | Bool of bool
+ | Bytes of bytes
+ | Char of char
+ | Float of float
+ | Int of int
+ | Int32 of int32
+ | Int64 of int64
+ | Lazy of t lazy_t
+ | List of t list
+ | Nativeint of nativeint
+ | Option of t option
+ | Ref of t ref
+#if OCAML_VERSION >= (4, 08, 0)
+ | Result of (t, t) result
+#endif
+ | String of string
+ | Unit of unit
+ | Tuple2 of (t * t)
+ | Tuple3 of (t * t * t)
+[@@deriving
+ visitors { variety = "iter"; concrete = true },
+ visitors { variety = "map"; concrete = true },
+ visitors { variety = "reduce"; ancestors=["VisitorsRuntime.addition_monoid"]; concrete = true },
+ visitors { variety = "endo"; concrete = true },
+ visitors { variety = "iter2"; concrete = true },
+ visitors { variety = "map2"; concrete = true },
+ visitors { variety = "reduce2"; ancestors=["VisitorsRuntime.addition_monoid"]; concrete = true }
+]
diff --git a/visitors.opam b/visitors.opam
new file mode 100644
index 0000000..bf77582
--- /dev/null
+++ b/visitors.opam
@@ -0,0 +1,23 @@
+opam-version: "2.0"
+maintainer: "francois.pottier@inria.fr"
+authors: [
+ "François Pottier <francois.pottier@inria.fr>"
+]
+homepage: "https://gitlab.inria.fr/fpottier/visitors"
+dev-repo: "git+https://gitlab.inria.fr/fpottier/visitors.git"
+bug-reports: "francois.pottier@inria.fr"
+build: [
+ ["dune" "build" "-p" name "-j" jobs]
+]
+depends: [
+ "ocaml" {>= "4.05.0"}
+ "ppxlib" {>= "0.22.0"}
+ "ppx_deriving" {>= "5.0"}
+ "result"
+ "dune" {>= "2.0"}
+]
+synopsis: "An OCaml syntax extension for generating visitor classes"
+description: """
+Annotating an algebraic data type definition with [@@deriving visitors { ... }]
+causes visitor classes to be automatically generated. A visitor is an object
+that knows how to traverse and transform a data structure."""