github.com/mavryk-network/mvgo@v1.19.9/internal/parse/entrypoints.go (about)

     1  package parse
     2  
     3  import (
     4  	"sort"
     5  	"strconv"
     6  
     7  	"github.com/mavryk-network/mvgo/contract/ast"
     8  	"github.com/mavryk-network/mvgo/micheline"
     9  
    10  	"github.com/pkg/errors"
    11  )
    12  
    13  func (p *parser) parseEntrypoints() error {
    14  	entrypointMap, err := p.script.Entrypoints(true)
    15  	if err != nil {
    16  		return errors.Wrap(err, "failed to get entrypoints")
    17  	}
    18  	entrypoints := mapValues(entrypointMap)
    19  	// Sort entrypoints by id
    20  	sort.SliceStable(entrypoints, func(i, j int) bool { return entrypoints[i].Id < entrypoints[j].Id })
    21  	for _, entrypoint := range entrypoints {
    22  		e, err := p.parseEntrypoint(&entrypoint)
    23  		if err != nil {
    24  			return errors.Wrap(err, "failed to parse entrypoint")
    25  		}
    26  		if getter, isGetter := e.(*ast.Getter); isGetter {
    27  			p.contract.Getters = append(p.contract.Getters, getter)
    28  		} else {
    29  			p.contract.Entrypoints = append(p.contract.Entrypoints, e.(*ast.Entrypoint))
    30  		}
    31  	}
    32  	return nil
    33  }
    34  
    35  func (p *parser) parseEntrypoint(entrypoint *micheline.Entrypoint) (any, error) {
    36  	e := ast.Entrypoint{
    37  		Name: entrypoint.Name,
    38  		Raw:  entrypoint,
    39  	}
    40  	nArgs := len(entrypoint.Typedef)
    41  	for i, arg := range entrypoint.Typedef {
    42  		if arg.Type == "unit" && i == 0 {
    43  			// continue because it can still be a getter
    44  			continue
    45  		}
    46  		if arg.Type == "contract" && i == nArgs-1 {
    47  			// arg.Args contains the return type of the getter
    48  			returnType, err := p.buildTypeStructs(&arg.Args[0])
    49  			if err != nil {
    50  				return nil, errors.Wrap(err, "failed to parse return type")
    51  			}
    52  			return &ast.Getter{Entrypoint: e, ReturnType: returnType}, nil
    53  		}
    54  		typ, err := p.buildTypeStructs(&arg)
    55  		if err != nil {
    56  			return nil, errors.Wrap(err, "failed to parse type")
    57  		}
    58  		e.Params = append(e.Params, entrypointParam(&arg, typ, i))
    59  	}
    60  	return &e, nil
    61  }
    62  
    63  func entrypointParam(arg *micheline.Typedef, typ *ast.Struct, i int) *ast.Struct {
    64  	argName := arg.Name
    65  	if argName == "" || startsWithInt(argName) {
    66  		argName = arg.Type + strconv.Itoa(i)
    67  	}
    68  	originalType := arg.Type
    69  	if arg.Optional {
    70  		originalType = "option<" + originalType + ">"
    71  	}
    72  	return &ast.Struct{Name: argName, Type: typ, OriginalType: originalType}
    73  }
    74  
    75  func startsWithInt(s string) bool {
    76  	if s == "" {
    77  		return false
    78  	}
    79  	return s[0] >= '0' && s[0] <= '9'
    80  }
    81  
    82  func mapValues[M ~map[K]V, K comparable, V any](m M) []V {
    83  	values := make([]V, 0, len(m))
    84  	for _, v := range m {
    85  		values = append(values, v)
    86  	}
    87  	return values
    88  }