github.com/mavryk-network/mvgo@v1.19.9/micheline/builder.go (about) 1 // Copyright (c) 2020-2021 Blockwatch Data Inc. 2 // Author: alex@blockwatch.cc 3 4 package micheline 5 6 import ( 7 "math/big" 8 "sort" 9 10 "github.com/mavryk-network/mvgo/mavryk" 11 ) 12 13 var ( 14 Unit = NewCode(D_UNIT) 15 ) 16 17 func NewCode(c OpCode, args ...Prim) Prim { 18 var typ PrimType 19 switch len(args) { 20 case 0: 21 typ = PrimNullary 22 case 1: 23 typ = PrimUnary 24 case 2: 25 typ = PrimBinary 26 default: 27 typ = PrimVariadicAnno 28 } 29 return Prim{Type: typ, OpCode: c, Args: args} 30 } 31 32 func NewCodeAnno(c OpCode, anno string, args ...Prim) Prim { 33 p := NewCode(c, args...) 34 p.Anno = []string{anno} 35 if p.Type != PrimVariadicAnno { 36 p.Type++ 37 } 38 return p 39 } 40 41 func NewSeq(args ...Prim) Prim { 42 return Prim{Type: PrimSequence, Args: args} 43 } 44 45 func NewInt64(i int64) Prim { 46 return NewBig(big.NewInt(i)) 47 } 48 49 func NewZ(z mavryk.Z) Prim { 50 return NewBig(new(big.Int).Set(z.Big())) 51 } 52 53 func NewMumav(n mavryk.N) Prim { 54 return NewBig(big.NewInt(int64(n))) 55 } 56 57 func NewBig(i *big.Int) Prim { 58 return Prim{Type: PrimInt, Int: i} 59 } 60 61 func NewNat(i *big.Int) Prim { 62 return Prim{Type: PrimInt, Int: i} 63 } 64 65 func NewKeyHash(a mavryk.Address) Prim { 66 return NewBytes(a.Encode()) 67 } 68 69 func NewAddress(a mavryk.Address) Prim { 70 return NewBytes(a.EncodePadded()) 71 } 72 73 func NewBytes(b []byte) Prim { 74 return Prim{Type: PrimBytes, Bytes: b} 75 } 76 77 func NewString(s string) Prim { 78 return Prim{Type: PrimString, String: s} 79 } 80 81 func NewOption(p ...Prim) Prim { 82 if len(p) == 0 { 83 return Prim{Type: PrimNullary, OpCode: D_NONE} 84 } 85 return Prim{Type: PrimUnary, OpCode: D_SOME, Args: []Prim{p[0]}} 86 } 87 88 func NewPairType(l, r Prim, anno ...string) Prim { 89 typ := PrimBinary 90 if len(anno) > 0 { 91 typ = PrimBinaryAnno 92 } 93 return Prim{Type: typ, OpCode: T_PAIR, Args: []Prim{l, r}, Anno: anno} 94 } 95 96 func NewMapType(k, v Prim, anno ...string) Prim { 97 typ := PrimBinary 98 if len(anno) > 0 { 99 typ = PrimBinaryAnno 100 } 101 return Prim{Type: typ, OpCode: T_MAP, Args: []Prim{k, v}, Anno: anno} 102 } 103 104 func NewMap(elts ...Prim) Prim { 105 sort.Slice(elts, func(i, j int) bool { 106 return elts[i].Args[0].Compare(elts[j].Args[0]) <= 0 107 }) 108 return Prim{Type: PrimSequence, Args: elts} 109 } 110 111 func NewMapElem(k, v Prim) Prim { 112 return Prim{Type: PrimBinary, OpCode: D_ELT, Args: []Prim{k, v}} 113 } 114 115 func NewSetType(e Prim, anno ...string) Prim { 116 typ := PrimUnary 117 if len(anno) > 0 { 118 typ = PrimUnaryAnno 119 } 120 return Prim{Type: typ, OpCode: T_SET, Args: []Prim{e}, Anno: anno} 121 } 122 123 func NewOptType(e Prim, anno ...string) Prim { 124 typ := PrimUnary 125 if len(anno) > 0 { 126 typ = PrimUnaryAnno 127 } 128 return Prim{Type: typ, OpCode: T_OPTION, Args: []Prim{e}, Anno: anno} 129 } 130 131 func NewPair(l, r Prim) Prim { 132 return Prim{Type: PrimBinary, OpCode: D_PAIR, Args: []Prim{l, r}} 133 } 134 135 func NewCombPair(contents ...Prim) Prim { 136 return Prim{Type: PrimSequence, Args: contents} 137 } 138 139 func NewCombPairType(contents ...Prim) Prim { 140 return Prim{Type: PrimSequence, OpCode: T_PAIR, Args: contents} 141 } 142 143 func NewPrim(c OpCode, anno ...string) Prim { 144 typ := PrimNullary 145 if len(anno) > 0 { 146 typ = PrimNullaryAnno 147 } 148 return Prim{Type: typ, OpCode: c, Anno: anno} 149 } 150 151 func NewUnion(path []int, prim Prim) Prim { 152 if len(path) == 0 { 153 return prim 154 } 155 oc := D_LEFT 156 if path[0] == 1 { 157 oc = D_RIGHT 158 } 159 return NewCode(oc, NewUnion(path[1:], prim)) 160 } 161 162 func (p Prim) WithAnno(anno string) Prim { 163 p.Anno = append(p.Anno, anno) 164 return p 165 } 166 167 // Macros 168 func ASSERT_CMPEQ() Prim { 169 return NewSeq( 170 NewSeq(NewCode(I_COMPARE), NewCode(I_EQ)), 171 NewCode(I_IF, NewSeq(), NewSeq(NewSeq(NewCode(I_UNIT), NewCode(I_FAILWITH)))), 172 ) 173 } 174 175 func DUUP() Prim { 176 return NewSeq(NewCode(I_DIP, NewSeq(NewCode(I_DUP)), NewCode(I_SWAP))) 177 } 178 179 func IFCMPNEQ(left, right Prim) Prim { 180 return NewSeq( 181 NewCode(I_COMPARE), 182 NewCode(I_EQ), 183 NewCode(I_IF, left, right), 184 ) 185 } 186 187 func UNPAIR() Prim { 188 return NewSeq(NewSeq( 189 NewCode(I_DUP), 190 NewCode(I_CAR), 191 NewCode(I_DIP, NewSeq(NewCode(I_CDR))), 192 )) 193 }