From 2bad76314f90cb871122b8395feddf79c1de843e Mon Sep 17 00:00:00 2001 From: Hans Svensson Date: Mon, 24 Feb 2020 15:34:23 +0100 Subject: [PATCH] More efficient implementations in String.aes --- priv/stdlib/String.aes | 63 +++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/priv/stdlib/String.aes b/priv/stdlib/String.aes index db5242f..9e9efb2 100644 --- a/priv/stdlib/String.aes +++ b/priv/stdlib/String.aes @@ -15,30 +15,41 @@ namespace String = (StringInternal.from_list(List.take(i, cs)), StringInternal.from_list(List.drop(i, cs))) function at(ix : int, s : string) = - switch(List.drop(ix - 1, StringInternal.to_list(s))) + switch(List.drop(ix, StringInternal.to_list(s))) [] => None x :: _ => Some(x) - function tokens(s : string, pat : string) = - let pat_len = StringInternal.length(pat) - tokens_(StringInternal.to_list(pat), StringInternal.to_list(s), []) - function to_upper(s : string) = - StringInternal.from_list([ Char.to_upper(c) | c <- StringInternal.to_list(s) ]) + StringInternal.from_list(List.map(Char.to_upper, StringInternal.to_list(s))) function to_lower(s : string) = - StringInternal.from_list([ Char.to_lower(c) | c <- StringInternal.to_list(s) ]) + StringInternal.from_list(List.map(Char.to_lower, StringInternal.to_list(s))) function contains(str : string, substr : string) : option(int) = - let last_ix = StringInternal.length(str) - (StringInternal.length(substr) - 1) - contains_(1, last_ix, StringInternal.to_list(str), StringInternal.to_list(substr)) + if(substr == "") Some(0) + else + contains_(0, StringInternal.to_list(str), StringInternal.to_list(substr)) - function - to_int : (string, int) => option(int) - to_int(s, 10) = to_int_(List.reverse(StringInternal.to_list(s)), ch_to_int_10, 0, 1, 10) - to_int(s, 16) = to_int_(List.reverse(StringInternal.to_list(s)), ch_to_int_16, 0, 1, 16) + function tokens(s : string, pat : string) = + require(pat != "", "String.tokens: empty pattern") + tokens_(StringInternal.to_list(pat), StringInternal.to_list(s), []) - function + function to_int(s : string) : option(int) = + let s = StringInternal.to_list(s) + switch(is_prefix(['-'], s)) + None => to_int_pos(s) + Some(s) => switch(to_int_pos(s)) + None => None + Some(x) => Some(-x) + + private function to_int_pos(s : list(char)) = + switch(is_prefix(['0', 'x'], s)) + None => + to_int_(s, ch_to_int_10, 0, 10) + Some(s) => + to_int_(s, ch_to_int_16, 0, 16) + + private function tokens_(_, [], acc) = [StringInternal.from_list(List.reverse(acc))] tokens_(pat, str, acc) = switch(is_prefix(pat, str)) @@ -48,36 +59,36 @@ namespace String = let c :: cs = str tokens_(pat, cs, c :: acc) - function contains_(ix, lix, str, substr) = - if(ix > lix) None - else + private function + contains_(_, [], _) = None + contains_(ix, str, substr) = switch(is_prefix(substr, str)) None => let _ :: str = str - contains_(ix + 1, lix, str, substr) + contains_(ix + 1, str, substr) Some(_) => Some(ix) - function + private function is_prefix([], ys) = Some(ys) is_prefix(_, []) = None is_prefix(x :: xs, y :: ys) = if(x == y) is_prefix(xs, ys) else None - function - to_int_([], _, x, _, _) = Some(x) - to_int_(i :: is, c, x, t, f) = - switch(c(i)) + private function + to_int_([], _, x, _) = Some(x) + to_int_(i :: is, value, x, b) = + switch(value(i)) None => None - Some(i) => to_int_(is, c, x + t * i, t * f, f) + Some(i) => to_int_(is, value, x * b + i, b) - function ch_to_int_10(c) = + private function ch_to_int_10(c) = let c = Char.to_int(c) if(c >= 48 && c =< 57) Some(c - 48) else None - function ch_to_int_16(c) = + private function ch_to_int_16(c) = let c = Char.to_int(c) if(c >= 48 && c =< 57) Some(c - 48) elif(c >= 65 && c =< 70) Some(c - 55)