github.com/hoop33/elvish@v0.0.0-20160801152013-6d25485beab4/eval/struct.go (about)

     1  package eval
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"github.com/elves/elvish/parse"
     8  )
     9  
    10  var (
    11  	ErrIndexMustBeString = errors.New("index must be string")
    12  )
    13  
    14  // Struct is like a Map with fixed keys.
    15  type Struct struct {
    16  	FieldNames []string
    17  	Fields     []Variable
    18  }
    19  
    20  var (
    21  	_ Value   = (*Struct)(nil)
    22  	_ MapLike = (*Struct)(nil)
    23  )
    24  
    25  func (*Struct) Kind() string {
    26  	return "map"
    27  }
    28  
    29  func (s *Struct) Repr(indent int) string {
    30  	var builder MapReprBuilder
    31  	builder.Indent = indent
    32  	for i, name := range s.FieldNames {
    33  		builder.WritePair(parse.Quote(name), s.Fields[i].Get().Repr(indent+1))
    34  	}
    35  	return builder.String()
    36  }
    37  
    38  func (s *Struct) Len() int {
    39  	return len(s.FieldNames)
    40  }
    41  
    42  func (s *Struct) IndexOne(idx Value) Value {
    43  	return s.index(idx).Get()
    44  }
    45  
    46  func (s *Struct) HasKey(k Value) bool {
    47  	index, ok := k.(String)
    48  	if !ok {
    49  		return false
    50  	}
    51  	for _, name := range s.FieldNames {
    52  		if string(index) == name {
    53  			return true
    54  		}
    55  	}
    56  	return false
    57  }
    58  
    59  func (s *Struct) IndexSet(idx Value, v Value) {
    60  	s.index(idx).Set(v)
    61  }
    62  
    63  func (s *Struct) index(idx Value) Variable {
    64  	index, ok := idx.(String)
    65  	if !ok {
    66  		throw(ErrIndexMustBeString)
    67  	}
    68  	for i, name := range s.FieldNames {
    69  		if string(index) == name {
    70  			return s.Fields[i]
    71  		}
    72  	}
    73  	throw(fmt.Errorf("no such field: %s", index.Repr(NoPretty)))
    74  	panic("unreachable")
    75  }