From de95c3e8b57c88c291abaa544a9db4387e59df56 Mon Sep 17 00:00:00 2001 From: William Bell Date: Sun, 26 Mar 2023 21:55:03 +0100 Subject: [PATCH] add sort to strings --- src/sortany.go | 4 +++ src/string.go | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/src/sortany.go b/src/sortany.go index c090a77..19261f5 100644 --- a/src/sortany.go +++ b/src/sortany.go @@ -78,6 +78,10 @@ func compare(a, b any) (bool, error) { 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)) } diff --git a/src/string.go b/src/string.go index 2fe649c..eace6e0 100644 --- a/src/string.go +++ b/src/string.go @@ -366,6 +366,80 @@ func ArString(str string) ArObject { } return strings.Count(str, a[0].(string)), ArErr{} }} + + obj.obj["sort"] = builtinFunc{ + "sort", + func(args ...any) (any, ArErr) { + if len(args) > 2 { + return nil, ArErr{ + TYPE: "TypeError", + message: "too many arguments", + EXISTS: true, + } + } + reverse := false + if len(args) >= 1 { + if typeof(args[0]) != "boolean" { + return nil, ArErr{ + TYPE: "TypeError", + message: "argument must be a boolean", + EXISTS: true, + } + } + reverse = args[0].(bool) + } + bytes := []byte(str) + anyarr := make([]any, len(bytes)) + for i, b := range bytes { + anyarr[i] = b + } + if len(args) == 2 { + if typeof(args[1]) != "function" { + return nil, ArErr{ + TYPE: "TypeError", + message: "argument must be a function", + EXISTS: true, + } + } + output, err := quickSort(anyarr, func(a any) (any, ArErr) { + return runCall(call{ + args[1], + []any{a}, "", 0, "", + }, stack{}, 0) + }) + if err.EXISTS { + return nil, err + } + bytes = make([]byte, len(output)) + for i, b := range output { + bytes[i] = b.(byte) + } + str = string(bytes) + obj.obj["length"] = len(str) + obj.obj["__value__"] = str + return nil, ArErr{} + } + output, err := quickSort(anyarr, func(a any) (any, ArErr) { + return a, ArErr{} + }) + if err.EXISTS { + return nil, err + } + if reverse { + for i, j := 0, len(output)-1; i < j; i, j = i+1, j-1 { + output[i], output[j] = output[j], output[i] + } + } + bytes = make([]byte, len(output)) + for i, b := range output { + bytes[i] = b.(byte) + } + str = string(bytes) + obj.obj["length"] = len(str) + obj.obj["__value__"] = str + return nil, ArErr{} + }, + } obj.obj["strip"] = builtinFunc{ "strip", func(a ...any) (any, ArErr) {