package object import ( "fmt" "strings" "unicode/utf8" ) type String struct { Value string } func (s String) Len() int { return utf8.RuneCountInString(s.Value) } func (s String) Bool() bool { return s.Value != "" } func (s String) Type() Type { return StringType } func (s String) Inspect() string { return fmt.Sprintf("%#v", s.Value) } func (s String) Clone() Object { return String{Value: s.Value} } func (s String) String() string { return s.Value } func (s String) Add(other Object) (Object, error) { if !AssertTypes(other, StringType) { return nil, NewBinaryOpError(s, other, "+") } return String{s.Value + other.(String).Value}, nil } func (s String) Mul(other Object) (Object, error) { if !AssertTypes(other, IntegerType) { return nil, NewBinaryOpError(s, other, "*") } return String{strings.Repeat(s.Value, int(other.(Integer).Value))}, nil } func (s String) Get(index Object) (Object, error) { if !AssertTypes(index, IntegerType) { return nil, fmt.Errorf("invalid type for string index, expected Integer got %s", index.Type()) } i := int(index.(Integer).Value) if i < 0 || i >= len(s.Value) { return String{}, nil } return String{string(s.Value[i])}, nil } func (s String) Compare(other Object) int { if obj, ok := other.(String); ok { switch { case s.Value < obj.Value: return -1 case s.Value > obj.Value: return 1 default: return 0 } } return 1 }