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  }