dhall-eta is a eta library that wraps the
haskell implementation
of dhall configuration language with a friendly java api.
Its main goal is to create a language binding to make possible configure java libraries and applications with dhall files.
We already can use eta to compile the dhall haskell implementation
and etlas (a
specific build tool for eta) to install dhall and its tools (dhall-to-json
or
dhall-text)
as java cli applications. However, the classes generated by eta can't
be used directly in java code in a easy way. Hence the need for this library.
- The quick way to explore the java api is use
jshellthe java repl tool present since java 9.- To start a session with the library in the classpath you can do:
> jshell --class-path /path/to/dhall-eta-all-${version}.jarNOTE: The version of java used is openjdk-9.0.4.
- To use the api in your project simply download from last release the
dhall-eta-all-${version}.jarand put it in the project classpath. - The project has an executable class with some more examples.
The main class to compile dhall expressions and get java objects is
the class org.dhall.eta.Input.
- The class has methods to compile simple types and convert them to java:
jshell> import org.dhall.eta.Input
jshell> Input.bool("True")
$2 ==> true
jshell> Input.str("\"This is a dhall Text\"")
$3 ==> "This is a dhall Text"
jshell> Input.bigInt("-1234567890")
$4 ==> -1234567890
jshell> Input.natural("123456789 * 123456789")
$5 ==> Natural [15241578750190521]- Those are shorthands for the main method
Input.type. To use it we need to build aorg.dhall.eta.Type<R>used by the api to extract a java value (of typeR) and typecheck the dhall expression. Methods for basic types are already defined inorg.dhall.eta.Types:
jshell> import org.dhall.eta.Type
jshell> import org.dhall.eta.Types
jshell> Type<Boolean> boolTy = Types.bool()
boolTy ==> eta.org.dhall.eta.Type$Eta@67bf0d91
jshell> Input.type(boolTy, "True && False")
$6 ==> false- The class
org.dhall.eta.Typeshas methods to build standard "container" types asList,OptionalorMap.- For extract a java
Mapfrom a dhall record, we need to build aMapwith the keys and types of the fields expected and then useTypes.objMapto get aType<Map<String, Object>>suitable to use withInput.type:
- For extract a java
jshell> Map<String,Type<? extends Object>> fieldTypes=new HashMap<>();
fieldTypes ==> {}
jshell> fieldTypes.put("name",Types.str());
$9 ==> null
jshell> fieldTypes.put("nats",Types.list(Types.natural()))
$10 ==> null
jshell> Type<Map<String,Object>> mapTy=Types.objMap(FieldTypes.upcast(fieldTypes))
mapTy ==> eta.org.dhall.eta.Type$Eta@35884aff
jshell> Input.type(mapTy, "{ name = \"name\", nats=[1, 2, 3] }")
$11 ==> {name=name, nats=[Natural[1], Natural[2], Natural[3]]}- Of course you can use the api to create an arbitrary java object from dhall code. We should use the generic
Input.typemethod and create the appropiate type:- From a dhall record, using the method
Types.recordand implementingorg.dhall.eta.RecordType- See an example implementation here.
- From a dhall union, using the method
Types.unionand implementingorg.dhall.eta.UnionType- See an example implementation here.
- From arbitrary dhall code implementing the low-level
org.dhall.eta.Typeinterface and using directlyInput.type.
- From a dhall record, using the method
- A more detailed overview of the low level api is coming soon.
- For now we can list the classes that can be used to handle each dhall compiler phase and a link to some example case uses:
- Parsing:
org.dhall.eta.Parser - Resolving imports:
org.dhall.eta.Import - Normalizing and pretty printing:
org.dhall.eta.Core - Typechecking:
org.dhall.eta.TypeCheck - Binary encoding/decoding:
org.dhall.eta.Binary
- Parsing:
-
Download etlas from https://eta-lang.org/docs/user-guides/eta-user-guide/installation/etlas- WARNING: Actually
dhall-etacan only be built usingetaandetlasbuilt themselves from master. We are in the cutting edge!
- WARNING: Actually
-
Run
etlas build --enable-uberjar-modeto compile and generate an uberjar with all dependecies included in./dist/build/eta-${version}/dhall-eta-${version}/x/dhall-eta-all/build/dhall-eta-all/dhall-eta-all.jar- The output jar is not minimized and include an example executable with
etlas run dhall-eta-all
- The output jar is not minimized and include an example executable with
-
Run
etlas testto execute the test suite againstdhall-langacceptance tests- As a previous step you'll need to checkout
dhall-langproject in the same parent directory asdhall-eta - Current dhall standard version supported is
4.0.0and we have to use a fixed version of tests for4.0.0in https://github.com/jneira/dhall-lang - So the command to get them could be (being in the
dhall-etaproject dir):
- As a previous step you'll need to checkout
> git clone --branch v4.0.0 --depth=1 https://github.com/jneira/dhall-lang.git ../dhall-lang- The test suite does not check the validity of
dhall-haskell(and it should not do it!), only that thedhall-haskellimplementation compiled byetaanddhall-etaitself are consistent.
- WARNING: For now, the
gradlebuild is configured to use the system wide versions ofetaandetlasso you will must have them built from source and available inPATH. We are in the cutting edge here too! - This is the preferred method to build the project and the used one to generate the artifacts needed for a release of the library.
- It uses the
gradleplugin for eta and the proguard and shadow ones to generate a minimized jar with all the dependencies included. - It is recommended to use the
gradlewrapper cause the etagradleplugin will likely work with it. - So
./gradlew buildwill generate the following artifacts:- A minimized uberjar ready to be used standalone in
./lib/dhall-eta-${version}-all.jar - An artefact with the objects representing the core business model of dhall. In this one will not be any code for actually parse, normalize o compile dhall code.
- The package root name has not reference to
eta: it is simplyorg.dhall. - The code is in a
gradlesubproject nameddhall-modelin the folder./java - The artifact generated is
./java/build/libs/dhall-model-${version}.jar
- The package root name has not reference to
- An artefact with the java executable example
org.dhall.eta.examples.Client.- The code is in a gradle subproject named
dhall-eta-examplesin the folderexamples - You can run it with
./gradlew run.
- The code is in a gradle subproject named
- A minimized uberjar ready to be used standalone in
