%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