-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathAbstractFormat.idr
235 lines (195 loc) · 7.62 KB
/
AbstractFormat.idr
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
module Compiler.Erlang.IR.AbstractFormat
import public Data.Vect
import public Data.List1
import public Compiler.Erlang.Utils.PrimTerm
%default total
-- This file contain representations of Erlang's Abstract Format,
-- as described here: https://erlang.org/doc/apps/erts/absform.html
public export
Line : Type
Line = Int
public export
data Literal : Type where
ALAtom : Line -> String -> Literal
ALChar : Line -> Char -> Literal
ALFloat : Line -> Double -> Literal
ALInteger : Line -> Integer -> Literal
ALCharlist : Line -> String -> Literal
public export
data MapFieldAssoc : Type -> Type where
MkAssoc : Line -> (key : a) -> (value : a) -> MapFieldAssoc a
public export
data MapFieldExact : Type -> Type where
MkExact : Line -> (key : a) -> (value : a) -> MapFieldExact a
public export
data BitSignedness = ABUnsigned | ABSigned
public export
data BitEndianness = ABBig | ABLittle | ABNative
-- Unit is a value from 1-256 where `FZ` is representing the value 1
export
data BitUnit = MkBitUnit (Fin 256)
export
bitUnitToNat : BitUnit -> Nat
bitUnitToNat (MkBitUnit x) = finToNat x + 1
export
natToBitUnit : Nat -> Maybe BitUnit
natToBitUnit x = MkBitUnit <$> natToFin (x `minus` 1) 256
export
fromInteger : (x : Integer) -> {auto prf : So (fromInteger x >= 1 && fromInteger x <= 256)} -> BitUnit
fromInteger x =
fromMaybe (MkBitUnit 0) (natToBitUnit (integerToNat x))
-- SOURCE: https://www.erlang.org/doc/reference_manual/expressions.html#bit-syntax-expressions
public export
data TypeSpecifierList : Type where
ABInteger : {default ABUnsigned signedness : BitSignedness} -> {default ABBig endianness : BitEndianness} -> {default 1 unit : BitUnit} -> TypeSpecifierList
ABFloat : {default ABBig endianness : BitEndianness} -> {default 1 unit : BitUnit} -> TypeSpecifierList
ABBinary : {default 8 unit : BitUnit} -> TypeSpecifierList
-- `bytes` is shorthand for `binary`
ABBitstring : {default 1 unit : BitUnit} -> TypeSpecifierList
-- `bits` is shorthand for `bitstring`
ABUtf8 : TypeSpecifierList
ABUtf16 : {default ABBig endianness : BitEndianness} -> TypeSpecifierList
ABUtf32 : {default ABBig endianness : BitEndianness} -> TypeSpecifierList
public export
data BitSize : Type where
ABSDefault : BitSize
ABSInteger : Line -> Integer -> BitSize
ABSVar : Line -> String -> BitSize
public export
data BitSegment : Type -> Type where
MkBitSegment : Line -> a -> (size : BitSize) -> TypeSpecifierList -> BitSegment a
public export
data BitPattern : Type where
ABPInteger : Line -> Integer -> BitPattern
ABPFloat : Line -> Double -> BitPattern
ABPCharlist : Line -> String -> BitPattern
ABPUniversal : Line -> BitPattern -- Wildcard matching
ABPVar : Line -> (name : String) -> BitPattern
public export
data Pattern : Type where
APLiteral : Literal -> Pattern
APBitstring : Line -> List (BitSegment BitPattern) -> Pattern
-- Compound pattern
APCons : Line -> Pattern -> Pattern -> Pattern
APMap : Line -> List (MapFieldExact Pattern) -> Pattern
APNil : Line -> Pattern
-- Operator pattern
-- Paranthesized pattern
-- Record field index pattern
-- Record pattern
APTuple : Line -> List Pattern -> Pattern
APUniversal : Line -> Pattern -- Wildcard matching
APVar : Line -> (name : String) -> Pattern
public export
data Guard : Type where
AGLiteral : Literal -> Guard
-- Bitstring constructor
AGCons : Line -> Guard -> Guard -> Guard
AGFunCall : Line -> (fnName : String) -> List Guard -> Guard -- NOTE: Function calls are restricted to the 'erlang' module
-- Map creation
-- Map update
AGNil : Line -> Guard
AGOp : Line -> (op : String) -> Guard -> Guard -> Guard
-- Paranthesized guard
-- Record creation
-- Record field access
-- Record field index
AGTuple : Line -> List Guard -> Guard
AGVar : Line -> (name : String) -> Guard
-- A guard sequence `Gd1, Gd2; Gd3, Gd4` has the same meaning as:
-- `(Gd1 andalso Gd2) orelse (Gd3 andalso Gd4)`
--
-- A guard sequence is represented by the type `List GuardAlt`:
-- * You can have zero or more `GuardAlt` expressions.
-- * Each `GuardAlt` needs to have at least one `Guard` expression.
public export
data GuardAlt : Type where
MkGuardAlt : (guards : List1 Guard) -> GuardAlt
mutual
public export
data Expr : Type where
AELiteral : Literal -> Expr
AEBitstring : Line -> List (BitSegment Expr) -> Expr
-- Bitstring comprehension
AEBlock : Line -> (body : List1 Expr) -> Expr
AECase : Line -> Expr -> (clauses : List1 CaseClause) -> Expr
-- Catch expression
AECons : Line -> Expr -> Expr -> Expr
-- Function reference
AEFun : Line -> (arity : Nat) -> (clauses : List1 (FunClause arity)) -> Expr
AEFunCall : Line -> (fn : Expr) -> (args : List Expr) -> Expr
AERemoteRef : Line -> (modName : Expr) -> (fnName : Expr) -> Expr
-- If expression
-- List comprehension
AEMapNew : Line -> List (MapFieldAssoc Expr) -> Expr
-- Map update
AEMatch : Line -> (lhs : Pattern) -> (rhs : Expr) -> Expr
AENil : Line -> Expr
AEOp : Line -> (op : String) -> (lhs : Expr) -> (rhs : Expr) -> Expr
-- Paranthesized expression
AEReceive : Line -> List CaseClause -> ReceiveTimeout -> Expr
-- Record creation expression
-- Record update expression
AETuple : Line -> List Expr -> Expr
AETry : Line -> (statements : List1 Expr) -> List CaseClause -> List CatchClause -> (afterBody : List Expr) -> Expr
AEVar : Line -> (name : String) -> Expr
public export
data FunClause : Nat -> Type where
MkFunClause : Line -> Vect arity Pattern -> List GuardAlt -> (body : List1 Expr) -> FunClause arity
public export
data CaseClause : Type where
MkCaseClause : Line -> Pattern -> List GuardAlt -> (body : List1 Expr) -> CaseClause
public export
data CatchClause : Type where
MkCatchClause : Line -> (class : Pattern) -> (reason : Pattern) -> (stacktrace : Pattern) -> List GuardAlt -> (body : List1 Expr) -> CatchClause
public export
data ReceiveTimeout : Type where
NoTimeout : ReceiveTimeout
TimeoutAfter : (ms : Expr) -> (body : List1 Expr) -> ReceiveTimeout
public export
data Decl : Type where
ADExport : Line -> List (String, Nat) -> Decl
-- ADImport
ADModule : Line -> (name : String) -> Decl
-- ADFile
ADFunDef : Line -> (name : String) -> (arity : Nat) -> (clauses : List1 (FunClause arity)) -> Decl
-- ADFunSpec
-- ADRecord
-- ADType
ADAttribute : Line -> (attr : String) -> (value : PrimTerm) -> Decl
-- LINE HELPERS
export
getLiteralLine : Literal -> Line
getLiteralLine (ALAtom l _) = l
getLiteralLine (ALChar l _) = l
getLiteralLine (ALFloat l _) = l
getLiteralLine (ALInteger l _) = l
getLiteralLine (ALCharlist l _) = l
export
getGuardLine : Guard -> Line
getGuardLine (AGLiteral lit) = getLiteralLine lit
getGuardLine (AGCons l _ _) = l
getGuardLine (AGFunCall l _ _) = l
getGuardLine (AGNil l) = l
getGuardLine (AGOp l _ _ _) = l
getGuardLine (AGTuple l _) = l
getGuardLine (AGVar l _) = l
-- TYPE SPECIFIER LIST HELPERS
export
getBitSignedness : TypeSpecifierList -> Maybe BitSignedness
getBitSignedness (ABInteger {signedness}) = Just signedness
getBitSignedness _ = Nothing
export
getBitEndianness : TypeSpecifierList -> Maybe BitEndianness
getBitEndianness (ABInteger {endianness}) = Just endianness
getBitEndianness (ABFloat {endianness}) = Just endianness
getBitEndianness (ABUtf16 {endianness}) = Just endianness
getBitEndianness (ABUtf32 {endianness}) = Just endianness
getBitEndianness _ = Nothing
export
getBitUnit : TypeSpecifierList -> Maybe BitUnit
getBitUnit (ABInteger {unit}) = Just unit
getBitUnit (ABFloat {unit}) = Just unit
getBitUnit (ABBinary {unit}) = Just unit
getBitUnit (ABBitstring {unit}) = Just unit
getBitUnit _ = Nothing