1%if false 2 Copyright (c) 2009 ETH Zurich. 3 All rights reserved. 4 5 This file is distributed under the terms in the attached LICENSE file. 6 If you do not find this file, copies can be found by writing to: 7 ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 8%endif 9 10%include polycode.fmt 11 12%if false 13 14> module Constructs.Enumerations where 15 16> import Data.Maybe 17 18> import Semantics 19> import Constructs 20> import PureExpressions 21> import {-# SOURCE #-} Expressions 22 23> import IL.FoF.FoF 24> import IL.FoF.Compile 25 26%endif 27 28\section{Enumeration} 29 30The |Enumeration| construct mirrors the @enum@ data-type of C. It 31allows us to name a finite number of natural constants and manipulate 32these names instead of numbers. 33 34\subsection{Smart Constructors} 35 36The |newEnum| combinator is used to create a member |value| belonging 37to one of the |fields| of |nameEnum|. 38 39> newEnum :: String -> 40> Enumeration -> 41> String -> 42> FoFCode PureExpr 43> newEnum nameEnum fields value = 44> inject (NewEnum Nothing nameEnum fields value return) 45 46Similarly, |newEnumN| creates a named member of an enumeration. 47 48> newEnumN :: String -> 49> String -> 50> Enumeration -> 51> String -> 52> FoFCode PureExpr 53> newEnumN name nameEnum fields value = 54> inject (NewEnum (Just name) name fields value return) 55 56\subsection{Compile Instantiation} 57 58A |NewEnum| is compiled as follow. 59 60> compileEnumerations (NewEnum name enumName vals value r) binding = 61> (FStatement (FNewEnum publicName enumName vals value) cont, 62> binding3) 63> where (publicName, binding2) 64> = case name of 65> Just x -> (Provided x, binding) 66> Nothing -> (makeVarName Local loc, 67> binding1) 68> where (loc, binding1) = getFreshVar binding 69> ret = CLRef Global uint64T (Provided value) 70> (cont, binding3) = r ret binding2 71 72Note that |ret| is actually the name of the enumerated value: it is 73treated as a constant and passed as such to the remaining code. A more 74standard implementation would have been to create a variable 75containing this constant value and pass the reference to the variable 76to the subsequent code. However, when |switch|-ing over an enumerated 77value, the case would match a variable instead of a constant, which is 78refused by the C compiler. 79 80Clearly, a clean solution to this implementation must be 81found. However, the current solution, if not perfect, seems to be good 82enough. 83 84\subsection{Run Instantiation} 85 86Running a |newEnum| simply consists in getting the associated value. 87 88> runEnumerations (NewEnum _ _ enum name r) heap = 89> let ref = uint64 $ toInteger $ fromJust $ name `lookup` enum in 90> r ref heap 91