package object import ( "bytes" "fmt" "strings" ) // Array is the array literal type that holds a slice of Object(s) type Array struct { Elements []Object } func (ao *Array) Type() Type { return ArrayType } func (ao *Array) Bool() bool { return len(ao.Elements) > 0 } func (ao *Array) PopLeft() Object { if len(ao.Elements) > 0 { e := ao.Elements[0] ao.Elements = ao.Elements[1:] return e } return Null{} } func (ao *Array) PopRight() Object { if len(ao.Elements) > 0 { e := ao.Elements[(len(ao.Elements) - 1)] ao.Elements = ao.Elements[:(len(ao.Elements) - 1)] return e } return Null{} } func (ao *Array) Prepend(obj Object) { ao.Elements = append([]Object{obj}, ao.Elements...) } func (ao *Array) Append(obj Object) { ao.Elements = append(ao.Elements, obj) } func (ao *Array) Inspect() string { var out bytes.Buffer var elements []string for _, e := range ao.Elements { elements = append(elements, e.Inspect()) } out.WriteString("[") out.WriteString(strings.Join(elements, ", ")) out.WriteString("]") return out.String() } func (ao *Array) String() string { return ao.Inspect() } func (a *Array) Less(i, j int) bool { return a.Elements[i].Compare(a.Elements[j]) == -1 } func (a *Array) Add(other Object) (Object, error) { switch obj := other.(type) { case *Array: var elements []Object elements = append(elements, a.Elements...) elements = append(elements, obj.Elements...) return &Array{Elements: elements}, nil default: return nil, NewBinaryOpError(a, other, "+") } } func (a *Array) Mul(other Object) (Object, error) { switch obj := other.(type) { case Integer: var elements []Object N := int(obj.Value) for i := 0; i < N; i++ { elements = append(elements, a.Elements...) } return &Array{Elements: elements}, nil default: return nil, NewBinaryOpError(a, other, "*") } } func (ao *Array) Get(index Object) (Object, error) { if !AssertTypes(index, IntegerType) { return nil, fmt.Errorf("invalid type for array index, expected Integer got %s", index.Type()) } i := index.(Integer).Value N := int64(len(ao.Elements)) if i < 0 || i >= N { return Null{}, nil } return ao.Elements[i], nil } func (ao *Array) Set(index, other Object) error { if !AssertTypes(index, IntegerType) { return fmt.Errorf("invalid type for array index, expected Integer got %s", index.Type()) } i := index.(Integer).Value N := int64(len(ao.Elements)) if i < 0 || i >= N { return fmt.Errorf("index out of bounds %d with array length %d", i, N) } ao.Elements[i] = other return nil } func (a *Array) Compare(other Object) int { if obj, ok := other.(*Array); ok { if len(a.Elements) != len(obj.Elements) { return -1 } for i, el := range a.Elements { val := el.Compare(obj.Elements[i]) if val != 0 { return val } } return 0 } return -1 } func (ao *Array) Copy() *Array { elements := make([]Object, len(ao.Elements)) for i, e := range ao.Elements { elements[i] = e } return &Array{Elements: elements} } func (ao *Array) Reverse() { for i, j := 0, len(ao.Elements)-1; i < j; i, j = i+1, j-1 { ao.Elements[i], ao.Elements[j] = ao.Elements[j], ao.Elements[i] } } func (ao *Array) Len() int { return len(ao.Elements) } func (ao *Array) Swap(i, j int) { ao.Elements[i], ao.Elements[j] = ao.Elements[j], ao.Elements[i] }