// Wraps a string and provides operations for that string. // // * len - property representing the length of the string in characters. // // * str - property the wrapped string. // // * split_on - module that splits the string on a character. // - `on` field represents the string to split on. // // * split_at - function splits the wrapped string at an character index. // // * substr - module that returns a substr of the wrapped string. // - `start` field is the index at which the substr starts (defaults to 0) // - `end` field is the index at which the substr ends (defaults to end of string) let ops = module { str="", } => ({len=len, str=str, chars=chars, split_on=split_on, split_at=split_at, substr=substr, }) { let len = import "std/lists.ucg".len(mod.str); let str = mod.str; let chars = reduce(func(acc, char) => acc + [char], [], mod.str); let split_on = module{ on=" ", buf = "", out = [], str=mod.str, } => (result) { let recurse = module { buf = "", acc = [], str = mod.str, sep = NULL, } => (result) { (mod.sep != NULL) || fail "mod.sep can not be NULL"; let pkg = mod.pkg(); let this = mod.this; let check_str = pkg.ops{str=mod.str}; let split_str = pkg.ops{str=mod.sep}; let maybe_prefix = check_str.substr{end=split_str.len - 1}; let maybe_suffix = check_str.substr{start=split_str.len}; let result = select (maybe_prefix.len == 0) => { // terminal condition true = mod.acc + [mod.buf], //true = mod, // recurse condition. false = select (maybe_prefix.str == mod.sep) => { true = this{ // this is a match to our separator str=maybe_suffix.str, sep=mod.sep, acc=mod.acc + [mod.buf], }, false = this{ buf=mod.buf + check_str.chars.0, str=check_str.substr{start=1}.str, sep=mod.sep, acc=mod.acc, }, }, }; }; let result = recurse{sep=mod.on, str=mod.str}; }; let split_at = func(idx) => filter( func(name, val) => name != "counter", reduce( func(acc, char) => acc{ counter = acc.counter + 1, left = select (acc.counter < idx, acc.left) => { true = acc.left + char, }, right = select (acc.counter >= idx, acc.right) => { true = acc.right + char, }, }, {counter = 0, left = "", right = ""}, mod.str ) ); let substr = module{ str = mod.str, start = 0, end = len, } => (result) { let pkg = mod.pkg(); let reducer = func(acc, char) => acc{ counter = acc.counter + 1, str = select ((acc.counter >= mod.start) && (acc.counter <= mod.end), acc.str) => { true = acc.str + char, }, }; let result = pkg.ops{str=reduce( reducer, {counter = 0, str = ""}, mod.str).str}; }; };