91 lines
2.8 KiB
Plaintext
91 lines
2.8 KiB
Plaintext
%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.Enumerations where
|
|
|
|
> import Data.Maybe
|
|
|
|
> import Semantics
|
|
> import Constructs
|
|
> import PureExpressions
|
|
> import {-# SOURCE #-} Expressions
|
|
|
|
> import IL.FoF.FoF
|
|
> import IL.FoF.Compile
|
|
|
|
%endif
|
|
|
|
\section{Enumeration}
|
|
|
|
The |Enumeration| construct mirrors the @enum@ data-type of C. It
|
|
allows us to name a finite number of natural constants and manipulate
|
|
these names instead of numbers.
|
|
|
|
\subsection{Smart Constructors}
|
|
|
|
The |newEnum| combinator is used to create a member |value| belonging
|
|
to one of the |fields| of |nameEnum|.
|
|
|
|
> newEnum :: String ->
|
|
> Enumeration ->
|
|
> String ->
|
|
> FoFCode PureExpr
|
|
> newEnum nameEnum fields value =
|
|
> inject (NewEnum Nothing nameEnum fields value return)
|
|
|
|
Similarly, |newEnumN| creates a named member of an enumeration.
|
|
|
|
> newEnumN :: String ->
|
|
> String ->
|
|
> Enumeration ->
|
|
> String ->
|
|
> FoFCode PureExpr
|
|
> newEnumN name nameEnum fields value =
|
|
> inject (NewEnum (Just name) name fields value return)
|
|
|
|
\subsection{Compile Instantiation}
|
|
|
|
A |NewEnum| is compiled as follow.
|
|
|
|
> compileEnumerations (NewEnum name enumName vals value r) binding =
|
|
> (FStatement (FNewEnum publicName enumName vals value) cont,
|
|
> binding3)
|
|
> where (publicName, binding2)
|
|
> = case name of
|
|
> Just x -> (Provided x, binding)
|
|
> Nothing -> (makeVarName Local loc,
|
|
> binding1)
|
|
> where (loc, binding1) = getFreshVar binding
|
|
> ret = CLRef Global uint64T (Provided value)
|
|
> (cont, binding3) = r ret binding2
|
|
|
|
Note that |ret| is actually the name of the enumerated value: it is
|
|
treated as a constant and passed as such to the remaining code. A more
|
|
standard implementation would have been to create a variable
|
|
containing this constant value and pass the reference to the variable
|
|
to the subsequent code. However, when |switch|-ing over an enumerated
|
|
value, the case would match a variable instead of a constant, which is
|
|
refused by the C compiler.
|
|
|
|
Clearly, a clean solution to this implementation must be
|
|
found. However, the current solution, if not perfect, seems to be good
|
|
enough.
|
|
|
|
\subsection{Run Instantiation}
|
|
|
|
Running a |newEnum| simply consists in getting the associated value.
|
|
|
|
> runEnumerations (NewEnum _ _ enum name r) heap =
|
|
> let ref = uint64 $ toInteger $ fromJust $ name `lookup` enum in
|
|
> r ref heap
|