The java-adt package

[Tags:program]

A simple tool to create immutable algebraic data structures and visitors for Java (such as abstract syntax trees). The input syntax is similar to Haskell data types, and they will be compiled to Java class hierarchies.


[Skip to Readme]

Properties

Versions 0.2016.11.28
Dependencies array, base (>=4.2 && <5.0), pretty [details]
License OtherLicense
Author Andreas Abel
Maintainer Andreas Abel <andreas.abel@ifi.lmu.de>
Category Java
Home page http://github.com/andreasabel/java-adt
Bug tracker http://github.com/andreasabel/java-adt/issues
Source repository head: git clone http://github.com/andreasabel/java-adt.git
Uploaded Mon Nov 28 17:09:22 UTC 2016 by AndreasAbel
Distributions NixOS:0.2016.11.28
Downloads 75 total (9 in the last 30 days)
Votes
0 []
Status Docs not available [build log]
Last success reported on 2016-11-28 [all 2 reports]
Hackage Matrix CI

Downloads

Maintainer's Corner

For package maintainers and hackage trustees

Readme for java-adt

Readme for java-adt-0.2016.11.28

java-adt

A tool to create immutable algebraic data structures and visitors for Java (such as abstract syntax trees). The input syntax is similar to Haskell data types, and they will be compiled to Java class hierarchies.

Installation

cabal install alex happy java-adt

Example 1: Immutable linked lists with default visitor

Input: List.hs

data List A = Nil | Cons { head :: A, tail :: List A }

Invokation java-adt List.hs prints to standard output:

abstract class List<A> {
}

class Nil<A> extends List<A> {
    public Nil () {
    }
}

class Cons<A> extends List<A> {
    public A head;
    public List<A> tail;
    public Cons (A head, List<A> tail) {
        this.head = head;
        this.tail = tail;
    }
}

Invokation: java-adt -o List.java List.hs leaves output in List.java.

Invokation: java-adt -d List.hs outputs same but with default visitor on standard output:

abstract class List<A> {
    public abstract <R> R accept (ListVisitor<R,A> v);
}

class Nil<A> extends List<A> {
    public Nil () {
    }
    public <R> R accept (ListVisitor<R,A> v) {
        return v.visit (this);
    }
}

class Cons<A> extends List<A> {
    public A head;
    public List<A> tail;
    public Cons (A head, List<A> tail) {
        this.head = head;
        this.tail = tail;
    }
    public <R> R accept (ListVisitor<R,A> v) {
        return v.visit (this);
    }
}

interface ListVisitor<R,A> {
    public R visit (Nil<A> l);
    public R visit (Cons<A> l);
}

Example 2: A simple AST with custom visitor

Input file Exp.hs: (Note the use of Haskell lists in [Exp])

data Exp
  = EInt  { i :: Integer }
  | EAdd  { e1 :: Exp, e2 :: Exp }
  | ECall { f :: String, es :: [Exp] }
--visitor Integer EvalVisitor

Invokation java-ast -o Exp.java Exp.hs outputs into Exp.java:

import java.util.List;

abstract class Exp {
    public abstract Integer accept (EvalVisitor v);
}

class EInt extends Exp {
    public Integer i;
    public EInt (Integer i) {
        this.i = i;
    }
    public Integer accept (EvalVisitor v) {
        return v.visit (this);
    }
}

class EAdd extends Exp {
    public Exp e1;
    public Exp e2;
    public EAdd (Exp e1, Exp e2) {
        this.e1 = e1;
        this.e2 = e2;
    }
    public Integer accept (EvalVisitor v) {
        return v.visit (this);
    }
}

class ECall extends Exp {
    public String f;
    public List<Exp> es;
    public ECall (String f, List<Exp> es) {
        this.f = f;
        this.es = es;
    }
    public Integer accept (EvalVisitor v) {
        return v.visit (this);
    }
}

interface EvalVisitor {
    public Integer visit (EInt e);
    public Integer visit (EAdd e);
    public Integer visit (ECall e);
}

Input file grammar

The input file format is similar to Haskell data type declarations, with the special comment --visitor.

  datadecl    ::= 'data' uppername '=' constructors visitors

  constructor ::= uppername ['{' fieldlist '}']

  fieldlist   ::= fieldlist ',' field
                | field

  field       ::= lowername '::' type

  type        ::= type atom
                | atom

  atom        ::= name
                | '[' type ']'
                | '(' type ')'

  visitor     ::= '--visitor' type name

Limitations

  • Visitors do not support mutually recursive data types.
  • Record types with same constructor name as record name do not produce valid Java. E.g.
    data R = R { f :: A }
    
    creates two classes with name R.