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) { switch obj := other.(type) { case String: return String{s.Value + obj.Value}, nil default: return nil, NewBinaryOpError(s, other, "+") } } func (s String) Mul(other Object) (Object, error) { switch obj := other.(type) { case Integer: return String{strings.Repeat(s.Value, int(obj.Value))}, nil default: return nil, NewBinaryOpError(s, other, "*") } } 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 }