Quick start
This page takes about ten minutes. You write one .sou file, run a behavior in it, read what the example rows cover, and then start a Maven project. It needs the souther command from Installation and nothing else. Maven is needed only for the last step.
-
Write a model
Section titled “Write a model”Create a directory and put this file in it as
claim.sou. It models an expense claim desk. A claim up to 500 is approved on the spot, and a larger one goes to review.data Amount = Intinvariant value >= 0data Approved ={ amount: Amount}data NeedsReview ={ amount: Amount}behavior claim : (amount: Amount) -> Approved | NeedsReviewconstructs Approved, NeedsReviewlet claim (amount) = {guard amount <= 500 else NeedsReview { amount = amount }Approved { amount = amount }}example claim| "a small claim" : (Amount(120)) -> Approved { amount = Amount(120) }| "at the limit" : (Amount(500)) -> Approved { amount = Amount(500) }| "over the limit" : (Amount(501)) -> NeedsReview { amount = Amount(501) }Amountis a newtype overIntwith aninvariant. NoAmountbelow zero can exist anywhere in the program, because every construction checks the rule.claimis abehaviorwhose output is a sum of two cases. Theguardreturns theNeedsReviewcase and stops when its condition is false. Theexamplerows are checked on every compile. A single file needs nomoduleheader. It is named after the file. -
Run a behavior
Section titled “Run a behavior”souther runcompiles the file in memory, decodes--inputas JSON, applies the behavior and prints the output as JSON. The file holds one behavior, so--behaviorcan be left out.Terminal window souther run claim.sou --input '120'{"amount":120,"type":"Approved"}Terminal window souther run claim.sou --input '900'{"amount":900,"type":"NeedsReview"}Now give it an input the model refuses:
Terminal window souther run claim.sou --input '-5'input #1 could not be decoded — (root): must be non-negativeThe behavior never ran. The derived decoder checks the invariant of
Amountat the boundary and reports the failure, so the body ofclaimonly ever sees a validAmount. The exit code is 1. -
Read the coverage report
Section titled “Read the coverage report”souther examplesreports what theexamplerows reach and what they do not:Terminal window souther examples claim.souclaim measurement: completeclaim implemented rows 3 pending 0signature out specified 2/2 observed 2/2 verified 2/2partition axes 1 equivalence partitions 2/2border borders 2 obligations 4/5! no row is at an OUT point (comparison@15:18)· read as claim/amount: in 501 < amount· no OFF point is owed at amount = 0 (invariant Amount #1): excluded — the rules leave no value there· no OUT point is owed at amount = 0 (invariant Amount #1): excluded — the rules leave no value therebranch 2/2decision rules 2 taken 2replacement 2/2declarations obligations 0/1Amount! no row is at the ON point value = 0 (invariant Amount #1)1 behavior: 1 implemented, 0 unimplemented, 0 injected; 0 rows waiting for a `let`.adequacy: not satisfied2 gaps marked `!`: what a strict build refuses over.The
partitionline says the guard divides the input into two classes, and a row stands in each. Theborderlines list the values each rule places on a boundary. The guard at line 15 has rows on 500 and 501, but no row well past it, and the invariant ofAmounthas no row at 0. Thedecisionline says both rules of the body were taken by some row. Theadequacyline is the verdict over all of this, and the two gaps marked!are whatsouther examples --strictrefuses the build over. Add a row forAmount(0)and one for a value such asAmount(2000), run the report again, and both gaps close. -
Start a project
Section titled “Start a project”For a model that Java code will call,
souther initwrites a Maven project. It takes a group and an artifact as one coordinate:Terminal window souther init com.example:hellocreated hello/pom.xmlcreated hello/.gitignorecreated hello/src/main/souther/hello.soumodule com.example.hellocd hello && mvn compileThe
pom.xmldeclaressouther-runtimeand the Souther Maven plugin, andhello.souholds a small library-desk model with itsexamplerows. Compile it:Terminal window cd hello && mvn compile[INFO] --- souther:0.1.0:compile (default) @ hello ---[INFO][INFO] --- resources:3.4.0:resources (default-resources) @ hello ---[INFO] skip non existing resourceDirectory /Users/you/hello/src/main/resources[INFO][INFO] --- compiler:3.15.0:compile (default-compile) @ hello ---[INFO] No sources to compile[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------The plugin compiles
src/main/southerintotarget/classes, and theexamplerows are checked as part of that compile. The generated classes are ordinary Java 25 records and interfaces that Java and Kotlin code can use.souther init com.example:hello --build gradlewrites a Gradle build instead and tells you to rungradle wrapperfirst.souther init --build nonewrites only the source and a.souther-versionfile, for a project that compiles withsouther compile --targetand has no Java build. -
Next steps
Section titled “Next steps”- Tutorial: build a business-trip approval model and close its coverage gaps one report at a time.
- Language tour: the whole language on one page.
- Java: call the generated classes from Java.

