-
Notifications
You must be signed in to change notification settings - Fork 14
/
Lang.hs
78 lines (65 loc) · 1.78 KB
/
Lang.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
-- | Surface language
module Circuit.Lang
( c
, add
, sub
, mul
, and_
, or_
, xor_
, not_
, eq
, deref
, e
, cond
, ret
, input
) where
import Protolude
import Circuit.Affine (AffineCircuit(..))
import Circuit.Arithmetic (Gate(..), Wire(..))
import Circuit.Expr
-- | Convert constant to expression
c :: f -> Expr Wire f f
c = EConst
-- | Binary arithmetic operations on expressions
add, sub, mul :: Expr Wire f f -> Expr Wire f f -> Expr Wire f f
add = EBinOp BAdd
sub = EBinOp BSub
mul = EBinOp BMul
-- | Binary logic operations on expressions
-- Have to use underscore or similar to avoid shadowing @and@ and @or@
-- from Prelude/Protolude.
and_, or_, xor_ :: Expr Wire f Bool -> Expr Wire f Bool -> Expr Wire f Bool
and_ = EBinOp BAnd
or_ = EBinOp BOr
xor_ = EBinOp BXor
-- | Negate expression
not_ :: Expr Wire f Bool -> Expr Wire f Bool
not_ = EUnOp UNot
-- | Compare two expressions
eq :: Expr Wire f f -> Expr Wire f f -> Expr Wire f Bool
eq = EEq
-- | Convert wire to expression
deref :: Wire -> Expr Wire f f
deref = EVar
-- | Return compilation of expression into an intermediate wire
e :: Num f => Expr Wire f f -> ExprM f Wire
e = compileWithWire imm
-- | Conditional statement on expressions
cond :: Expr Wire f Bool -> Expr Wire f ty -> Expr Wire f ty -> Expr Wire f ty
cond = EIf
-- | Return compilation of expression into an output wire
ret :: Num f => Expr Wire f f -> ExprM f Wire
ret = compileWithWire freshOutput
compileWithWire :: Num f => ExprM f Wire -> Expr Wire f f -> ExprM f Wire
compileWithWire freshWire expr = do
compileOut <- compile expr
case compileOut of
Left wire -> pure wire
Right circ -> do
wire <- freshWire
emit $ Mul (ConstGate 1) circ wire
pure wire
input :: ExprM f Wire
input = freshInput