github.com/NeowayLabs/nash@v0.2.2-0.20200127205349-a227041ffd50/sh/obj.go (about)

     1  package sh
     2  
     3  import "fmt"
     4  
     5  //go:generate stringer -type=objType
     6  const (
     7  	StringType objType = iota + 1
     8  	FnType
     9  	ListType
    10  )
    11  
    12  type (
    13  	objType int
    14  
    15  	Obj interface {
    16  		Type() objType
    17  		String() string
    18  	}
    19  
    20  	ListObj struct {
    21  		objType
    22  		list []Obj
    23  	}
    24  
    25  	FnObj struct {
    26  		objType
    27  		fn FnDef
    28  	}
    29  
    30  	StrObj struct {
    31  		objType
    32  		runes []rune
    33  	}
    34  
    35  	Collection interface {
    36  		Len() int
    37  		Get(index int) (Obj, error)
    38  	}
    39  
    40  	WriteableCollection interface {
    41  		Set(index int, val Obj) error
    42  	}
    43  )
    44  
    45  func NewCollection(o Obj) (Collection, error) {
    46  	sizer, ok := o.(Collection)
    47  	if !ok {
    48  		return nil, fmt.Errorf(
    49  			"SizeError: trying to get size from type %s which is not a collection",
    50  			o.Type(),
    51  		)
    52  	}
    53  	return sizer, nil
    54  }
    55  
    56  func NewWriteableCollection(o Obj) (WriteableCollection, error) {
    57  	indexer, ok := o.(WriteableCollection)
    58  	if !ok {
    59  		return nil, fmt.Errorf(
    60  			"IndexError: trying to use a non write/indexable type %s to write on index: ",
    61  			o.Type(),
    62  		)
    63  	}
    64  	return indexer, nil
    65  }
    66  
    67  func (o objType) Type() objType {
    68  	return o
    69  }
    70  
    71  func NewStrObj(val string) *StrObj {
    72  	return &StrObj{
    73  		runes:   []rune(val),
    74  		objType: StringType,
    75  	}
    76  }
    77  
    78  func (o *StrObj) Str() string { return string(o.runes) }
    79  
    80  func (o *StrObj) String() string { return o.Str() }
    81  
    82  func (o *StrObj) Get(index int) (Obj, error) {
    83  	if index >= o.Len() {
    84  		return nil, fmt.Errorf(
    85  			"IndexError: Index[%d] out of range, string size[%d]",
    86  			index,
    87  			o.Len(),
    88  		)
    89  	}
    90  
    91  	return NewStrObj(string(o.runes[index])), nil
    92  }
    93  
    94  func (o *StrObj) Len() int {
    95  	return len(o.runes)
    96  }
    97  
    98  func NewFnObj(val FnDef) *FnObj {
    99  	return &FnObj{
   100  		fn:      val,
   101  		objType: FnType,
   102  	}
   103  }
   104  
   105  func (o *FnObj) Fn() FnDef { return o.fn }
   106  
   107  func (o *FnObj) String() string { return fmt.Sprintf("<fn %s>", o.fn.Name()) }
   108  
   109  func NewListObj(val []Obj) *ListObj {
   110  	return &ListObj{
   111  		list:    val,
   112  		objType: ListType,
   113  	}
   114  }
   115  
   116  func (o *ListObj) Len() int {
   117  	return len(o.list)
   118  }
   119  
   120  func (o *ListObj) Set(index int, value Obj) error {
   121  	if index >= len(o.list) {
   122  		return fmt.Errorf(
   123  			"IndexError: Index[%d] out of range, list size[%d]",
   124  			index,
   125  			len(o.list),
   126  		)
   127  	}
   128  	o.list[index] = value
   129  	return nil
   130  }
   131  
   132  func (o *ListObj) Get(index int) (Obj, error) {
   133  	if index >= len(o.list) {
   134  		return nil, fmt.Errorf(
   135  			"IndexError: Index out of bounds, index[%d] but list size[%d]",
   136  			index,
   137  			len(o.list),
   138  		)
   139  	}
   140  	return o.list[index], nil
   141  }
   142  
   143  func (o *ListObj) List() []Obj { return o.list }
   144  
   145  func (o *ListObj) String() string {
   146  	result := ""
   147  	list := o.List()
   148  	for i := 0; i < len(list); i++ {
   149  		l := list[i]
   150  
   151  		result += l.String()
   152  
   153  		if i < len(list)-1 {
   154  			result += " "
   155  		}
   156  	}
   157  
   158  	return result
   159  }