%if false  
  Copyright (c) 2009, ETH Zurich.
  All rights reserved.
  
  This file is distributed under the terms in the attached LICENSE file.
  If you do not find this file, copies can be found by writing to:
  ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
%endif

%include polycode.fmt

%if false

> module Constructs where

> import PureExpressions
> import Semantics

%endif


\section{Filet-o-Fish standard constructs}
\label{sec:fof_syntax_constructs}


The FoF language is defined by the syntax tree below. It gathers every
constructs defined in the |Constructs| directory as well as foreign
functions defined in the |Libc| and |Libbarrelfish| directories.


> data FoFConst a 

Foreign-call to libc Assert:

>     = Assert PureExpr a

Foreign-call to libc Printf:

>     | Printf String [PureExpr] a

Foreign-call to libarrelfish |has_descendants|:

>     | HasDescendants (Maybe String) PureExpr (PureExpr -> a)

Foreign-call to libarrelfish |mem_to_phys|:

>     | MemToPhys (Maybe String) PureExpr (PureExpr -> a)

Foreign-call to Hamlet |get_address|:

>     | GetAddress (Maybe String) PureExpr (PureExpr -> a)

Support for Union:

>     | NewUnion (Maybe String) AllocUnion String [(String,TypeExpr)] (String, Data) (Loc -> a)
>     | ReadUnion Loc String (Data -> a)
>     | WriteUnion Loc String Data a

Support for Typedef:

>     | Typedef TypeExpr a
>     | TypedefE String TypeExpr a

Support for Structures:

>     | NewStruct (Maybe String) AllocStruct String [(String,(TypeExpr,Data))] (Loc -> a)
>     | ReadStruct Loc String (Data -> a)
>     | WriteStruct Loc String Data a

Support for Strings:

>     | NewString (Maybe String) String (Loc -> a)

Support for Reference cells:

>      | NewRef (Maybe String) Data (Loc -> a)
>      | ReadRef Loc (Data -> a)
>      | WriteRef Loc Data a

Support for Functions:

>      | NewDef [FunAttr] String Function TypeExpr [(TypeExpr, Maybe String)] 
>               (PureExpr -> a)
>      | CallDef (Maybe String) PureExpr [PureExpr] 
>                (PureExpr -> a)
>      | Return PureExpr

Support for Enumerations:

>      | NewEnum (Maybe String) String Enumeration String (Loc -> a)

Support for Conditionals:

>      | If (FoFCode PureExpr)
>           (FoFCode PureExpr) 
>           (FoFCode PureExpr) a
>      | For (FoFCode PureExpr)  
>            (FoFCode PureExpr) 
>            (FoFCode PureExpr) 
>            (FoFCode PureExpr) a
>      | While (FoFCode PureExpr) 
>              (FoFCode PureExpr) a
>      | DoWhile (FoFCode PureExpr) 
>                (FoFCode PureExpr) a
>      | Switch PureExpr 
>               [(PureExpr, FoFCode PureExpr)] 
>               (FoFCode PureExpr) a
>      | Break
>      | Continue 

Support for Arrays:

>      | NewArray (Maybe String) AllocArray [Data] (Loc -> a)
>      | ReadArray Loc Index (Data -> a)
>      | WriteArray Loc Index Data a

The following type synonyms have been used above as a documentation
purpose. A |Data| represents a value used to initialize a
data-structure. A |Loc| represents a reference. An |Index| is a value
used to index an array.

> type Data = PureExpr
> type Loc = PureExpr
> type Index = PureExpr

\paragraph{Function attributes}

A function can be characterized by the following attributes, following
their C semantics:

> data FunAttr = Static
>              | Inline
>              deriving (Eq)

> instance Show FunAttr where
>     show Static = "static"
>     show Inline = "inline"

\paragraph{Enumeration}

When defining an enumeration, we use the following type synonym to
describe the list of pair name-value:

> type Enumeration = [(String, Int)]


\subsection{Functor instance}

A crucial specificity of |FoFConst| is that it defines a functor. This
functor is defined as follow.

> instance Functor FoFConst where
>     fmap f (Assert a b) = Assert a (f b)
>     fmap f (Printf a b c) = Printf a b (f c)
>     fmap f (HasDescendants a b c) = HasDescendants a b (f . c)
>     fmap f (MemToPhys a b c) = MemToPhys a b (f . c)
>     fmap f (GetAddress a b c) = GetAddress a b (f . c)
>     fmap f (NewUnion a b c d e g) = NewUnion a b c d e (f . g)
>     fmap f (ReadUnion a b c) = ReadUnion a b (f . c)
>     fmap f (WriteUnion a b c d) = WriteUnion a b c (f d)
>     fmap f (Typedef a c) = Typedef a (f c)
>     fmap f (TypedefE a b c) = TypedefE a b (f c)
>     fmap f (NewStruct a b c d e) = NewStruct a b c d (f . e)
>     fmap f (ReadStruct a b c) = ReadStruct a b (f . c)
>     fmap f (WriteStruct a b c d) = WriteStruct a b c (f d)
>     fmap f (NewString a b c) = NewString a b (f . c)
>     fmap f (NewRef a b c) = NewRef a b (f . c)
>     fmap f (ReadRef a b) = ReadRef a (f . b)
>     fmap f (WriteRef a b c) = WriteRef a b (f c)
>     fmap g (NewDef a b c d e f) = NewDef a b c d e (g . f)
>     fmap f (CallDef a b c d) = CallDef a b c (f . d)
>     fmap f (Return a) = Return a
>     fmap f (NewEnum a b c d e) = NewEnum a b c d (f . e)
>     fmap f (If a b c d) = If a b c (f d)
>     fmap f (For a b c d e) = For a b c d (f e)
>     fmap f (While a b c) = While a b (f c)
>     fmap f (DoWhile a b c) = DoWhile a b (f c)
>     fmap f (Switch a b c d) = Switch a b c (f d)
>     fmap f Break = Break
>     fmap f Continue = Continue
>     fmap f (NewArray a b c d) = NewArray a b c (f . d)
>     fmap f (ReadArray a b c) = ReadArray a b (f . c)
>     fmap f (WriteArray a b c d) = WriteArray a b c (f d)

Thanks to this functor structure, it makes sense to embed |FoFConst|
in a |Semantics|: the machinery we build in
Chapter~\ref{sec:semantics_machinery} will take care of transforming
this functor into a free monad. Hence the following type synonym.

> type FoFCode a = Semantics FoFConst a

