github.com/mavryk-network/mvgo@v1.19.9/internal/parse/type.go (about) 1 package parse 2 3 import ( 4 "github.com/mavryk-network/mvgo/contract/ast" 5 m "github.com/mavryk-network/mvgo/micheline" 6 ) 7 8 func (p *parser) buildTypeStructs(t *m.Typedef) (*ast.Struct, error) { 9 // Unwrap optional 10 if t.Optional { 11 typ, err := p.buildTypeStructs(&m.Typedef{Name: t.Name, Type: t.Type, Args: t.Args}) 12 if err != nil { 13 return nil, err 14 } 15 return typ, nil 16 } 17 // Builtin types 18 if op, err := m.ParseOpCode(t.Type); err == nil { 19 opstr := op.String() 20 switch op { 21 case m.T_NAT, 22 m.T_INT, 23 m.T_STRING, 24 m.T_BOOL, 25 m.T_BYTES, 26 m.T_UNIT, 27 m.T_TIMESTAMP, 28 m.T_ADDRESS, 29 m.T_MUMAV, 30 m.T_KEY, 31 m.T_KEY_HASH, 32 m.T_SIGNATURE, 33 m.T_CHAIN_ID, 34 m.T_OPERATION, 35 m.T_CONTRACT: 36 return &ast.Struct{ 37 Name: t.Name, 38 MichelineType: opstr, 39 }, nil 40 case m.T_BIG_MAP, 41 m.T_MAP, 42 m.T_LAMBDA: 43 type1, err := p.buildTypeStructs(&t.Args[0]) 44 if err != nil { 45 return nil, err 46 } 47 type2, err := p.buildTypeStructs(&t.Args[1]) 48 if err != nil { 49 return nil, err 50 } 51 switch op { 52 case m.T_BIG_MAP, m.T_MAP: 53 return &ast.Struct{ 54 Name: t.Name, 55 MichelineType: opstr, 56 Key: type1, 57 Value: type2, 58 }, nil 59 case m.T_LAMBDA: 60 return &ast.Struct{ 61 Name: t.Name, 62 MichelineType: opstr, 63 ParamType: type1, 64 ReturnType: type2, 65 }, nil 66 } 67 } 68 } 69 // container type 70 type1, err := p.buildTypeStructs(&t.Args[0]) 71 if err != nil { 72 return nil, err 73 } 74 switch t.Type { 75 case m.TypeStruct: 76 return p.buildStruct(t) 77 case m.TypeUnion: 78 type2, err := p.buildTypeStructs(&t.Args[1]) 79 if err != nil { 80 return nil, err 81 } 82 return &ast.Struct{ 83 MichelineType: "union", 84 LeftType: type1, 85 RightType: type2, 86 }, nil 87 case "list": 88 return &ast.Struct{ 89 MichelineType: "list", 90 Type: type1, 91 }, nil 92 case "set": 93 return &ast.Struct{ 94 MichelineType: "set", 95 Type: type1, 96 }, nil 97 } 98 return nil, nil 99 } 100 101 func (p *parser) buildStruct(t *m.Typedef) (*ast.Struct, error) { 102 fieldTypes := make([]*ast.Struct, 0, len(t.Args)) 103 path := make([][]int, 0, len(t.Args)) 104 for _, a := range t.Args { 105 typ, err := p.buildTypeStructs(&a) 106 if err != nil { 107 return nil, err 108 } 109 name := a.Name 110 if startsWithInt(name) { 111 name = "field" + name 112 } 113 fieldTypes = append(fieldTypes, &ast.Struct{Name: name, Type: typ}) 114 path = append(path, a.Path) 115 } 116 st := &ast.Struct{ 117 MichelineType: "struct", 118 Fields: fieldTypes, 119 Path: path, 120 } 121 // Without annotation, structs gets a 122 // @-prefixed auto generated name. 123 // We want to remove it, so we get our auto-generated name. 124 if len(t.Name) > 0 && t.Name[0] != '@' { 125 st.Name = t.Name 126 } 127 cachedStruct, err := p.registerStruct(st) 128 if err != nil { 129 return nil, err 130 } 131 if cachedStruct != nil { 132 return cachedStruct, nil 133 } 134 return st, nil 135 } 136 137 func (p *parser) registerStruct(newStruct *ast.Struct) (*ast.Struct, error) { 138 if found, ok := p.cache.IsCached(newStruct); ok { 139 return found, nil 140 } 141 p.structs = append(p.structs, newStruct) 142 return nil, p.cache.CacheStruct(newStruct) 143 }