bin: add shorthands for ltlcross and ltldo
* src/bin/common_trans.cc: Implement shorthands. * doc/org/ltlcross.org, doc/org/ltldo.org: Document them. * src/tgbatest/ltldo2.test: Quick test. * NEWS: Mention it.
This commit is contained in:
parent
259c9faaae
commit
a24a021964
5 changed files with 217 additions and 27 deletions
6
NEWS
6
NEWS
|
|
@ -37,6 +37,12 @@ New in spot 1.99a (not yet released)
|
||||||
now. The short '-n NUM' option is now the same as the new
|
now. The short '-n NUM' option is now the same as the new
|
||||||
--max-count=N option, for consistency with other tools.
|
--max-count=N option, for consistency with other tools.
|
||||||
|
|
||||||
|
- ltlcross (and ltldo) have a list of hard-coded shorthands
|
||||||
|
for some existing tools. So for instance running
|
||||||
|
'ltlcross spin ...' is the same as running
|
||||||
|
'ltlcross "spin -f %s>%N" ...'. This feature is much
|
||||||
|
more useful for ltldo.
|
||||||
|
|
||||||
- There is a parser for the HOA format
|
- There is a parser for the HOA format
|
||||||
(http://adl.github.io/hoaf/) available as a
|
(http://adl.github.io/hoaf/) available as a
|
||||||
spot::hoa_stream_parser object or spot::hoa_parse() function.
|
spot::hoa_stream_parser object or spot::hoa_parse() function.
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,35 @@ tools:
|
||||||
so we have to rename =%D.dst= as =%D= so that =ltlcross= can find the file)
|
so we have to rename =%D.dst= as =%D= so that =ltlcross= can find the file)
|
||||||
- '=ltl3dra -f %s >%D='
|
- '=ltl3dra -f %s >%D='
|
||||||
|
|
||||||
|
To simplify the use of some of the above tools, a set of predefined
|
||||||
|
shorthands are available. Those can be listed with the
|
||||||
|
=--list-shorthands= option.
|
||||||
|
|
||||||
|
#+BEGIN_SRC sh :results verbatim :exports both
|
||||||
|
ltlcross --list-shorthands
|
||||||
|
#+END_SRC
|
||||||
|
#+RESULTS:
|
||||||
|
#+begin_example
|
||||||
|
If a COMMANDFMT does not use any %-sequence, and starts with one of
|
||||||
|
the following words, then the string on the right is appended.
|
||||||
|
|
||||||
|
lbt <%L>%T
|
||||||
|
ltl2ba -f %s>%N
|
||||||
|
ltl2dstar %L %D
|
||||||
|
ltl2tgba -H %f>%H
|
||||||
|
ltl3ba -f %s>%N
|
||||||
|
ltl3dra -f %f>%D
|
||||||
|
modella %L %T
|
||||||
|
spin -f %s>%N
|
||||||
|
#+end_example
|
||||||
|
|
||||||
|
What this implies is that running =ltlcross ltl2ba ltl3ba ...= is
|
||||||
|
the same as running =ltlcross 'ltl2ba -f %s>%N' 'ltl3ba -f %s>%N' ...=
|
||||||
|
|
||||||
|
Because only the prefix of the actual command is checked, you can
|
||||||
|
still specify some options. For instance =ltlcross 'ltl2tgba -D' ...=
|
||||||
|
is short for =ltlcross 'ltl2tgba -D -H %F>%H' ...=
|
||||||
|
|
||||||
* Getting statistics
|
* Getting statistics
|
||||||
|
|
||||||
Detailed statistics about the result of each translation, and the
|
Detailed statistics about the result of each translation, and the
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ X[]!<>((a && ![]b) || (!a && []b)),4,10
|
||||||
Using =ltldo= the above command can be reduced to this:
|
Using =ltldo= the above command can be reduced to this:
|
||||||
|
|
||||||
#+BEGIN_SRC sh :results verbatim :exports both
|
#+BEGIN_SRC sh :results verbatim :exports both
|
||||||
ltldo -F sample.ltl 'ltl3ba -f %s>%N' --stats='%f,%s,%t'
|
ltldo 'ltl3ba -f %s>%N' -F sample.ltl --stats='%f,%s,%t'
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
#+RESULTS:
|
#+RESULTS:
|
||||||
#+begin_example
|
#+begin_example
|
||||||
|
|
@ -101,6 +101,27 @@ Note that the formulas look different in both cases, because in the
|
||||||
=while= loop the formula printed has already been processed with
|
=while= loop the formula printed has already been processed with
|
||||||
=ltlfilt=, while =ltldo= emits the input string untouched.
|
=ltlfilt=, while =ltldo= emits the input string untouched.
|
||||||
|
|
||||||
|
In fact, as we will discuss below, =ltl3ba= is a tool that =ltldo=
|
||||||
|
already knows about, so there is a shorter way to run the above
|
||||||
|
command:
|
||||||
|
|
||||||
|
#+BEGIN_SRC sh :results verbatim :exports code
|
||||||
|
ltldo ltl3ba -F sample.ltl --stats='%f,%s,%t'
|
||||||
|
#+END_SRC
|
||||||
|
#+RESULTS:
|
||||||
|
#+begin_example
|
||||||
|
1,1,1
|
||||||
|
1 U a,2,4
|
||||||
|
!(!((a U Gb) U b) U GFa),2,4
|
||||||
|
(b <-> Xc) xor Fb,7,21
|
||||||
|
FXb R (a R (1 U b)),6,28
|
||||||
|
Ga,1,1
|
||||||
|
G(!(c | (a & (a W Gb))) M Xa),1,0
|
||||||
|
GF((b R !a) U (Xc M 1)),2,4
|
||||||
|
G(Xb | Gc),3,11
|
||||||
|
XG!F(a xor Gb),4,10
|
||||||
|
#+end_example
|
||||||
|
|
||||||
* Example: running =spin= and producing HOA
|
* Example: running =spin= and producing HOA
|
||||||
|
|
||||||
Here is another example, where we use Spin to produce two automata in
|
Here is another example, where we use Spin to produce two automata in
|
||||||
|
|
@ -142,6 +163,13 @@ State: 1 {0}
|
||||||
--END--
|
--END--
|
||||||
#+end_example
|
#+end_example
|
||||||
|
|
||||||
|
Again, using the shorthands defined below, the previous command can be
|
||||||
|
simplified to just this:
|
||||||
|
|
||||||
|
#+BEGIN_SRC sh :results verbatim :exports code
|
||||||
|
ltldo spin -f a -f GFa -H
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
* Syntax for specifying tools to call
|
* Syntax for specifying tools to call
|
||||||
|
|
||||||
The syntax for specifying how a tool should be called is the same as
|
The syntax for specifying how a tool should be called is the same as
|
||||||
|
|
@ -159,9 +187,10 @@ ltldo --help | sed -n '/character sequences:/,/^$/p' | sed '1d;$d'
|
||||||
: %N,%T,%D,%H the automaton is output as a Never claim, or in
|
: %N,%T,%D,%H the automaton is output as a Never claim, or in
|
||||||
: LBTT's, in LTL2DSTAR's, or in the HOA format
|
: LBTT's, in LTL2DSTAR's, or in the HOA format
|
||||||
|
|
||||||
Contrarily to =ltlcross=, it this not mandatory to specify an output filename
|
Contrarily to =ltlcross=, it this not mandatory to specify an output
|
||||||
using one of the sequence for that later lines. For instance we could
|
filename using one of the sequence for that last line. For instance
|
||||||
simply run a formula though =echo= to compare different output syntaxes:
|
we could simply run a formula though =echo= to compare different
|
||||||
|
output syntaxes:
|
||||||
|
|
||||||
#+BEGIN_SRC sh :results verbatim :exports both
|
#+BEGIN_SRC sh :results verbatim :exports both
|
||||||
ltldo -f 'p0 U p1' -f 'GFp0' 'echo %f, %s, %l, %w'
|
ltldo -f 'p0 U p1' -f 'GFp0' 'echo %f, %s, %l, %w'
|
||||||
|
|
@ -257,6 +286,66 @@ ltl3ba,4,7
|
||||||
|
|
||||||
Much more readable!
|
Much more readable!
|
||||||
|
|
||||||
|
* Shorthands for existing tools
|
||||||
|
|
||||||
|
There is a list of existing tools for which =ltldo= (and =ltlcross=)
|
||||||
|
have built-in specifications. This list can be printed using the
|
||||||
|
=--list-shorthands= option:
|
||||||
|
|
||||||
|
#+BEGIN_SRC sh :results verbatim :exports both
|
||||||
|
ltldo --list-shorthands
|
||||||
|
#+END_SRC
|
||||||
|
#+RESULTS:
|
||||||
|
#+begin_example
|
||||||
|
If a COMMANDFMT does not use any %-sequence, and starts with one of
|
||||||
|
the following words, then the string on the right is appended.
|
||||||
|
|
||||||
|
lbt <%L>%T
|
||||||
|
ltl2ba -f %s>%N
|
||||||
|
ltl2dstar %L %D
|
||||||
|
ltl2tgba -H %f>%H
|
||||||
|
ltl3ba -f %s>%N
|
||||||
|
ltl3dra -f %f>%D
|
||||||
|
modella %L %T
|
||||||
|
spin -f %s>%N
|
||||||
|
#+end_example
|
||||||
|
|
||||||
|
So for instance you can type just
|
||||||
|
|
||||||
|
#+BEGIN_SRC sh :results verbatim :exports both
|
||||||
|
ltldo ltl2ba -f a
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
to obtain a Dot output (this is the default output format for =ltldo=)
|
||||||
|
for the neverclaim produced by =ltl2ba -f a=.
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
: digraph G {
|
||||||
|
: rankdir=LR
|
||||||
|
: I [label="", style=invis, width=0]
|
||||||
|
: I -> 0
|
||||||
|
: 0 [label="0", peripheries=2]
|
||||||
|
: 0 -> 1 [label="a"]
|
||||||
|
: 1 [label="1", peripheries=2]
|
||||||
|
: 1 -> 1 [label="1"]
|
||||||
|
: }
|
||||||
|
|
||||||
|
The =ltl2ba= argument passed to =ltldo= was interpreted as if you had
|
||||||
|
typed ={ltl2ba}ltl2ba -f %s>%N=.
|
||||||
|
|
||||||
|
The shorthand is only used if it is the first word of an command
|
||||||
|
string that does not use any =%= character. This makes it possible to
|
||||||
|
add options:
|
||||||
|
|
||||||
|
#+BEGIN_SRC sh :results verbatim :exports both
|
||||||
|
ltldo ltl3ba 'ltl3ba -H2' -f GFa --stats='%T, %s states, %e edges'
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+RESULTS:
|
||||||
|
: ltl3ba, 2 states, 4 edges
|
||||||
|
: ltl3ba -H2, 1 states, 2 edges
|
||||||
|
|
||||||
|
|
||||||
* Transparent renaming
|
* Transparent renaming
|
||||||
|
|
||||||
Have you ever tried to use =spin=, =ltl2ba=, or =ltl3ba=, to translate
|
Have you ever tried to use =spin=, =ltl2ba=, or =ltl3ba=, to translate
|
||||||
|
|
@ -281,7 +370,7 @@ only atomic propositions starting with a lowercase letter.
|
||||||
Running the same command through =ltldo= will work:
|
Running the same command through =ltldo= will work:
|
||||||
|
|
||||||
#+BEGIN_SRC sh :results verbatim :exports both
|
#+BEGIN_SRC sh :results verbatim :exports both
|
||||||
ltldo -t 'spin -f %s>%N' -f '[]!Error' -s
|
ltldo spin -f '[]!Error' -s
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
#+RESULTS:
|
#+RESULTS:
|
||||||
: never {
|
: never {
|
||||||
|
|
@ -291,6 +380,9 @@ ltldo -t 'spin -f %s>%N' -f '[]!Error' -s
|
||||||
: fi;
|
: fi;
|
||||||
: }
|
: }
|
||||||
|
|
||||||
|
(We need the =-s= option to obtain a never claim, instead of the
|
||||||
|
default GraphViz output.)
|
||||||
|
|
||||||
What happened is that =ltldo= renamed the atomic propositions in the
|
What happened is that =ltldo= renamed the atomic propositions in the
|
||||||
formula before calling =spin=. So =spin= actually received the
|
formula before calling =spin=. So =spin= actually received the
|
||||||
formula =[]!p0=, produced a never claim using =p0=, and that never
|
formula =[]!p0=, produced a never claim using =p0=, and that never
|
||||||
|
|
@ -311,7 +403,7 @@ automaton uses the atomic proposition =Error=, but its name contains a
|
||||||
reference to =p0=.
|
reference to =p0=.
|
||||||
|
|
||||||
#+BEGIN_SRC sh :results verbatim :exports both
|
#+BEGIN_SRC sh :results verbatim :exports both
|
||||||
ltldo 'ltl3ba -H -f %s>%H' -f '[]!Error' -H
|
ltldo 'ltl3ba -H' -f '[]!Error' -H
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
#+RESULTS:
|
#+RESULTS:
|
||||||
#+begin_example
|
#+begin_example
|
||||||
|
|
@ -333,7 +425,7 @@ If this is a problem, you can always force a new name with the
|
||||||
=--name= option:
|
=--name= option:
|
||||||
|
|
||||||
#+BEGIN_SRC sh :results verbatim :exports both
|
#+BEGIN_SRC sh :results verbatim :exports both
|
||||||
ltldo 'ltl3ba -H -f %s>%H' -f '[]!Error' -H --name='BA for %f'
|
ltldo 'ltl3ba -H' -f '[]!Error' -H --name='BA for %f'
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
#+RESULTS:
|
#+RESULTS:
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
|
|
@ -31,12 +32,40 @@
|
||||||
#include "ltlvisit/lbt.hh"
|
#include "ltlvisit/lbt.hh"
|
||||||
#include "common_conv.hh"
|
#include "common_conv.hh"
|
||||||
|
|
||||||
|
// A set of tools for which we know the correct output
|
||||||
|
static struct shorthands_t
|
||||||
|
{
|
||||||
|
const char* prefix;
|
||||||
|
const char* suffix;
|
||||||
|
}
|
||||||
|
shorthands[] = {
|
||||||
|
{ "lbt", " <%L>%T" },
|
||||||
|
{ "ltl2ba", " -f %s>%N" },
|
||||||
|
{ "ltl2dstar", " %L %D"},
|
||||||
|
{ "ltl2tgba", " -H %f>%H" },
|
||||||
|
{ "ltl3ba", " -f %s>%N" },
|
||||||
|
{ "ltl3dra", " -f %f>%D" },
|
||||||
|
{ "modella", " %L %T" },
|
||||||
|
{ "spin", " -f %s>%N" },
|
||||||
|
};
|
||||||
|
|
||||||
|
void show_shorthands()
|
||||||
|
{
|
||||||
|
std::cout
|
||||||
|
<< ("If a COMMANDFMT does not use any %-sequence, and starts with one of\n"
|
||||||
|
"the following words, then the string on the right is appended.\n\n");
|
||||||
|
for (auto& s: shorthands)
|
||||||
|
std::cout << " "
|
||||||
|
<< std::left << std::setw(12) << s.prefix
|
||||||
|
<< s.suffix << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
translator_spec::translator_spec(const char* spec)
|
translator_spec::translator_spec(const char* spec)
|
||||||
: spec(spec), cmd(spec), name(spec)
|
: spec(spec), cmd(spec), name(spec)
|
||||||
{
|
{
|
||||||
if (*cmd != '{')
|
if (*cmd == '{')
|
||||||
return;
|
{
|
||||||
|
|
||||||
// Match the closing '}'
|
// Match the closing '}'
|
||||||
const char* pos = cmd;
|
const char* pos = cmd;
|
||||||
unsigned count = 1;
|
unsigned count = 1;
|
||||||
|
|
@ -55,18 +84,46 @@ translator_spec::translator_spec(const char* spec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If we recognize a shorthand, add the suffixes.
|
||||||
|
bool allocated = false;
|
||||||
|
if (!strchr(cmd, '%'))
|
||||||
|
{
|
||||||
|
for (auto& p: shorthands)
|
||||||
|
{
|
||||||
|
int n = strlen(p.prefix);
|
||||||
|
if (strncmp(cmd, p.prefix, n) == 0 &&
|
||||||
|
(cmd[n] == 0 || cmd[n] == ' '))
|
||||||
|
{
|
||||||
|
int m = strlen(p.suffix);
|
||||||
|
int q = strlen(cmd);
|
||||||
|
char* tmp = static_cast<char*>(malloc(q + m + 1));
|
||||||
|
strcpy(tmp, cmd);
|
||||||
|
strcpy(tmp + q, p.suffix);
|
||||||
|
cmd = tmp;
|
||||||
|
allocated = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!allocated)
|
||||||
|
cmd = strdup(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
translator_spec::translator_spec(const translator_spec& other)
|
translator_spec::translator_spec(const translator_spec& other)
|
||||||
: spec(other.spec), cmd(other.cmd), name(other.name)
|
: spec(other.spec), cmd(other.cmd), name(other.name)
|
||||||
{
|
{
|
||||||
if (name != spec)
|
if (name != spec)
|
||||||
name = strdup(name);
|
name = strdup(name);
|
||||||
|
if (cmd != spec)
|
||||||
|
cmd = strdup(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
translator_spec::~translator_spec()
|
translator_spec::~translator_spec()
|
||||||
{
|
{
|
||||||
if (name != spec)
|
if (name != spec)
|
||||||
free(const_cast<char*>(name));
|
free(const_cast<char*>(name));
|
||||||
|
if (cmd != spec)
|
||||||
|
free(const_cast<char*>(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<translator_spec> translators;
|
std::vector<translator_spec> translators;
|
||||||
|
|
@ -326,6 +383,7 @@ exec_with_timeout(const char* cmd)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define OPT_LIST 1
|
||||||
static const argp_option options[] =
|
static const argp_option options[] =
|
||||||
{
|
{
|
||||||
/**************************************************/
|
/**************************************************/
|
||||||
|
|
@ -333,6 +391,8 @@ static const argp_option options[] =
|
||||||
{ "translator", 't', "COMMANDFMT", 0,
|
{ "translator", 't', "COMMANDFMT", 0,
|
||||||
"register one translator to call", 0 },
|
"register one translator to call", 0 },
|
||||||
{ "timeout", 'T', "NUMBER", 0, "kill translators after NUMBER seconds", 0 },
|
{ "timeout", 'T', "NUMBER", 0, "kill translators after NUMBER seconds", 0 },
|
||||||
|
{ "list-shorthands", OPT_LIST, 0 , 0,
|
||||||
|
"list availabled shorthands to use in COMMANDFMT", 0},
|
||||||
/**************************************************/
|
/**************************************************/
|
||||||
{ 0, 0, 0, 0,
|
{ 0, 0, 0, 0,
|
||||||
"COMMANDFMT should specify input and output arguments using the "
|
"COMMANDFMT should specify input and output arguments using the "
|
||||||
|
|
@ -369,6 +429,9 @@ static int parse_opt_trans(int key, char* arg, struct argp_state*)
|
||||||
<< "on your platform" << std::endl;
|
<< "on your platform" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
case OPT_LIST:
|
||||||
|
show_shorthands();
|
||||||
|
exit(0);
|
||||||
default:
|
default:
|
||||||
return ARGP_ERR_UNKNOWN;
|
return ARGP_ERR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,5 +27,5 @@ genltl=../../bin/genltl
|
||||||
test -n "$LTL2BA" || exit 77
|
test -n "$LTL2BA" || exit 77
|
||||||
|
|
||||||
$genltl --or-g=1..2 |
|
$genltl --or-g=1..2 |
|
||||||
run 0 $ltldo '{ltl2ba}ltl2ba -f %s>%H' >output
|
run 0 $ltldo 'ltl2ba -f %s>%H' '{foo}ltl2ba' >output
|
||||||
test 2 = `grep -c digraph output`
|
test 4 = `grep -c digraph output`
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue