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