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  }