From: Tom Ridge via Cl-isabelle-users <cl-isabelle-users@lists.cam.ac.uk>
Dear All,
I'm exporting to OCaml from Isabelle/HOL. I would like type synonyms to be
preserved (because I perform some munging on the generated code). Is this
possible? The top of the isabelle .thy looks like:
theory Export_code
imports Find Insert Delete Insert_many
"~~/src/HOL/Library/Code_Target_Numeral"
"~~/src/HOL/Library/Code_Char"
begin
export_code "Code_Numeral.nat_of_integer" "Code_Numeral.int_of_integer"
...
A related question: The code contains eg:
let rec dest_lista
xs = (match xs
with [] ->
failwitha ['d'; 'e'; 's'; 't'; '_'; 'l'; 'i'; 's'; 't'; '\039';
' ']
| _ :: _ -> (List.butlast xs, List.last xs));;
In Isabelle, the param to failwitha is a string. How can I make the list of
chars param in the generated code a proper OCaml string?
Similarly, my exported code contains things like:
val split_at : Arith.nat -> 'a list -> 'a list * 'a list
How can I get OCaml's "int" type instead of Arith.nat?
Thanks
Tom
From: Tobias Nipkow <nipkow@in.tum.de>
On 08/02/2017 11:44, Tom Ridge via Cl-isabelle-users wrote:
Dear All,
I'm exporting to OCaml from Isabelle/HOL. I would like type synonyms to be
preserved (because I perform some munging on the generated code). Is this
possible? The top of the isabelle .thy looks like:
Unfortunately not, they are expanded after parsing. What you can do, but this is
a hack, is to fold them back explicitly via a translation. Example:
type_synonym nat_list = "nat list"
translations
(type) "nat_list" <= (type) "nat list"
But now EVERY occurrence of "nat list" becomes "nat_list". Use at your own risk.
Tobias
theory Export_code
imports Find Insert Delete Insert_many
"~~/src/HOL/Library/Code_Target_Numeral"
"~~/src/HOL/Library/Code_Char"
beginexport_code "Code_Numeral.nat_of_integer" "Code_Numeral.int_of_integer"
...
A related question: The code contains eg:
let rec dest_lista
xs = (match xs
with [] ->
failwitha ['d'; 'e'; 's'; 't'; '_'; 'l'; 'i'; 's'; 't'; '\039';
' ']
| _ :: _ -> (List.butlast xs, List.last xs));;In Isabelle, the param to failwitha is a string. How can I make the list of
chars param in the generated code a proper OCaml string?Similarly, my exported code contains things like:
val split_at : Arith.nat -> 'a list -> 'a list * 'a list
How can I get OCaml's "int" type instead of Arith.nat?
Thanks
Tom
From: Andreas Lochbihler <andreas.lochbihler@inf.ethz.ch>
Pretty-print translations only work within Isabelle, not for the generated code. The code
generator does not offer any means to use type synonyms. You have to make the type synonym
a typedef and lift all functions in your formalisation to the new type.
Andreas
From: Andreas Lochbihler <andreas.lochbihler@inf.ethz.ch>
Hi Tom,
On 08/02/17 11:44, Tom Ridge via Cl-isabelle-users wrote:
A related question: The code contains eg:
let rec dest_lista
xs = (match xs
with [] ->
failwitha ['d'; 'e'; 's'; 't'; '_'; 'l'; 'i'; 's'; 't'; '\039';
' ']
| _ :: _ -> (List.butlast xs, List.last xs));;In Isabelle, the param to failwitha is a string. How can I make the list of
chars param in the generated code a proper OCaml string?
There are a few types in Isabelle/HOL's library which are designed for exchanging data in
the generated code. For strings, you should use String.literal if you want to have OCaml
strings.
For integers, there's integer in the theory Code_Target, but this maps to Big_Int, not it.
Many years ago, there was also some setup to implement nat with the Big_Int type, but that
has long gone, because it was not formally checked that all functions maintain the
invariant ">= 0". If you import Code_Target_Nat from HOL/Library, your generated code will
implement Arith.nat using Big_Int, so you can construct such Arith.nat values in your
hand-written code and pass it to functions like split_at.
As OCaml's int type is bounded, one should not use it for nat, because nat is unbounded in
HOL. My AFP entry Native_Word imports various fixed-length integers from the target
languages (OCaml's int as Uint.uint). But clearly, Uint.uint is not isomorphic to nat.
In general, I recommend that you define a clear interface between the generated code and
your hand-written parts, which should be as small as possible. Some thought's on this can
be found in my Isabelle 2014 workshop paper (Section 4):
Hope this helps,
Andreas
Similarly, my exported code contains things like:
val split_at : Arith.nat -> 'a list -> 'a list * 'a list
How can I get OCaml's "int" type instead of Arith.nat?
Thanks
Tom
From: Tom Ridge via Cl-isabelle-users <cl-isabelle-users@lists.cam.ac.uk>
Thanks to all. Very useful, and the '14 paper is a good read.
Thanks
From: Tom Ridge via Cl-isabelle-users <cl-isabelle-users@lists.cam.ac.uk>
Suppose I know somehow (!) that integer overflow is not a problem, and in
OCaml I define a Nat module, with type t = int, which maintains the >=0
invariant (and others? basically, int is made to behave like nat). Is it
possible to target the Nat.t type in Isabelle code generation?
Thanks
From: Andreas Lochbihler <andreas.lochbihler@inf.ethz.ch>
Hi Tom,
Sure. You can map any HOL type constructor to any target-language type using adaptation.
But as adaptations are unverified, they become part of the trusted code base, so be careful.
Adaptations are explained in general the code generator tutorial (isabelle doc codegen,
Section 6). In your case, you can probably copy most of the OCaml adaptations (code_module
and code_printing) for uint in AFP/Native_Word/Uint and change everything from uint to
nat. Note that Native_Word does some things in a somewhat complicated way (there are
several versions of division), because it tries to fit several different target languages
and evaluation by the simplifier under one hood. If you grep for "code_printing" in the
distribution and the AFP, you should find more examples of how adaptation is done in practice.
Hope this helps,
Andreas
Last updated: Apr 25 2024 at 20:15 UTC