aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/options/Shell.scala
blob: 4fb8945094cbcf76ce9ac5895c2cd99cd4e365b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// See LICENSE for license details.

package firrtl.options

import firrtl.AnnotationSeq

import scopt.OptionParser

import java.util.ServiceLoader

/** Indicate an error in [[firrtl.options]]
  * @param msg a message to print
  */
case class OptionsException(msg: String, cause: Throwable = null) extends Exception(msg, cause)

/** A utility for working with command line options
  * @param applicationName the application associated with these command line options
  */
class Shell(val applicationName: String) {

  /** Command line argument parser (OptionParser) with modifications */
  final val parser = new OptionParser[AnnotationSeq](applicationName) with DuplicateHandling

  /** Contains all discovered [[RegisteredLibrary]] */
  lazy val registeredLibraries: Seq[RegisteredLibrary] = {
    val libraries = scala.collection.mutable.ArrayBuffer[RegisteredLibrary]()
    val iter = ServiceLoader.load(classOf[RegisteredLibrary]).iterator()
    while (iter.hasNext) {
      val lib = iter.next()
      libraries += lib
      parser.note(lib.name)
      lib.addOptions(parser)
    }
    libraries
  }

  /** Contains all discovered [[RegisteredTransform]] */
  lazy val registeredTransforms: Seq[RegisteredTransform] = {
    val transforms = scala.collection.mutable.ArrayBuffer[RegisteredTransform]()
    val iter = ServiceLoader.load(classOf[RegisteredTransform]).iterator()
    parser.note("FIRRTL Transform Options")
    while (iter.hasNext) {
      val tx = iter.next()
      transforms += tx
      tx.addOptions(parser)
    }
    transforms
  }

  /** The [[AnnotationSeq]] generated from command line arguments
    *
    * This requires lazy evaluation as subclasses will mixin new command
    * line options via methods of [[Shell.parser]]
    */
  def parse(args: Array[String], initAnnos: AnnotationSeq = Seq.empty): AnnotationSeq = {
    registeredTransforms
    registeredLibraries
    parser
      .parse(args, initAnnos)
      .getOrElse(throw new OptionsException("Failed to parse command line options", new IllegalArgumentException))
  }

  parser.note("Shell Options")
  Seq( InputAnnotationFileAnnotation(),
       TargetDirAnnotation() )
    .map(_.addOptions(parser))
}