src/Pure/library.scala
changeset 75393 87ebf5a50283
parent 75382 81673c441ce3
child 75709 a068fb7346ef
equal deleted inserted replaced
75388:b3ca4a6ed74b 75393:87ebf5a50283
    10 import scala.annotation.tailrec
    10 import scala.annotation.tailrec
    11 import scala.collection.mutable
    11 import scala.collection.mutable
    12 import scala.util.matching.Regex
    12 import scala.util.matching.Regex
    13 
    13 
    14 
    14 
    15 object Library
    15 object Library {
    16 {
       
    17   /* resource management */
    16   /* resource management */
    18 
    17 
    19   def using[A <: AutoCloseable, B](a: A)(f: A => B): B =
    18   def using[A <: AutoCloseable, B](a: A)(f: A => B): B = {
    20   {
       
    21     try { f(a) }
    19     try { f(a) }
    22     finally { if (a != null) a.close() }
    20     finally { if (a != null) a.close() }
    23   }
    21   }
    24 
    22 
    25 
    23 
    26   /* integers */
    24   /* integers */
    27 
    25 
    28   private val small_int = 10000
    26   private val small_int = 10000
    29   private lazy val small_int_table =
    27   private lazy val small_int_table = {
    30   {
       
    31     val array = new Array[String](small_int)
    28     val array = new Array[String](small_int)
    32     for (i <- 0 until small_int) array(i) = i.toString
    29     for (i <- 0 until small_int) array(i) = i.toString
    33     array
    30     array
    34   }
    31   }
    35 
    32 
    36   def is_small_int(s: String): Boolean =
    33   def is_small_int(s: String): Boolean = {
    37   {
       
    38     val len = s.length
    34     val len = s.length
    39     1 <= len && len <= 4 &&
    35     1 <= len && len <= 4 &&
    40     s.forall(c => '0' <= c && c <= '9') &&
    36     s.forall(c => '0' <= c && c <= '9') &&
    41     (len == 1 || s(0) != '0')
    37     (len == 1 || s(0) != '0')
    42   }
    38   }
    50     else i.toString
    46     else i.toString
    51 
    47 
    52 
    48 
    53   /* separated chunks */
    49   /* separated chunks */
    54 
    50 
    55   def separate[A](s: A, list: List[A]): List[A] =
    51   def separate[A](s: A, list: List[A]): List[A] = {
    56   {
       
    57     val result = new mutable.ListBuffer[A]
    52     val result = new mutable.ListBuffer[A]
    58     var first = true
    53     var first = true
    59     for (x <- list) {
    54     for (x <- list) {
    60       if (first) {
    55       if (first) {
    61         first = false
    56         first = false
    70   }
    65   }
    71 
    66 
    72   def separated_chunks(sep: Char => Boolean, source: CharSequence): Iterator[CharSequence] =
    67   def separated_chunks(sep: Char => Boolean, source: CharSequence): Iterator[CharSequence] =
    73     new Iterator[CharSequence] {
    68     new Iterator[CharSequence] {
    74       private val end = source.length
    69       private val end = source.length
    75       private def next_chunk(i: Int): Option[(CharSequence, Int)] =
    70       private def next_chunk(i: Int): Option[(CharSequence, Int)] = {
    76       {
       
    77         if (i < end) {
    71         if (i < end) {
    78           var j = i
    72           var j = i
    79           var cont = true
    73           var cont = true
    80           while (cont) {
    74           while (cont) {
    81             j += 1
    75             j += 1
   113     isabelle.setup.Library.prefix_lines(prfx, str)
   107     isabelle.setup.Library.prefix_lines(prfx, str)
   114 
   108 
   115   def indent_lines(n: Int, str: String): String =
   109   def indent_lines(n: Int, str: String): String =
   116     prefix_lines(Symbol.spaces(n), str)
   110     prefix_lines(Symbol.spaces(n), str)
   117 
   111 
   118   def first_line(source: CharSequence): String =
   112   def first_line(source: CharSequence): String = {
   119   {
       
   120     val lines = separated_chunks(_ == '\n', source)
   113     val lines = separated_chunks(_ == '\n', source)
   121     if (lines.hasNext) lines.next().toString
   114     if (lines.hasNext) lines.next().toString
   122     else ""
   115     else ""
   123   }
   116   }
   124 
   117 
   132   def decode_lines(s: String): String = s.replace('\u000b', '\n')
   125   def decode_lines(s: String): String = s.replace('\u000b', '\n')
   133 
   126 
   134 
   127 
   135   /* strings */
   128   /* strings */
   136 
   129 
   137   def make_string(f: StringBuilder => Unit, capacity: Int = 16): String =
   130   def make_string(f: StringBuilder => Unit, capacity: Int = 16): String = {
   138   {
       
   139     val s = new StringBuilder(capacity)
   131     val s = new StringBuilder(capacity)
   140     f(s)
   132     f(s)
   141     s.toString
   133     s.toString
   142   }
   134   }
   143 
   135 
   172   def commas_quote(ss: Iterable[String]): String = ss.iterator.map(quote).mkString(", ")
   164   def commas_quote(ss: Iterable[String]): String = ss.iterator.map(quote).mkString(", ")
   173 
   165 
   174 
   166 
   175   /* CharSequence */
   167   /* CharSequence */
   176 
   168 
   177   class Reverse(text: CharSequence, start: Int, end: Int) extends CharSequence
   169   class Reverse(text: CharSequence, start: Int, end: Int) extends CharSequence {
   178   {
       
   179     require(0 <= start && start <= end && end <= text.length, "bad reverse range")
   170     require(0 <= start && start <= end && end <= text.length, "bad reverse range")
   180 
   171 
   181     def this(text: CharSequence) = this(text, 0, text.length)
   172     def this(text: CharSequence) = this(text, 0, text.length)
   182 
   173 
   183     def length: Int = end - start
   174     def length: Int = end - start
   185 
   176 
   186     def subSequence(i: Int, j: Int): CharSequence =
   177     def subSequence(i: Int, j: Int): CharSequence =
   187       if (0 <= i && i <= j && j <= length) new Reverse(text, end - j, end - i)
   178       if (0 <= i && i <= j && j <= length) new Reverse(text, end - j, end - i)
   188       else throw new IndexOutOfBoundsException
   179       else throw new IndexOutOfBoundsException
   189 
   180 
   190     override def toString: String =
   181     override def toString: String = {
   191     {
       
   192       val buf = new StringBuilder(length)
   182       val buf = new StringBuilder(length)
   193       for (i <- 0 until length)
   183       for (i <- 0 until length)
   194         buf.append(charAt(i))
   184         buf.append(charAt(i))
   195       buf.toString
   185       buf.toString
   196     }
   186     }
   197   }
   187   }
   198 
   188 
   199   class Line_Termination(text: CharSequence) extends CharSequence
   189   class Line_Termination(text: CharSequence) extends CharSequence {
   200   {
       
   201     def length: Int = text.length + 1
   190     def length: Int = text.length + 1
   202     def charAt(i: Int): Char = if (i == text.length) '\n' else text.charAt(i)
   191     def charAt(i: Int): Char = if (i == text.length) '\n' else text.charAt(i)
   203     def subSequence(i: Int, j: Int): CharSequence =
   192     def subSequence(i: Int, j: Int): CharSequence =
   204       if (j == text.length + 1) new Line_Termination(text.subSequence(i, j - 1))
   193       if (j == text.length + 1) new Line_Termination(text.subSequence(i, j - 1))
   205       else text.subSequence(i, j)
   194       else text.subSequence(i, j)
   225   /* lists */
   214   /* lists */
   226 
   215 
   227   def take_prefix[A](pred: A => Boolean, xs: List[A]): (List[A], List[A]) =
   216   def take_prefix[A](pred: A => Boolean, xs: List[A]): (List[A], List[A]) =
   228     (xs.takeWhile(pred), xs.dropWhile(pred))
   217     (xs.takeWhile(pred), xs.dropWhile(pred))
   229 
   218 
   230   def take_suffix[A](pred: A => Boolean, xs: List[A]): (List[A], List[A]) =
   219   def take_suffix[A](pred: A => Boolean, xs: List[A]): (List[A], List[A]) = {
   231   {
       
   232     val rev_xs = xs.reverse
   220     val rev_xs = xs.reverse
   233     (rev_xs.dropWhile(pred).reverse, rev_xs.takeWhile(pred).reverse)
   221     (rev_xs.dropWhile(pred).reverse, rev_xs.takeWhile(pred).reverse)
   234   }
   222   }
   235 
   223 
   236   def trim[A](pred: A => Boolean, xs: List[A]): List[A] =
   224   def trim[A](pred: A => Boolean, xs: List[A]): List[A] =
   244   def merge[A](xs: List[A], ys: List[A]): List[A] =
   232   def merge[A](xs: List[A], ys: List[A]): List[A] =
   245     if (xs.eq(ys)) xs
   233     if (xs.eq(ys)) xs
   246     else if (xs.isEmpty) ys
   234     else if (xs.isEmpty) ys
   247     else ys.foldRight(xs)(Library.insert(_)(_))
   235     else ys.foldRight(xs)(Library.insert(_)(_))
   248 
   236 
   249   def distinct[A](xs: List[A], eq: (A, A) => Boolean = (x: A, y: A) => x == y): List[A] =
   237   def distinct[A](xs: List[A], eq: (A, A) => Boolean = (x: A, y: A) => x == y): List[A] = {
   250   {
       
   251     val result = new mutable.ListBuffer[A]
   238     val result = new mutable.ListBuffer[A]
   252     xs.foreach(x => if (!result.exists(y => eq(x, y))) result += x)
   239     xs.foreach(x => if (!result.exists(y => eq(x, y))) result += x)
   253     result.toList
   240     result.toList
   254   }
   241   }
   255 
   242 
   256   def duplicates[A](lst: List[A], eq: (A, A) => Boolean = (x: A, y: A) => x == y): List[A] =
   243   def duplicates[A](lst: List[A], eq: (A, A) => Boolean = (x: A, y: A) => x == y): List[A] = {
   257   {
       
   258     val result = new mutable.ListBuffer[A]
   244     val result = new mutable.ListBuffer[A]
   259     @tailrec def dups(rest: List[A]): Unit =
   245     @tailrec def dups(rest: List[A]): Unit =
   260       rest match {
   246       rest match {
   261         case Nil =>
   247         case Nil =>
   262         case x :: xs =>
   248         case x :: xs =>
   295     if (list == null || list.isEmpty) None else Some(list)
   281     if (list == null || list.isEmpty) None else Some(list)
   296 
   282 
   297 
   283 
   298   /* reflection */
   284   /* reflection */
   299 
   285 
   300   def is_subclass[A, B](a: Class[A], b: Class[B]): Boolean =
   286   def is_subclass[A, B](a: Class[A], b: Class[B]): Boolean = {
   301   {
       
   302     import scala.language.existentials
   287     import scala.language.existentials
   303     @tailrec def subclass(c: Class[_]): Boolean =
   288     @tailrec def subclass(c: Class[_]): Boolean = {
   304     {
   289       c == b || { val d = c.getSuperclass; d != null && subclass(d) }
   305       c == b ||
       
   306         {
       
   307           val d = c.getSuperclass
       
   308           d != null && subclass(d)
       
   309         }
       
   310     }
   290     }
   311     subclass(a)
   291     subclass(a)
   312   }
   292   }
   313 }
   293 }