! char.ax.txt - character and symbol utility predicates ! uses form.ax, ho.ax, bit.ax, natnum.ax ----+----|----+----|----+----|----+----|----+----|----+----|----+----|----+----8 !/ char` - distinguishing atom for a syntax-extension character char - set of (8-bit) characters charseq - sequence of characters pchar - set of printable characters (x20..x7E) dig - decimal digit char ('0' - '9') /dig - a non-digit char ucltr - uppercase letter ('A' - 'Z') lcltr - lowercase letter ('a' - 'z') ltr - upper- or lower-case letter /ucltr - a non-uppercase-letter char /lcltr - a non-lowercase-letter char /ltr - char that is not a letter write - write a "tree" of characters to a flat string lc>uc - map lowercase letters to uppercase (in nested expr) uc>lc - map uppercase " lowercase " ===== symbol utilities ===== sym` - distinguishing atom for a syntax-extension symbol sym - set of syntax-extension symbols *pred - apply predicate to seq of tuples formed from argument sequences (h-o) ===== decimal number representation ===== dec>nat - map digit string to its natural number value nat>dec - map natural number to digit string ("0" for zero) dsym>nat - map digit symbol to natural number nat>dsym - map natural number to digit symbol (_dsym _seq _elem) - select element from seq given decimal symbol index 0.. el>id1 - map seq of elem groups to elem-to-1-digit-index map (skip _n _f) - skip _n iargs, then apply _f to remaining args (repl _idx _uf) - return iarg 0 seq, with unary fn applied to elem [_idx] !\ ! char` - distinguishing atom for a syntax-extension character (char` `char). ! char - set of syntax-extension characters (which have 8 bits) (char (%char_atom %8bits))< (char` %char_atom), (bitseq %8bits), (=l %8bits (7 6 5 4 3 2 1 0)). ! Note that <, <= ordering between chars derives from bit ordering. ! Do we need to define ordering between char and char sequence?? ! charseq - set of character sequences (def charseq (* char)). ! pchar - set of printable characters (x20..x7E) (pchar (%char` %8bits))< ! printable char (char (%char` %8bits)), ! get char atom and its 8 bits (bits %0 %1), ! get 0,1 bit atoms (<= (%0 %0 %1 %0 %0 %0 %0 %0) %8bits), ! x20..x7E (<= %8bits (%0 %1 %1 %1 %1 %1 %1 %0)). !z (one_valid (== %8bits (`0 `0 `1 $)) ! x20..3F !z (== %8bits (`0 `1 $))). ! x40..7F !z ! -- this covers ASCII 20..7F (but we should probably exclude 7F) ! dig - decimal digit char (dig %digit)< (char %digit), (<= '0' %digit), (<= %digit '9'). !or: (finite_set dig "0123456789"). ! /dig - a non-digit char (/dig %/dig)< (char %/dig), (one_valid (< %/dig '0') (< '9' %/dig)). ! ucltr - uppercase letter ('A' - 'Z') (ucltr %ul)< (char %ul), (<= 'A' %ul), (<= %ul 'Z'). ! lcltr - lowercase letter ('a' - 'z') (lcltr %ll)< (char %ll), (<= 'a' %ll), (<= %ll 'z'). ! ltr - upper- or lower-case letter (ltr %l)< (one_valid (ucltr %l) (lcltr %l)). ! /ucltr - char that is not an uppercase letter (/ucltr %/ul)< (char %/ul), (one_valid (< %/ul 'A') (< 'Z' %/ul)). ! /lcltr - char that is not a lowercase letter (/lcltr %/ll)< (char %/l), (one_valid (< %/ll 'A') (< 'Z' %/ll)). ! /ltr - char that is not a letter (/ltr %/l)< (all_valid (/ucltr %/l) (/lcltr %/l)). ! write - write a "tree" of characters to a flat char string (write %c (%c))< (char %c). (write () ()). (write (% $) %chstr)< (write % %chstr1), (write ($) %chstr2), (cat %chstr1 %chstr2 %chstr). c ! lc>uc - map lowercase letters to uppercase (in nested char expr) (lc>uc (%char` (%b7 %b6 %1 $b)) (%char` (%b7 %b6 %0 $b))< ! lc -> uc (lltr (%char` (%b7 %b6 %1 $b))), (bits %0 %1). (lc>uc %c %c)< ! non-lowercase letter char is unchanged (/lltr %c). (lc>uc () ()). ! map nested char seqs (lc>uc (%c $c) (%c' $c'))< (lc>uc %c %c'), (lc>uc ($c) ($c')). ! uc>lc - map uppercase letters to lowercase (in nested char expr) (uc>lc (%char` (%b7 %b6 %0 $b)) (%char` (%b7 %b6 %1 $b))< ! uc -> lc (ultr (%char` (%b7 %b6 %0 $b))), (bits %0 %1). (uc>lc %c %c)< ! non-uppercase letter char is unchanged (/ultr %c). (uc>lc () ()). ! map nested char seqs (uc>lc (%c $c) (%c' $c'))< (uc>lc %c %c'), (uc>lc ($c) ($c')). ! ===== symbol utilities ===== ! sym` - distinguishing atom for a syntax-extension symbol (sym` `). ! alternative: `sym ! sym - set of syntax-extension symbols (sym (%sym` (%c1)))< (sym` %sym`), (pchar %c1), ! 1st symbol char is printable char (/in %c1 " `%$'""!()") ! other than blank ` % $ ' " ! ( ) (sym (%sym` ($cstr %c)))< (sym (%sym` ($cstr))), (pchar %c), ! remaining symbol chars are printable chars (/in %c " ()"). ! other than blank ( ) ! *_pred - map predicate to all tuples formed from argument sequences ! ((%sym` ('*' $pname)) $nulls)< ! pred name begins with letter (sym` %sym`), (copies () ($nulls)). ((%sym` ('*' $pname)) $argseqs')< ((%sym` ($pname)) $args), ((%sym` ('*' $pname)) $argseqs), (distr ($args) ($argseqs) ($argseqs')). ! - don't need (* _pname) h-o form! *pname is more concise ===== decimal number representation ===== ! dec>nat - map decimal digit string to its natural number value ! - null string maps to zero, other strings can have leading zeros (dec>nat () %0)< (zero %0). (dec>nat ($d %d) %n')< (dec>nat ($d) %n), (len (* * * * * * * * * *) %10), ! need constant 10 ! - we can't use decimal 10 since that is what we're trying to define! (t"imes %n %10 %10n), (ord dig %d %k), ! get "ordinal" value of a finite set element (plus %10n %k %n'). ! nat>dec - map natural number to decimal digit string ! - zero maps to 0, everything else has non-zero leading digit (nat>dec %z "0")< ! we don't use null string for decimal number repr (zero %z). (nat>dec %n (%d $d))< ! other decimal numbers have non-zero leading digit (dec>nat (%d $d) %n), (< '0' %d). ! dsym>nat - map decimal digit symbol to natural number (dsym>nat (%sym` %dstr) %n)< (sym` %sym`), (dec>nat %dstr %n). ! Note that null-string symbol maps to zero, but that shouldn't cause prob. ! nat>dsym - map natural number to decimal digit symbol (nat>dsym %n (%sym` %dstr))< (sym` %sym`), (nat>dec %n %dstr). ! (_dsym _seq _elem) - select element from seq given decimal symbol index 0.. (%dsym %seq %elem)< ! decimal symbol is the selection function name! (dsym>nat %dsym %nat), ! get natural number value of decimal symbol (sel# %nat %seq %elem). ! select sequence element given nat num index ! el>id1 - map seq of elem groups to elem-to-1-digit-index map ! phonecode example: ! (el>id1 ("e" "jnq" ... "ghz") (('e' '0') ('j' '1') ('n' '1') ... ('z' '9'))) ! -- works for <=10 groups (def el>id1 (dup len iota0n- *nat>dig *0 pair rev *pair ! (("e" '0')) ("jnq" '1') ... ("ghz" '9')) ) (* (bun (*1 pair))) cat*)). ! (('e' '0') ('j' '1') ('n' '1') ... ('z' '9')) !/ expanded: (def el>id1 ! ("e" "jnq" ... "ghz" (dup len iota0n- *nat>dig ! ("0" "1" ... "9") ("e" "jnq" ... "ghz") *0 pair rev *pair ! (("e" '0')) ("jnq" '1') ... ("ghz" '9')) (* (bun (*1 pair))) cat* ! (('e' '0') ('j' '1') ('n' '1') ... ('z' '9')) ) ). (def el>id1 - map seq of seqs to element-to-1-digit map ( ! using input example ...: ("e" "jnq" ... "ghz") dup ! duplicate first arg ! ("e" "jnq" ... "ghz") ("e" ... "ghz") len ! get natural number length of arg sequence (= 10) ! _n10 ("e" ... "ghz") - seq len must be <= 10 for 1-dig indices! iota0n- ! get vector of natural numbers 0..9 given length 10 ! (_n0 .. _n9) ("e" ... "ghz") *nat>dig ! convert vector of natural numbers to digit strings ! ("0" .. "9") ("e" ... "ghz") *0 ! sel elem [0] (first digit) of each number string ! ('0' .. '9') ("e" ... "ghz") ! (this works only when we have <=10 elem groups!) pair ! pair the first two args into one expr ! (('0' .. '9') ("e" .. "ghz")) rev ! reverse the pair components to put the elem groups first ! (("e" .. "ghz") ('0' .. '9')) *pair ! pair elem groups and digits ! (("e" '0') .. ("ghz" '9')) (* (bun (*1 pair))) ! (unary) pair each group element with its digit ! (*1 pair) pairs all elems in 0th arg seq with arg 1 ! (bun _binop) makes binary op unary ! - the two args for _binop are components of a 2-elem seq arg ! ((('e' '0')) .. (('g' '9') ('h' '9') ('z' '9'))) ! - note that element groups are still grouped cat* ! concatenate letter groups into flat elem-to-digit map ! (('e' '0') .. ('g' '9') ('h' '9') ('z' '9')) )). ! - function result on phonecode input! !\ ! (skip _dsym _f) - skip _dsym iargs, then apply _f to remaining args (((skip %dsym %f) $f) $iaskip $args)< (dsym>nat %dsym %n), (len ($iaskipd) %n), ! skip n input args ((%f $f) $args). ! then apply fn to remaining args in composition ! (repl _dsym _uf) - return iarg0 seq, with unary fn applied to elem [_dsym] (((repl %dsym %uf) $f) ($pre %ex $suf) $args)< (dsym>nat %dsym %n), (len ($pre) %n), (%uf %ex %ex'), ! apply unary fn to nth elem of 1st arg (($f) ($pre %ex' $suf) $args). ! replace that elem with result