Files
argon-v3/src/sortany.go
2023-03-26 22:04:57 +01:00

88 lines
1.8 KiB
Go

package main
import "fmt"
type keyCache map[interface{}]interface{}
func quickSort(list []interface{}, getKey func(interface{}) (interface{}, ArErr)) ([]interface{}, ArErr) {
if len(list) <= 1 {
return list, ArErr{}
}
pivot := list[0]
var left []interface{}
var right []interface{}
var cache = make(keyCache)
for _, v := range list[1:] {
val, err := getkeyCache(getKey, v, cache)
if err.EXISTS {
return nil, err
}
pivotval, err := getkeyCache(getKey, pivot, cache)
if err.EXISTS {
return nil, err
}
comp, comperr := compare(val, pivotval)
if comperr != nil {
return nil, ArErr{
TYPE: "TypeError",
message: comperr.Error(),
EXISTS: true,
}
}
if comp {
left = append(left, v)
} else {
right = append(right, v)
}
}
left, err := quickSort(left, getKey)
if err.EXISTS {
return nil, err
}
right, err = quickSort(right, getKey)
if err.EXISTS {
return nil, err
}
return append(append(left, pivot), right...), ArErr{}
}
func getkeyCache(getKey func(interface{}) (interface{}, ArErr), index interface{}, cache keyCache) (interface{}, ArErr) {
key := ArValidToAny(index)
if cacheval, ok := cache[key]; ok {
return cacheval, ArErr{}
}
val, err := getKey(index)
if err.EXISTS {
return nil, err
}
cache[key] = val
return val, ArErr{}
}
func compare(a, b any) (bool, error) {
if isAnyNumber(a) && isAnyNumber(b) {
return a.(number).Cmp(b.(number)) < 0, nil
} else if x, ok := a.(ArObject); ok {
if y, ok := x.obj["__LessThan__"]; ok {
resp, err := runCall(
call{
callable: y,
args: []any{b},
}, stack{}, 0)
if !err.EXISTS {
return anyToBool(resp), nil
}
}
} else if x, ok := b.(byte); ok {
if y, ok := a.(byte); ok {
return y < x, nil
}
}
return false, fmt.Errorf("cannot compare %s to %s", typeof(a), typeof(b))
}