Stat
Stat
The :tools:stat module measures how much and what kind of specification a
project has. It walks every declaration and contract, counts the JML constructs
(clauses, modifiers, behaviors, binders, class expressions) and estimates the
cost of specification terms — the numbers VCG users care about when scaling
verification effort.
Counters
The core is a keyed, hierarchical Statistics accumulator:
data class Statistics(
val data: MutableMap<StatisticKey<*>, Any>, // keyed counts
val children: MutableList<Statistics>, // per-node subtrees
) {
operator fun get(key: JmlClauseKind) // e.g. Statistics()[JmlClauseKind.REQUIRES]
operator fun get(key: String) // e.g. "requires"
fun inc(key: StatisticKey<*>) // increment-many helper
fun subStat(n: Node) // attach a subtree to an AST node
fun summary(): Statistics // aggregate children into a total
operator fun plus(x: Statistics) // fold two trees
}Keys are registered per name in StatisticKeys (clauses become
CLAUSE_<KIND>, modifiers MODIFIER_<KEYWORD>, plus BEHAVIOR_, BINDER_
and CLASS_ keys); string lookups are normalized (\result → RESULT).
JmlStatisticsReporter visits a CompilationUnit and increments the right
counters; ExpressionCosts assigns a cost to each expression node.
CLI
jmltk stat [-t TEXT|JSON|CSV|XML] [-c COLUMN ...] [--jml-key KEY] FILE|DIR ...-t/--target— output format;TEXTprints an indented per-unit table (TOTALfirst, then oneCblock per compilation unit,Tper type,cper constructor/method),XMLemits astatistics-modeldocument built by the legacyStatVisitor;JSON/CSVare declared but not yet wired.-c/--column— restrict output to the named statistic keys (repeatable).- files and directories are accepted; directories are scanned recursively for
*.java. JML parsing uses theKEYkey set when--jml-keyis absent.
Library usage
val statistics = Statistics()
val reporter = JmlStatisticsReporter()
for (node: CompilationUnit in units) reporter.visit(node, statistics)
val requiresCount: Int = statistics[JmlClauseKind.REQUIRES]
val totalClauses: Int = statistics[JmlClauseKind.REQUIRES] // per-kind view
val txt = StatisticsTxtOutput(PrintWriter(System.out), selectedColumns).also {
it.start(); it.run(statistics, units); it.end()
}