-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnarcissus.ml
145 lines (110 loc) · 3.1 KB
/
narcissus.ml
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
module Expr = struct
type t =
| Var of int
| RecordLit of (string * t) list
| RecordProj of t * string
| ByteLit of char
| BytesLit of t list
| BytesAppend of t * t
end
module Pred = struct
type t =
| And of t * t
| Or of t * t
| Eq of Expr.t * Expr.t
end
module Format = struct
type t =
| Byte
| Seq of t * t
| Proj of t * string
(* | Union of t * t *)
(* | Restrict of Pred.t * t *)
| Empty
let rec seq (formats : t list) : t =
match formats with
| [] -> Empty
| format :: formats -> Seq (format, seq formats)
end
module Decoder = struct
type t =
| Byte
| Pure of Expr.t
| Bind of t * Expr.t
| Fail of t
let compile (_pred : Pred.t) (format : Format.t) : t =
(* Based on Figure 5 from the Narcissus paper *)
match format with
| Byte ->
Byte
(* DecCompose *)
| Proj (_, _) ->
failwith "TODO"
(* DecSeqProj *)
| Seq (Proj _, _) ->
failwith "TODO"
(* DecSeq *)
| Seq (_, _) ->
failwith "TODO"
(* DecDone *)
| Empty ->
(* if (pred src) then pure src else fail *)
failwith "TODO"
end
module Encoder = struct
type t =
| Byte
| Pure of Expr.t
| Bind of t * t
| Fail of t
type neu =
| Var of int
| RecordProj of neu * string
let ( let@ ) = ( @@ )
let rec quote_neu (size : int) (neu : neu) : Expr.t =
match neu with
| Var level -> Var (size - level - 1)
| RecordProj (neu, label) -> RecordProj (quote_neu size neu, label)
let rec compile (size : int) (src : neu) (format : Format.t) : t =
(* Based on Figure 3 from the Narcissus paper *)
match format with
| Byte ->
Pure (BytesLit [quote_neu size src])
(* EncComp *)
| Proj (format, label) ->
compile size (RecordProj (src, label)) format
(* EncSeq *)
| Seq (format1, format2) ->
(* TODO: Check format relations? Might be important for threading through state *)
let@ size, x = compile_bind size src format1 in
let@ size, y = compile_bind size src format2 in
Pure (BytesAppend (quote_neu size x, quote_neu size y))
(*
(* EncRest *)
| Restrict (pred, format) ->
let src = quote_neu size src in
If (PredApp (pred, src), compile size src format, Fail)
(* EncUnion *)
| Union (format1, format2) ->
let encode1 = compile size src format1
and encode2 = compile size src format2 in
(* How do we choose between [format1] and [format2]? *)
failwith "TODO"
*)
(* EncEmpty *)
| Empty ->
Pure (BytesLit [])
and compile_bind (size : int) (src : neu) (format : Format.t) (body : int * neu -> t) : t =
Bind ((* x, *) compile size src format,
body (size + 1, Var size))
end
module Examples = struct
let sensor_msg : Format.t = Format.seq [
Proj (Byte, "station-id");
Proj (Byte, "data");
]
let sensor_msg_decoder =
Decoder.compile (failwith "TODO") sensor_msg
let sensor_msg_encoder =
Encoder.compile (failwith "TODO") (failwith "TODO") sensor_msg
end