-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathLamVal.hs
109 lines (91 loc) · 2.86 KB
/
LamVal.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
module LambdaBuffers.Codegen.LamVal (
ValueE (..),
ValueName,
Ref,
(@),
SumImpl,
ProductImpl,
RecordImpl,
Record,
Product,
Sum,
Field,
Ctor,
QField,
QRecord,
QProduct,
QSum,
QCtor,
) where
import Data.Map.Ordered (OMap)
import Data.Text (Text)
import LambdaBuffers.Compiler.LamTy qualified as LT
import LambdaBuffers.ProtoCompat qualified as PC
-- | Simple HOAS encoding of a little lambda calculus language.
data ValueE where
LamE :: (ValueE -> ValueE) -> ValueE
AppE :: ValueE -> ValueE -> ValueE
RefE :: Ref -> ValueE
VarE :: String -> ValueE
-- | Sum expressions
CaseE :: QSum -> ValueE -> ((Ctor, [ValueE]) -> ValueE) -> ValueE
CtorE :: QCtor -> [ValueE] -> ValueE
-- | Record expressions
RecordE :: QRecord -> [(Field, ValueE)] -> ValueE
FieldE :: QField -> ValueE -> ValueE
-- | Product expressions
ProductE :: QProduct -> [ValueE] -> ValueE
LetE :: QProduct -> ValueE -> ([ValueE] -> ValueE) -> ValueE
-- | Int expressions
IntE :: Int -> ValueE
-- caseInt :: Int -> [(Int, a)] -> (Int -> a) -> a
CaseIntE :: ValueE -> [(ValueE, ValueE)] -> (ValueE -> ValueE) -> ValueE
-- | Text expressions
TextE :: Text -> ValueE
-- caseText :: Text -> [(Text, a)] -> (Text -> a) -> a
CaseTextE :: ValueE -> [(ValueE, ValueE)] -> (ValueE -> ValueE) -> ValueE
-- | List expressions
ListE :: [ValueE] -> ValueE
CaseListE :: ValueE -> [(Int, [ValueE] -> ValueE)] -> (ValueE -> ValueE) -> ValueE
-- | Tuple expressions
TupleE :: ValueE -> ValueE -> ValueE
-- | Error
ErrorE :: String -> ValueE
(@) :: ValueE -> ValueE -> ValueE
(@) = AppE
-- | A name for a value.
type ValueName = String
{- | A value reference that may be parametrized on `LT.Ty`s.
We use this during code generation when 'finding' concrete values, especially for polymorphic functions.
For example
```haskell
id :: a -> a
id x = x
firstUseSite :: Int -> Int
firstUseSite = id
secondUseSite :: String -> String
secondUseSite = id
thirdUseSite :: a -> a
thirdUseSite = id
```
In the `firstUseSite` the `id` is instantiated to 'is `(["Int"], "id")`.
In the `secondUseSite` the `id` is instantiated to 'is `(["String"], "id")`.
In the `thirdUseSite` the `id` is instantiated to 'is `(["a"], "id")`.
-}
type Ref = ([LT.Ty], ValueName)
{- | Wrapper types.
TODO(bladyjoker): Refactor `ProtoCompat.Eval` to have these types explicitly named.
-}
type Sum = OMap (PC.InfoLess PC.ConstrName) LT.Ty
type Product = [LT.Ty]
type Record = OMap (PC.InfoLess PC.FieldName) LT.Ty
type Ctor = (PC.InfoLess PC.ConstrName, Product)
type Field = (PC.InfoLess PC.FieldName, LT.Ty)
type SumImpl = QSum -> ValueE
type ProductImpl = QProduct -> ValueE
type RecordImpl = QRecord -> ValueE
type QCtor = (PC.QTyName, Ctor)
type QSum = (PC.QTyName, Sum)
type QField = (PC.QTyName, PC.InfoLess PC.FieldName)
type QRecord = (PC.QTyName, Record)
type QProduct = (PC.QTyName, Product)