summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-09-18 17:23:05 -0700
committerKaz Kylheku <kaz@kylheku.com>2016-09-18 17:23:05 -0700
commit5eb43586824efc00a733df1df6a2420c90bf3eb2 (patch)
tree368148fd4a052f78f1c59216fba80e9ffa3e4646
parent0bdd5c59675cce09791d51c8d533a9d14ca8da56 (diff)
downloadtxr-5eb43586824efc00a733df1df6a2420c90bf3eb2.tar.gz
txr-5eb43586824efc00a733df1df6a2420c90bf3eb2.tar.bz2
txr-5eb43586824efc00a733df1df6a2420c90bf3eb2.zip
New awk operator: fconv.
* share/txr/stdlib/awk.tl (sys:awk-let): Add new symbol macro, fconv. * share/txr/stdlib/conv.tl: New file. * txr.1: Documented fconv.
-rw-r--r--share/txr/stdlib/awk.tl6
-rw-r--r--share/txr/stdlib/conv.tl83
-rw-r--r--txr.1113
3 files changed, 201 insertions, 1 deletions
diff --git a/share/txr/stdlib/awk.tl b/share/txr/stdlib/awk.tl
index bc5dc9dd..b1e9f509 100644
--- a/share/txr/stdlib/awk.tl
+++ b/share/txr/stdlib/awk.tl
@@ -23,6 +23,8 @@
;; AND UNDER ANY THEORY OF LIABILITY, ARISING IN ANY WAY OUT OF THE USE OF THIS
;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+(load "conv.tl")
+
(defstruct sys:awk-state ()
(rs "\n") krs
fs ft kfs
@@ -202,7 +204,9 @@
(set f [(opip ,*opip-args) f])))
(mf (. opip-args)
^(symacrolet ((f (rslot ,',aws-sym 'fields 'f-to-rec)))
- (set f (mapcar (opip ,*opip-args) f)))))
+ (set f (mapcar (opip ,*opip-args) f))))
+ (fconv (. conv-args)
+ ^(set f (sys:conv (,*conv-args) f))))
,*body)))
(defmacro awk (:env e . clauses)
diff --git a/share/txr/stdlib/conv.tl b/share/txr/stdlib/conv.tl
new file mode 100644
index 00000000..546b8759
--- /dev/null
+++ b/share/txr/stdlib/conv.tl
@@ -0,0 +1,83 @@
+;; Copyright 2016
+;; Kaz Kylheku <kaz@kylheku.com>
+;; Vancouver, Canada
+;; All rights reserved.
+;;
+;; Redistribution of this software in source and binary forms, with or without
+;; modification, is permitted provided that the following two conditions are met.
+;;
+;; Use of this software in any manner constitutes agreement with the disclaimer
+;; which follows the two conditions.
+;;
+;; 1. Redistributions of source code must retain the above copyright
+;; notice, this list of conditions and the following disclaimer.
+;; 2. Redistributions in binary form must reproduce the above copyright
+;; notice, this list of conditions and the following disclaimer in
+;; the documentation and/or other materials provided with the
+;; distribution.
+;;
+;; THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+;; WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+;; MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE
+;; COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DAMAGES, HOWEVER CAUSED,
+;; AND UNDER ANY THEORY OF LIABILITY, ARISING IN ANY WAY OUT OF THE USE OF THIS
+;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+(defun sys:conv-let (. body)
+ ^(flet ((i (arg : radix)
+ (toint arg radix))
+ (o (arg)
+ (toint arg 8))
+ (x (arg)
+ (toint arg 16))
+ (b (arg)
+ (toint arg 2))
+ (r (arg)
+ (tofloat arg)))
+ ,*body))
+
+(defun sys:do-conv (lfl mfl tfl nm list)
+ (while (and list lfl)
+ (set (car list) (call (car lfl) (car list)))
+ (set list (cdr list))
+ (set lfl (cdr lfl)))
+ (dotimes (i nm)
+ (unless list
+ (return))
+ (when mfl
+ (set (car list) (call (car mfl) (car list)))
+ (set mfl (cdr mfl)))
+ (set list (cdr list)))
+ (while (and list tfl)
+ (set (car list) (call (car tfl) (car list)))
+ (set list (cdr list))
+ (set tfl (cdr tfl))))
+
+(defun sys:conv-expand (form specs list-sym)
+ (mac-param-bind form (lead : mid trail)
+ (split* (mapcar [iff (op eq :)
+ identity
+ [iff (op eq '-)
+ (retf '(fun identity))
+ (ret ^[identity ,@1])]]
+ specs)
+ (op where (op eq :)))
+ (let ((nl (length lead))
+ (nt (length trail)))
+ (with-gensyms (i nm lfl mfl tfl)
+ (sys:conv-let
+ ^(let* ((,nm (- (length ,list-sym) ,(+ nl nt)))
+ (,lfl (list ,*lead))
+ (,mfl (if (plusp ,nm) (repeat (list ,*mid))))
+ (,tfl (list ,*trail)))
+ (sys:do-conv ,lfl ,mfl ,tfl ,nm ,list-sym)))))))
+
+(defmacro sys:conv (:form form (. specs) list-expr)
+ (cond
+ ((null specs) list-expr)
+ ((atom specs)
+ (throwf 'eval-error "sys:conv: invalid conversion list: ~s" specs))
+ (t (with-gensyms (list-sym)
+ ^(let ((,list-sym ,list-expr))
+ ,(sys:conv-expand form specs list-sym)
+ ,list-sym)))))
diff --git a/txr.1 b/txr.1
index 8e95088d..cc972dff 100644
--- a/txr.1
+++ b/txr.1
@@ -38260,6 +38260,119 @@ a binding which shadows
(mf flo-str)
.cble
+.coNP Macro @ fconv
+.synb
+.mets (fconv >> { clause | : | - }*)
+.syne
+.desc
+The awk macro
+.code fconv
+provides a succinct way to request conversions of the textual fields.
+Conversions are expressed by clauses which correspond with fields.
+
+Each
+.code clause
+is an expression which must evaluate to a function. The clause is evaluated
+in the same manner as the argument a
+.code dwim
+operator, using Lisp-1-style name lookup. Thus, functions may be
+specified simply by using their name as a
+.metn clause .
+
+Furthermore, several local functions exist in the scope of each
+.codn clause ,
+providing a short-hand notation. These are described below.
+
+Conversion proceeds by applying the function produced by
+a clause to the field to which that clause corresponds, positionally.
+The return value of the function applied to the field replaces
+the field.
+
+When a clause is specified as the symbol
+.code -
+(minus)
+it has a special meaning: this minus clause occupies a field
+position and corresponds to a field, but performs no conversion
+on its field.
+
+The
+.code :
+(colon)
+symbol isn't a clause and does not correspond to a field position.
+Rather, it acts as a separator among clauses. It need not appear at
+all. If it appears, it may appear at most twice. Thus, the
+clauses may be separated into up to three sequences.
+
+If the colon does not appear, then all the clauses are
+.IR "prefix clauses" .
+Prefix clauses line up with fields from left to right. If there are fewer
+fields than prefix clauses, the values of the excess clauses are evaluated, but
+ignored.
+.IR "Vice versa" ,
+if there are fewer prefix clauses than fields, then the excess
+fields are not subject to conversions.
+
+If the colon appears once, then the clauses before the colon, if any, are
+prefix clauses, as described in the previous paragraph. Clauses after the
+colon, if any, are
+.IR "interior clauses" .
+Interior clauses apply to any fields which are left unconverted by the prefix
+clauses. All interior clauses are evaluated. If there are fewer fields than
+interior clauses, then the values of the excess interior clauses are ignored.
+If there are more fields than clauses, then the clause values are cycled:
+re-used from the beginning against the excess fields, enough times to convert
+all the fields.
+
+If the colon appears twice, then the clauses before the first colon, if any,
+are prefix clauses, the clauses between the two clause are interior clauses,
+and those after the second colon are
+.IR "suffix clauses" .
+The presence of suffix clauses change the behavior relative to the one-colon
+case as follows. After the conversions are performed according to the prefix
+clauses, the remaining fields are counted. If there are are only as many
+fields as there are suffix clauses, or fewer, then the interior clauses are
+evaluated, but ignored. The remaining fields are processed against the suffix
+clauses. If after processing the prefix clauses there are more fields
+remaining than suffix clauses, then a number of rightmost fields equal to the
+number of suffix clauses is reserved for those clauses. The interior fields
+are applied only to the unreserved middle fields which precede these reserved
+rightmost fields, using the same repeating behavior as in the one-colon case.
+Finally, the previously reserved rightmost fields are processed using
+the suffix clauses.
+
+The following special convenience functions are in scope of the clauses,
+effectively providing a short-hand for commonly-needed conversions:
+.RS
+.coIP i
+Provides conversion to integer. It is identical to the
+.code toint
+function.
+.coIP o
+Converts a string value holding an octal representation
+to the integer which it denotes. The expression
+.code "(o str)"
+is equivalent to
+.codn "(toint str 8)" .
+.coIP x
+Converts a string value holding a hexadecimal representation
+to the integer which it denotes. The expression
+.code "(x str)"
+is equivalent to
+.codn "(toint str 16)" .
+.coIP b
+Converts a string value holding a binary (base two) representation
+to the integer which it denotes. The expression
+.code "(c str)"
+is equivalent to
+.codn "(toint str 2)" .
+.coIP r
+Converts a string holding a floating-point representation to
+the floating-point value which it denotes. The expression
+.code "(r str)"
+is equivalent to
+.codn "(tofloat str)" .
+.RE
+
.SS* Environment Variables and Command Line
Note that environment variable names, their values, and command line