src/HOL/Tools/Nitpick/kodkod.scala
author wenzelm
Thu, 20 Aug 2020 14:22:49 +0200
changeset 72179 0841895ca438
parent 72178 2481cdb84832
child 72181 6241cbbf5a58
permissions -rw-r--r--
clarified signature;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
72176
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
     1
/*  Title:      HOL/Tools/Nitpick/kodkod.scala
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
     3
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
     4
Scala interface for Kodkod.
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
     5
*/
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
     6
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
     7
package isabelle.nitpick
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
     8
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
     9
import isabelle._
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
    10
72177
fbaa6b40b439 update to kodkodi-1.5.4;
wenzelm
parents: 72176
diff changeset
    11
import java.util.concurrent.Executors
fbaa6b40b439 update to kodkodi-1.5.4;
wenzelm
parents: 72176
diff changeset
    12
72178
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    13
import org.antlr.runtime.{ANTLRInputStream, RecognitionException}
72177
fbaa6b40b439 update to kodkodi-1.5.4;
wenzelm
parents: 72176
diff changeset
    14
import de.tum.in.isabelle.Kodkodi.{Context, KodkodiLexer, KodkodiParser}
72176
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
    15
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
    16
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
    17
object Kodkod
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
    18
{
72178
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    19
  sealed case class Result(rc: Int, out: String, err: String)
72179
0841895ca438 clarified signature;
wenzelm
parents: 72178
diff changeset
    20
  {
0841895ca438 clarified signature;
wenzelm
parents: 72178
diff changeset
    21
    def ok: Boolean = rc == 0
0841895ca438 clarified signature;
wenzelm
parents: 72178
diff changeset
    22
    def check: String =
0841895ca438 clarified signature;
wenzelm
parents: 72178
diff changeset
    23
      if (ok) out else error(if (err.isEmpty) "Error" else err)
0841895ca438 clarified signature;
wenzelm
parents: 72178
diff changeset
    24
  }
72178
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    25
72179
0841895ca438 clarified signature;
wenzelm
parents: 72178
diff changeset
    26
  def execute(source: String,
72176
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
    27
    solve_all: Boolean = false,
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
    28
    prove: Boolean = false,
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
    29
    max_solutions: Int = Integer.MAX_VALUE,
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
    30
    cleanup_inst: Boolean = false,
72178
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    31
    timeout: Time = Time.zero,
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    32
    max_threads: Int = 1): Result =
72176
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
    33
  {
72178
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    34
    val executor = Executors.newFixedThreadPool(max_threads)
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    35
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    36
    def executor_kill(): Unit =
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    37
      if (!executor.isShutdown) Isabelle_Thread.fork() { executor.shutdownNow() }
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    38
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    39
    class Exit extends Exception
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    40
72177
fbaa6b40b439 update to kodkodi-1.5.4;
wenzelm
parents: 72176
diff changeset
    41
    val context =
fbaa6b40b439 update to kodkodi-1.5.4;
wenzelm
parents: 72176
diff changeset
    42
      new Context {
72178
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    43
        private var rc = 0
72177
fbaa6b40b439 update to kodkodi-1.5.4;
wenzelm
parents: 72176
diff changeset
    44
        private val out = new StringBuilder
fbaa6b40b439 update to kodkodi-1.5.4;
wenzelm
parents: 72176
diff changeset
    45
        private val err = new StringBuilder
72178
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    46
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    47
        def return_code(i: Int): Unit = synchronized { rc = rc max i}
72177
fbaa6b40b439 update to kodkodi-1.5.4;
wenzelm
parents: 72176
diff changeset
    48
        override def output(s: String): Unit = synchronized { out ++= s; out += '\n' }
fbaa6b40b439 update to kodkodi-1.5.4;
wenzelm
parents: 72176
diff changeset
    49
        override def error(s: String): Unit = synchronized { err ++= s; err += '\n' }
72178
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    50
        override def exit(i: Int): Unit =
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    51
          synchronized {
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    52
            return_code(i)
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    53
            executor_kill()
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    54
            throw new Exit
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    55
          }
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    56
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    57
        def result(): Result = synchronized { Result(rc, out.toString, err.toString) }
72177
fbaa6b40b439 update to kodkodi-1.5.4;
wenzelm
parents: 72176
diff changeset
    58
      }
72178
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    59
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    60
    try {
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    61
      val lexer = new KodkodiLexer(new ANTLRInputStream(Bytes(source).stream))
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    62
      val parser =
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    63
        KodkodiParser.create(context, executor,
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    64
          false, solve_all, prove, max_solutions, cleanup_inst, lexer)
72176
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
    65
72178
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    66
      val timeout_request =
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    67
        if (timeout.is_zero) None
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    68
        else {
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    69
          Some(Event_Timer.request(Time.now() + timeout) {
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    70
            context.error("Ran out of time")
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    71
            context.return_code(2)
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    72
            executor_kill()
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    73
          })
72177
fbaa6b40b439 update to kodkodi-1.5.4;
wenzelm
parents: 72176
diff changeset
    74
        }
72178
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    75
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    76
      try { parser.problems() }
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    77
      catch { case exn: RecognitionException => parser.reportError(exn) }
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    78
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    79
      timeout_request.foreach(_.cancel)
72177
fbaa6b40b439 update to kodkodi-1.5.4;
wenzelm
parents: 72176
diff changeset
    80
72178
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    81
      if (parser.getTokenStream.LA(1) != KodkodiParser.EOF) {
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    82
        context.error("Error: trailing tokens")
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    83
        context.exit(1)
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    84
      }
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    85
      if (lexer.getNumberOfSyntaxErrors + parser.getNumberOfSyntaxErrors > 0) {
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    86
        context.exit(1)
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    87
      }
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    88
    }
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    89
    catch {
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    90
      case _: Exit =>
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    91
      case exn: Throwable =>
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    92
        val message = exn.getMessage
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    93
        context.error(if (message.isEmpty) exn.toString else "Error: " + message)
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    94
        context.return_code(1)
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    95
    }
72177
fbaa6b40b439 update to kodkodi-1.5.4;
wenzelm
parents: 72176
diff changeset
    96
72178
2481cdb84832 more realistic kodkod invocation, imitating command-line tool;
wenzelm
parents: 72177
diff changeset
    97
    context.result()
72176
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
    98
  }
72179
0841895ca438 clarified signature;
wenzelm
parents: 72178
diff changeset
    99
0841895ca438 clarified signature;
wenzelm
parents: 72178
diff changeset
   100
  def warmup(): String =
0841895ca438 clarified signature;
wenzelm
parents: 72178
diff changeset
   101
    execute(File.read(Path.explode("$KODKODI/examples/weber3.kki"))).check
72176
22c11f65ddf9 rudiments of Scala interface for Kodkod;
wenzelm
parents:
diff changeset
   102
}