Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Printer for terms #14

Closed
wants to merge 14 commits into from
Closed

Printer for terms #14

wants to merge 14 commits into from

Conversation

Gbury
Copy link
Owner

@Gbury Gbury commented Nov 9, 2018

Should close #8 once merged.

TODO:

  • Adapt dune build system to compile the printers in a separate package (with additional dependencies)
  • Finish term and statement printer for tptp
  • Term and statement printer for smtlib
  • some tests (testing identify of round-tripping parsing and printing)

@anmaped
Copy link

anmaped commented Dec 3, 2018

@Gbury In the tptp file is it a typo let name id = Pretty.Normal (Dolmen_std.Id.full_name id) in, or do you plan to extend the Normal construct inside Pretty?

@Gbury
Copy link
Owner Author

Gbury commented Dec 3, 2018

That's a typo, should indeed be Escape.Normal, ^^

@anmaped
Copy link

anmaped commented Dec 3, 2018

It's corrected then.

@anmaped
Copy link

anmaped commented Dec 3, 2018

Should we create a new package, including the external dependencies in the dolmen.opam file, or compile dolmen.export only if the dependencies are available?

@Gbury
Copy link
Owner Author

Gbury commented Dec 3, 2018

Separate package, by creating a dolmen-export.opam file with the correct deps (i.e. dolmen, uucp and uutf).

@anmaped
Copy link

anmaped commented Dec 3, 2018

@Gbury It's right. I forget it.

open Term

