{-# LANGUAGE DeriveFoldable #-}
{- |
Example: (only ground inductive types)
@
data D = C1 { x1 :: D1, ..., xn ::Dn }
| C2 ...
...
@
is printed as
@
public abstract class D {}
public class C1 extends D {
public D1 x1;
...
public Dn xn;
public C1 (D1 x1, ..., Dn xn) {
this.x1 = x1;
...
this xn = xn;
}
}
@
@
data D = C1 { x1 :: D1, ..., xn ::Dn }
| C2 ...
...
--visitor E1 V1
--visitor E2 V2
@
is printed as
@
class D {
public E1 accept (V1 v) {
return v.visit (this);
}
public E2 accept (V2 v) {
return v.visit (this);
}
}
class C1 extends D {
public D1 x1;
...
public Dn xn;
public C1 (D1 x1, ..., Dn xn) {
this.x1 = x1;
...
this xn = xn;
}
}
@
the visitor interface is created as follows
@
interface V1 {
public E1 visit (C1 x);
public E1 visit (C2 x);
...
}
@
Example:
@
data List a = Nil | Cons { head :: a, tail :: List a }
@
becomes
@
abstract class List {}
class Nil extends List {
Nil () {}
}
class Cons extends List {
public a head;
public List tail;
Cons (a head, List tail) {
this.head = head;
this.tail = tail;
}
}
@
Grammar:
@
datadecl :: 'data' uppername '=' constructors visitors
constructor :: uppername [fields]
fields :: '{' fieldlist '}'
fieldlist :: fieldlist ',' field
| field
field :: lowername '::' type
type :: type atom
| atom
atom :: name
| '[' type ']'
| '(' type ')
visitor :: '--visitor' name name
@
-}
module Syntax where
import Data.Foldable
import Data.Monoid
type FieldId = String
type ConstrId = String
type DataId = String
type Param = String
type ClassId = String
data TypeId
= TypeId String
| Gen String -- ^ Type variable.
deriving (Eq, Show)
data Visitor = Visitor
{ name :: ClassId
, returnType :: TypeId
} deriving Show
data Type
= List Type -- ^ @List@
| App Type Type -- ^ @Type@
| Name String -- ^ @Type@
deriving (Eq, Show)
data Field' a = Field
{ fieldId :: FieldId
, fieldType :: a
} deriving (Show, Foldable)
data Constructor' a = Constructor
{ constrId :: ConstrId
, constrFields :: [Field' a]
} deriving (Show, Foldable)
data Data' a = Data
{ dataId :: DataId
, dataParams :: [Param]
, dataConstructors :: [Constructor' a]
, dataVisitors :: [Visitor]
} deriving (Show, Foldable)
type Field = Field' Type
type Constructor = Constructor' Type
type Data = Data' Type
usesList :: Foldable f => f Type -> Bool
usesList = getAny . foldMap (Any . isList)
where
isList :: Type -> Bool
isList (List _) = True
isList _ = False