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 }