(* auxiliar functions *)
let pp_builtins = function
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe reserve the pp_* names for functions that actually print things (and thus have a type Format.formatter -> 'a -> unit). Maybe use a name like pretty_builtins ?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It's that the idea.

@anmaped
Copy link

anmaped commented Dec 5, 2018

Should we treat this cases like that ?

| Def (id, ({term = Binder (binder, _, _)} as term)) ->
    Format.fprintf
      fmt
      "(define-%s %s %a)"
      (print_binder binder).name
      (Dolmen_std.Id.full_name id)
      print_terms
      term
| Def (id, _) -> assert false

In smtlib doesn't make sense to print a definition that is not a function nor a sort.

@Gbury
Copy link
Owner Author

Gbury commented Dec 6, 2018

Smtlib's define-fun allows functions with arity 0, i.e. it allows defining constants, so no need for an assert false.

@@ -1,71 +1,86 @@
(* This module contains the pretty-printer functions for smtlib *)

open Dolmen_std

open Pretty
open Term
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm really, really, really not a fan of using a lot of opens. Dolmen_std is fine to open, but Pretty and Term should not be opened.

@Gbury
Copy link
Owner Author

Gbury commented Dec 6, 2018

I don't think you've understood the design of the Pretty module (though that's probably my fault for not documenting it enough). The point of a Pretty.t is to factorize away the printing of single identifiers.

So in a typical control flow, you'll have a function pretty_of_builtin : builtin -> Pretty.t (Note that you called it print_builtin although it simply creates a Pretty.t, and does not actually print anything). Similarly, you'd have a function from an Id to a Pretty.t.
Afterwards, you'd write a function that actually prints terms that are applications, and in this function, you'll use the information of the Pretty.t of the head symbol to decide how to print the term. So for instance the printing functions in https://github.com/Gbury/archsat/blob/master/src/output/tptp.ml#L113

@anmaped
Copy link

anmaped commented Dec 6, 2018

Smtlib's define-fun allows functions with arity 0, i.e. it allows defining constants, so no need for an assert false.

So, what to do with the other binders?

@Gbury
Copy link
Owner Author

Gbury commented Dec 6, 2018

So, what to do with the other binders?

Well, clearly, in a lot of cases (for instance, when a forall is bound), the term cannot be printed. In such cases, instead of assert false, a custom exception such as Smtlib.Cannot_print of term should be raised I think, at least for now.

@anmaped
Copy link

anmaped commented Dec 6, 2018

So, what to do with the other binders?

Well, clearly, in a lot of cases (for instance, when a forall is bound), the term cannot be printed. In such cases, instead of assert false, a custom exception such as Smtlib.Cannot_print of term should be raised I think, at least for now.

Yes. I will do it incrementally, first I expect to pretty print all the parsed smtlib files (some that I have generated), then we can do translations from other constructions available for instance in tptp.

@anmaped
Copy link

anmaped commented Jan 29, 2019

@Gbury Do you have any reason for implementing the order of body ty_ret like

let fun_def ?loc id args ty_ret body =
  let t = Term.lambda args (Term.colon body ty_ret) in
  mk ?loc (Def (id, t))

instead of

let fun_def ?loc id args ty_ret body =
  let t = Term.lambda args (Term.colon ty_ret body) in
  mk ?loc (Def (id, t))

@Gbury
Copy link
Owner Author

Gbury commented Jan 29, 2019

Typically, most type annotations are of the form: term: type (I think all the exmaples I know of always put the term on the left, and the type on the right). If you look at the way typed variables are handled (for instance, in quantifications), it is also in this order.

@anmaped
Copy link

anmaped commented Jan 29, 2019

Alright.

@anmaped
Copy link

anmaped commented Jan 31, 2019

Should we create a new bash script for testing dolmen-exports? Which testing mechanism have you in mind?

@Gbury
Copy link
Owner Author

Gbury commented Jan 31, 2019

Basically, the goal of tests would be to check that parsing and printing are invers of one another, which can be divided into two distinct tests:

  • For any AST, printing it, then parsing it should produce the same AST (modulo the normalization functions in Normalize)
  • For any printed file, parsing it and then printing it should produce an identical file (note that the input file needs to be the result of printing some AST using the printing function, in order to not fail on basic formatting differences).

The two tests can be done at the same time, using a small ocaml program which does the following:

  • take an arbitrary input in some language
  • parse it, and save the AST somewhere
  • print the AST to a first file
  • parse that file, and check that this second AST matched the first one
  • print that second AST into a second file
  • check that the two produced files are identical (could be done outside the ocaml program, by using diff in the shell script)

This would then need to be run on pretty much the whole smtlib to check that there are no errors.

@Gbury
Copy link
Owner Author

Gbury commented Jan 31, 2019

Additionally, it could be nice to have some quickcheck-like testing (using the same method as described in the previous comment, but using a randomly-generated AST instead of an AST coming from an input file).

@bobot
Copy link
Contributor

bobot commented Sep 28, 2021

@Gbury What is the plan for the printing feature?

@Gbury
Copy link
Owner Author

Gbury commented Sep 28, 2021

@Gbury What is the plan for the printing feature?

The printing feature is the next big item on my todo list for dolmen, on which i'll be working once #84 is merged.

My current plan is to add printing functors, which will take a view on terms, and return printing functions. I still have a few details concerning scopes[1] and differences in spec between languages[2] to work out, but it shouldn't delay things too much. When I have working code, I'll probably open a different PR (and close this one). As for the timeline, maybe I'll get enough time to get some working code around the end of October ?

[1] : the printing function will take as first argument an environment, which will carry both a global and local state in order to accurately track scopes and potential renaming of variables/constants in order to avoid unintended shadowing.

[2] : the module taken as argument to the printing functor will expect a view functions on terms. For simplicity, this view type will be defined by Dolmen and most likely use the current types builtins. The printing of builtins is straightforward when the same language is used as input and output, but for the other cases, it can be more tricky. Basically, there are a few subtle situations:

  • builtins from a source language that do not exist in the printing language. For these there are a few solutions (which will probably end up being configurable by the user of printing functions): either fail during the printing, or provide emulations (either in a prelude that will need to be printed/included from somewhere, or locally if the wrappers are small enough)
  • builtins that are present in both a the source and destination languages, but which might have subtly differing semantics in the two languages (think about arithmetic operators and rounding, etc...). For that, I'll probably need to re-read the specs quite carefully and assign a very precise semantics to each of Dolmen's builtins.
  • lastly for some language features which are missing in the destination language or different enough, dolmen might need some more involved manipulation on terms before printing. For instance, for datatype in a source language with mainly constructors/testers (i.e. which mainly use is#some_constructor predicates) and a destination language which mainly uses pattern matching, we'll probably want to recognize "deep" if/then/else structures that encode pattern matching using the is#constr predicates in order to print these as a single pattern matching.

@Gbury
Copy link
Owner Author

Gbury commented Feb 9, 2022

This is now a bit too outdated, so i'll close this PR and open a new one when I have the time to work on printing/exporting.

@Gbury Gbury closed this Feb 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Term printers
3 participants