diff --git a/README.md b/README.md index 3054bdd..fffb75d 100644 --- a/README.md +++ b/README.md @@ -194,7 +194,7 @@ Iterate a datastructure (as if with `?txpr`) and collect the matches in a new ### Transformer Operators - `?xpr`, `?txpr`, `?mxpr` -Perform operation on when pattern or condition is satisfied: +Perform operation when pattern or condition is satisfied: - `(?xpr sel)`: match current value against `EXPR Selector`. Return the result if not `nil`. - `(?xpr sel hit-expr)`: match current value against `EXPR Selector`. @@ -203,8 +203,8 @@ Perform operation on when pattern or condition is satisfied: selectors`. Evaluate `hit-expr` if not `nil`; else evaluate `miss-expr`. `_` is the matching item. -Recursively traverse a structure of `sequences` and `hts` and return -a new value for each match: +Recursively traverse a nested structure of `sequences` and `hts` and return a +new value for each match: - `(?txpr sel .. tx-expr)`: recursively traverse current value and replace matches with `tx-expr`. `tx-expr` can be a function name or expression. Also traverses vectors and `ht` values. diff --git a/bin/test-sh.sh b/bin/test-sh.sh index 9226605..c0e310e 100755 --- a/bin/test-sh.sh +++ b/bin/test-sh.sh @@ -60,12 +60,12 @@ a='[{"v":1},{"v":1},{"v":7},{"v":100}]' r=`echo '1 x 1 x 7 x 100' |\ sbcl --script ./tqn-sh.lisp -jm '(splt _ :x) int!? #((new$ :v _))'`; check; -a='((:V . 1)) -((:V . 3))' +a='((:v . 1)) +((:v . 3))' r=`echo '1 x 3 x ' |\ sbcl --script ./tqn-sh.lisp '(splt _ :x) int!? [is?] #((new$ :v _))'`; check; -a='#(((:V . 1)) ((:V . 1)) ((:V . 7)) ((:V . 100)))' +a='#(((:v . 1)) ((:v . 1)) ((:v . 7)) ((:v . 100)))' r=`echo '1 x 1 x 7 x 100' |\ sbcl --script ./tqn-sh.lisp -lm '(splt _ :x) int!? #((new$ :v _))'`; check; @@ -86,7 +86,7 @@ r=`echo '1 2' | sbcl --script ./jqn-sh.lisp -t '_'`; check; a='{"_id":1}' r=`echo '{"_id": 1}' | sbcl --script ./jqn-sh.lisp -jm '{:_id}'`; check; -a='((:_ID . 1))' +a='((:_id . 1))' r=`echo '{"_id": 1}' | sbcl --script ./jqn-sh.lisp -lm '{:_id}'`; check; a='{"_id":"65679","things":[{"id":10}]} diff --git a/docs/lqn.md b/docs/lqn.md index 0e3be1f..1f374bd 100644 --- a/docs/lqn.md +++ b/docs/lqn.md @@ -1,6 +1,4 @@ -# Lisp Query Notation Symbol Documentation (2.0.2) - -#### LQN:?? +# Lisp Query Notation Symbol Documentation (2.1.0) ``` ; LQN:?? @@ -13,8 +11,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:@\* - ``` ; LQN:@* ; [symbol] @@ -28,8 +24,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:@@ - ``` ; LQN:@@ ; [symbol] @@ -42,8 +36,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:ALL? - ``` ; LQN:ALL? ; [symbol] @@ -56,8 +48,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:APPLY\* - ``` ; LQN:APPLY* ; [symbol] @@ -69,8 +59,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:ASCII - ``` ; LQN:ASCII ; [symbol] @@ -83,8 +71,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:BAR - ``` ; LQN:BAR ; [symbol] @@ -98,8 +84,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:CAT$ - ``` ; LQN:CAT$ ; [symbol] @@ -113,8 +97,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:CAT\* - ``` ; LQN:CAT* ; [symbol] @@ -131,8 +113,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:CD - ``` ; LQN:CD ; [symbol] @@ -145,8 +125,6 @@ ; Source file: /data/x/lqn/src/sh.lisp ``` -#### LQN:CLMP - ``` ; LQN:CLMP ; [symbol] @@ -160,8 +138,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:CMD - ``` ; LQN:CMD ; [symbol] @@ -174,8 +150,6 @@ ; Source file: /data/x/lqn/src/sh.lisp ``` -#### LQN:COMPCT - ``` ; LQN:COMPCT ; [symbol] @@ -188,8 +162,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:CWD - ``` ; LQN:CWD ; [symbol] @@ -202,8 +174,6 @@ ; Source file: /data/x/lqn/src/sh.lisp ``` -#### LQN:D? - ``` ; LQN:D? ; [symbol] @@ -216,8 +186,6 @@ ; Source file: /data/x/lqn/src/init.lisp ``` -#### LQN:DAT-EXPORT - ``` ; LQN:DAT-EXPORT ; [symbol] @@ -231,8 +199,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:DAT-READ-FILE - ``` ; LQN:DAT-READ-FILE ; [symbol] @@ -245,8 +211,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:DAT-READ-FILES - ``` ; LQN:DAT-READ-FILES ; [symbol] @@ -259,8 +223,6 @@ ; Source file: /data/x/lqn/src/qry-extra.lisp ``` -#### LQN:DAT-READ-ONE - ``` ; LQN:DAT-READ-ONE ; [symbol] @@ -273,8 +235,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:DAT-READ-STREAM - ``` ; LQN:DAT-READ-STREAM ; [symbol] @@ -287,8 +247,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:DIR? - ``` ; LQN:DIR? ; [symbol] @@ -301,8 +259,6 @@ ; Source file: /data/x/lqn/src/sh.lisp ``` -#### LQN:EMPTY? - ``` :missing:todo: @@ -315,8 +271,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:FILE? - ``` ; LQN:FILE? ; [symbol] @@ -329,8 +283,6 @@ ; Source file: /data/x/lqn/src/sh.lisp ``` -#### LQN:FLATALL\* - ``` ; LQN:FLATALL* ; [symbol] @@ -344,8 +296,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:FLATN$ - ``` ; LQN:FLATN$ ; [symbol] @@ -358,8 +308,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:FLATN\* - ``` ; LQN:FLATN* ; [symbol] @@ -373,8 +321,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:FLT! - ``` ; LQN:FLT! ; [symbol] @@ -387,8 +333,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:FLT!? - ``` ; LQN:FLT!? ; [symbol] @@ -401,8 +345,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:FLT? - ``` ; LQN:FLT? ; [symbol] @@ -415,8 +357,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:FMT - ``` ; LQN:FMT ; [symbol] @@ -428,8 +368,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:HEAD - ``` ; LQN:HEAD ; [symbol] @@ -446,8 +384,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:IND\* - ``` ; LQN:IND* ; [symbol] @@ -461,8 +397,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:INT! - ``` ; LQN:INT! ; [symbol] @@ -475,8 +409,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:INT!? - ``` ; LQN:INT!? ; [symbol] @@ -489,8 +421,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:INT? - ``` ; LQN:INT? ; [symbol] @@ -503,8 +433,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:IPREF? - ``` ; LQN:IPREF? ; [symbol] @@ -517,8 +445,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:IS? - ``` ; LQN:IS? ; [symbol] @@ -531,8 +457,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:ISUB? - ``` ; LQN:ISUB? ; [symbol] @@ -546,8 +470,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:ISUBX? - ``` ; LQN:ISUBX? ; [symbol] @@ -562,8 +484,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:ISUF? - ``` ; LQN:ISUF? ; [symbol] @@ -577,8 +497,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:JOIN - ``` ; LQN:JOIN ; [symbol] @@ -590,8 +508,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:JSNLOADF - ``` ; LQN:JSNLOADF ; [symbol] @@ -604,8 +520,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:JSNLOADS - ``` ; LQN:JSNLOADS ; [symbol] @@ -618,8 +532,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:JSNOUT - ``` ; LQN:JSNOUT ; [symbol] @@ -633,8 +545,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:JSNQRYF - ``` ; LQN:JSNQRYF ; [symbol] @@ -646,8 +556,6 @@ ; Source file: /data/x/lqn/src/qry-operators.lisp ``` -#### LQN:JSNSTR - ``` ; LQN:JSNSTR ; [symbol] @@ -661,8 +569,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:KEYS? - ``` ; LQN:KEYS? ; [symbol] @@ -675,8 +581,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:KV? - ``` ; LQN:KV? ; [symbol] @@ -689,8 +593,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:KW? - ``` ; LQN:KW? ; [symbol] @@ -703,8 +605,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:LDNLOAD - ``` ; LQN:LDNLOAD ; [symbol] @@ -717,8 +617,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:LDNOUT - ``` ; LQN:LDNOUT ; [symbol] @@ -733,8 +631,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:LINSPACE - ``` ; LQN:LINSPACE ; [symbol] @@ -748,8 +644,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:LPAD - ``` ; LQN:LPAD ; [symbol] @@ -762,8 +656,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:LS - ``` ; LQN:LS ; [symbol] @@ -776,8 +668,6 @@ ; Source file: /data/x/lqn/src/sh.lisp ``` -#### LQN:LST! - ``` ; LQN:LST! ; [symbol] @@ -790,8 +680,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:LST!? - ``` ; LQN:LST!? ; [symbol] @@ -804,8 +692,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:LST? - ``` ; LQN:LST? ; [symbol] @@ -818,8 +704,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:MSYM? - ``` ; LQN:MSYM? ; [symbol] @@ -833,8 +717,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:NEW$ - ``` ; LQN:NEW$ ; [symbol] @@ -846,8 +728,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:NEW\* - ``` ; LQN:NEW* ; [symbol] @@ -859,8 +739,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:NONE? - ``` ; LQN:NONE? ; [symbol] @@ -873,8 +751,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:NOOP - ``` ; LQN:NOOP ; [symbol] @@ -886,8 +762,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:NOW - ``` ; LQN:NOW ; [symbol] @@ -900,8 +774,6 @@ ; Source file: /data/x/lqn/src/sh.lisp ``` -#### LQN:NSTR - ``` ; LQN:NSTR ; [symbol] @@ -915,8 +787,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:NUM!? - ``` ; LQN:NUM!? ; [symbol] @@ -929,8 +799,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:NUM? - ``` ; LQN:NUM? ; [symbol] @@ -943,8 +811,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:OUT - ``` ; LQN:OUT ; [symbol] @@ -956,8 +822,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:PATH? - ``` ; LQN:PATH? ; [symbol] @@ -970,8 +834,6 @@ ; Source file: /data/x/lqn/src/sh.lisp ``` -#### LQN:POP\* - ``` ; LQN:POP* ; [symbol] @@ -983,8 +845,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:PREF? - ``` ; LQN:PREF? ; [symbol] @@ -998,8 +858,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:PROC-QRY - ``` ; LQN:PROC-QRY ; [symbol] @@ -1012,8 +870,6 @@ ; Source file: /data/x/lqn/src/qry-operators.lisp ``` -#### LQN:PSH\* - ``` ; LQN:PSH* ; [symbol] @@ -1025,8 +881,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:QRY - ``` ; LQN:QRY ; [symbol] @@ -1034,12 +888,10 @@ ; QRY names a macro: ; Lambda-list: (DAT &REST REST) ; Documentation: - ; query data. rest is wrapped in the pipe operator. + ; query data. rest is wrapped in the ?pipe operator. ; Source file: /data/x/lqn/src/qry-operators.lisp ``` -#### LQN:QRYD - ``` ; LQN:QRYD ; [symbol] @@ -1051,8 +903,6 @@ ; Source file: /data/x/lqn/src/qry-operators.lisp ``` -#### LQN:QRYDB - ``` ; LQN:QRYDB ; [symbol] @@ -1060,12 +910,10 @@ ; QRYDB names a macro: ; Lambda-list: (DAT &REST REST) ; Documentation: - ; query data. rest is wrapped in the pipe operator. + ; query data. rest is wrapped in the ?pipe operator. ; Source file: /data/x/lqn/src/qry-operators.lisp ``` -#### LQN:QRYL - ``` ; LQN:QRYL ; [symbol] @@ -1078,8 +926,6 @@ ; Source file: /data/x/lqn/src/qry-operators.lisp ``` -#### LQN:RANGE - ``` ; LQN:RANGE ; [symbol] @@ -1093,8 +939,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:READ? - ``` ; LQN:READ? ; [symbol] @@ -1108,8 +952,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:REPL - ``` ; LQN:REPL ; [symbol] @@ -1123,8 +965,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:RPAD - ``` ; LQN:RPAD ; [symbol] @@ -1137,8 +977,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:SDWN - ``` ; LQN:SDWN ; [symbol] @@ -1151,8 +989,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:SEL - ``` ; LQN:SEL ; [symbol] @@ -1170,8 +1006,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:SEQ - ``` ; LQN:SEQ ; [symbol] @@ -1185,8 +1019,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:SEQ!? - ``` :missing:todo: @@ -1194,8 +1026,6 @@ ; [symbol] ``` -#### LQN:SEQ? - ``` ; LQN:SEQ? ; [symbol] @@ -1208,8 +1038,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:SIZE? - ``` ; LQN:SIZE? ; [symbol] @@ -1222,8 +1050,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:SOME? - ``` ; LQN:SOME? ; [symbol] @@ -1236,8 +1062,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:SPLT - ``` ; LQN:SPLT ; [symbol] @@ -1249,8 +1073,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:SRT - ``` ; LQN:SRT ; [symbol] @@ -1263,8 +1085,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:SSYM? - ``` ; LQN:SSYM? ; [symbol] @@ -1277,8 +1097,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:STR! - ``` ; LQN:STR! ; [symbol] @@ -1291,8 +1109,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:STR!? - ``` ; LQN:STR!? ; [symbol] @@ -1305,8 +1121,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:STR? - ``` ; LQN:STR? ; [symbol] @@ -1319,8 +1133,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:STRCAT - ``` ; LQN:STRCAT ; [symbol] @@ -1333,8 +1145,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:SUB? - ``` ; LQN:SUB? ; [symbol] @@ -1348,8 +1158,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:SUBDIR - ``` ; LQN:SUBDIR ; [symbol] @@ -1362,8 +1170,6 @@ ; Source file: /data/x/lqn/src/sh.lisp ``` -#### LQN:SUBFILES - ``` ; LQN:SUBFILES ; [symbol] @@ -1376,8 +1182,6 @@ ; Source file: /data/x/lqn/src/sh.lisp ``` -#### LQN:SUBX? - ``` ; LQN:SUBX? ; [symbol] @@ -1392,8 +1196,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:SUF? - ``` ; LQN:SUF? ; [symbol] @@ -1407,8 +1209,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:SUP - ``` ; LQN:SUP ; [symbol] @@ -1421,8 +1221,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:SYM! - ``` ; LQN:SYM! ; [symbol] @@ -1435,8 +1233,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:SYMB - ``` ; LQN:SYMB ; [symbol] @@ -1450,8 +1246,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:TAIL - ``` ; LQN:TAIL ; [symbol] @@ -1468,8 +1262,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:TRIM - ``` ; LQN:TRIM ; [symbol] @@ -1489,8 +1281,6 @@ ; Source file: /data/x/lqn/src/qry-utils.lisp ``` -#### LQN:TXT-EXPORT - ``` ; LQN:TXT-EXPORT ; [symbol] @@ -1504,8 +1294,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:TXT-READ-FILE - ``` ; LQN:TXT-READ-FILE ; [symbol] @@ -1518,8 +1306,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:TXT-READ-STREAM - ``` ; LQN:TXT-READ-STREAM ; [symbol] @@ -1533,8 +1319,6 @@ ; Source file: /data/x/lqn/src/io.lisp ``` -#### LQN:UNIQ - ``` ; LQN:UNIQ ; [symbol] @@ -1551,8 +1335,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:V? - ``` ; LQN:V? ; [symbol] @@ -1568,8 +1350,6 @@ ; Source file: /data/x/lqn/src/init.lisp ``` -#### LQN:VEC! - ``` ; LQN:VEC! ; [symbol] @@ -1582,8 +1362,6 @@ ; Source file: /data/x/lqn/src/basic-utils.lisp ``` -#### LQN:VEC!? - ``` :missing:todo: @@ -1591,8 +1369,6 @@ ; [symbol] ``` -#### LQN:VEC? - ``` ; LQN:VEC? ; [symbol] diff --git a/lqn.asd b/lqn.asd index 21cd90f..db3ee23 100644 --- a/lqn.asd +++ b/lqn.asd @@ -1,6 +1,6 @@ (asdf:defsystem #:lqn :description "Lisp Query Notation" - :version "2.0.2" + :version "2.1.0" :author "anders hoff / @inconvergent / inconvergent@gmail.com" :in-order-to ((asdf:test-op (asdf:test-op #:lqn/tests))) :licence "MIT" :pathname "src/" :serial nil @@ -19,7 +19,7 @@ (asdf:defsystem #:lqn/tests :depends-on (#:lqn #:prove #:uiop #:asdf) - :version "2.0.2" + :version "2.1.0" :perform (asdf:test-op (o s) (uiop:symbol-call ':lqn-tests '#:run-tests)) :pathname "test/" :serial t :components ((:file "run"))) diff --git a/make-docs.lisp b/make-docs.lisp index 5966ece..5a78c49 100755 --- a/make-docs.lisp +++ b/make-docs.lisp @@ -13,7 +13,7 @@ (defun make-docs () (loop for (o . rest) in (import-all (internal-path "src/packages")) if (eq o 'defpackage) - do (let* ((pkg (mkstr (car rest))) + do (let* ((pkg (sup (mkstr (car rest)))) (fn (string-downcase (internal-path (mkstr "docs/" (repl pkg "/" "-") ".md"))))) (format t "~&~a~%" fn) diff --git a/src/basic-utils.lisp b/src/basic-utils.lisp index ac54cff..3108690 100644 --- a/src/basic-utils.lisp +++ b/src/basic-utils.lisp @@ -21,7 +21,7 @@ (nreverse (cons l acc)))))) (if l (rec l nil) nil))) (defun mkstr (&rest args) (declare #.*opt*) "coerce all arguments to a string." - (with-output-to-string (s) (dolist (a args) (princ a s)))) + (with-output-to-string (s) (dolist (a args) (prtcomp (princ a s))))) (defun kw (s) (declare #.*opt*) "mkstr, upcase, keyword." (intern (string-upcase (etypecase s (string s) (symbol (symbol-name s)) (number (mkstr s)))) :keyword)) diff --git a/src/docs.lisp b/src/docs.lisp index a7ee576..3ddfa13 100644 --- a/src/docs.lisp +++ b/src/docs.lisp @@ -45,8 +45,7 @@ use :pretty to print verbose output to stdout in a readable form." (:pretty `(loop for (,str ,sym) in (pckgs ,pkg) do (mvb (,doc ,skip) (select-docs ,sym) - (unless ,skip (format t "~&#### ~a:~a~%~%~a~&~%" - (mkstr ,pkg) (-md-sanitize ,str) ,doc))))) + (unless ,skip (format t "~&~a~&~%" ,doc))))) (:pairs `(loop for (,str ,sym) in (pckgs ,pkg) collect (list ,str (select-docs ,sym)))) (otherwise `(loop for (,str ,sym) in (pckgs ,pkg) collect ,str))))) diff --git a/src/init.lisp b/src/init.lisp index 4289d0e..2c814be 100644 --- a/src/init.lisp +++ b/src/init.lisp @@ -1,13 +1,9 @@ (in-package :lqn) (defvar *qmodes* '(:+ :? :- :%)) -(defvar *operators* '(:|| :@ - :?select - :?map :?filter :?fld - :*$ :$* - :?srch :?grp +(defvar *operators* '(:|| :?pipe :?select :@ :?map :?filter :*$ :$* :?xpr :?txpr :?mxpr - ?rec)) + :?fld :?srch :?grp :?rec)) (defvar *opt* '(optimize (speed 3) (safety 1))) (defvar *fxns* '(:err :wrn :nope :noop :lst :lit :qt :hld :ghv :pnum :inum :cnt :λ :fmt :out :jsnstr @@ -34,6 +30,8 @@ #+abcl (ext:quit:status status) #+allegro (excl:exit status :quiet t) #+gcl (common-lisp-user::bye status) #+ecl (ext:quit status)) +(defmacro prtcomp (&rest o) ; (*print-readably* t) (*print-escape* t) + `(let ((*print-case* :downcase) (*print-gensym* nil)) (progn ,@o))) (defmacro with-struct ((name . fields) struct &body body) (let ((gs (gensym))) `(let ((,gs ,struct)) @@ -41,7 +39,6 @@ `(,f (,(psymb (symbol-package name) name f) ,gs))) fields) ,@body)))) - (defmacro with-gensyms (syms &body body) `(let ,(mapcar #'(lambda (s) `(,s (gensym ,(symbol-name s)))) syms) ,@body)) diff --git a/src/pre-qry.lisp b/src/pre-qry.lisp index a37c82f..f2218b3 100644 --- a/src/pre-qry.lisp +++ b/src/pre-qry.lisp @@ -1,5 +1,7 @@ (in-package :lqn) +(defun opstr (op &optional (fx #'identity)) + (prtcomp (format nil "██ op: ~s ██" (funcall fx op)))) (defun unpack-mode (o &optional (default :+) merciful) (labels ((valid-mode (m) (member m *qmodes* :test #'eq)) (repack- (s s*) (etypecase s (symbol (psymb (symbol-package s) (subseq s* 2))) @@ -18,14 +20,13 @@ (atom `(default ,o)) (otherwise (error "lqn: bad thing to have mode: ~a" o))))) - (defun ct/path/key (pp) (first (last (str-split pp "/")))) (defun dat/new (conf dat) `((:dat . ,dat) ,@conf)) (defun strip-all (d) (declare (list d)) (if (car- dat? d) (cdr d) d)) ; CONTEXTS ; envs -(defmacro q∈ ((dat fn fi) &body body) +(defmacro ██q∈ ((dat fn fi) &body body) (declare (symbol dat fn fi)) (awg (nope meta) `(let ((,meta (make-hash-table :test #'eq))) @@ -46,7 +47,7 @@ (inum () (wrn "no (inum) in this scope."))) ,@body))))) -(defmacro ∈ ((&key par cnt itr key) &body body) +(defmacro ██∈ ((&key par cnt itr key) &body body) (declare (symbol par cnt itr)) `(labels (,@(when par `((par () ,par) (pnum () (size? ,par)))) ,@(when itr `((itr () ,itr) (inum () (size? ,itr)))) @@ -91,8 +92,8 @@ ctx isect qq))) (loop for q in qq collect (pre/scan-clause q))) -(defun pre/|| (qq) (unless qq (warn "||: missing args.")) ; pipe - (loop for q in (pre/scan-clauses qq '#:pipe '(:@)) collect +(defun pre/?pipe (qq) (unless qq (warn "?pipe: missing args.")) ; pipe + (loop for q in (pre/scan-clauses qq '#:?pipe '(:@)) collect (if (dat? q) (kw q) (typecase q (cons q) (boolean q) (keyword `(?filter ,q)) (string `(?filter ,q)) @@ -110,7 +111,7 @@ (let* ((q* (remove-if #'dat? (pre/scan-clauses q '#:?map '(:@)))) (res (mapcar #'unpack- q*)) (allres (if (= (length q) (length q*)) res (cons `(lit :_) res)))) - (if (< (length allres) 2) allres `((|| ,@allres)))))) + (if (< (length allres) 2) allres `((?pipe ,@allres)))))) (defun pre/?select (q &optional (m :+)) (unless q (warn "?select: missing args.")) (labels ; TODO: how to handle selecting only keys with -@? diff --git a/src/qry-operators.lisp b/src/qry-operators.lisp index 0b00281..8c525e9 100755 --- a/src/qry-operators.lisp +++ b/src/qry-operators.lisp @@ -1,13 +1,12 @@ (in-package :lqn) -(defmacro o∈ (s ∇ expr) (declare (ignore s)) `(setf ,∇ ,expr)) -(defun compile/|| (rec conf d) ; (|| ...) pipe +(defmacro ██op∈ (∇ expr) `(setf ,∇ ,expr)) +(defun compile/?pipe (rec conf d) ; (|| ...) pipe (awg (∇-) (if (< (length d) 2) (funcall rec conf (car d)) `(let ((,∇- ,(gk conf :dat))) ,@(loop for op in d - collect `(o∈ ,(sdwn (head (str! op) 50)) ,∇- - ,(funcall rec (dat/new conf ∇-) op))) + collect `(██op∈ ,∇- ,(funcall rec (dat/new conf ∇-) op))) ,∇-)))) (defun compile/@ (rec conf d &aux (dat (gk conf :dat))) @@ -15,7 +14,7 @@ (1 `(@@ ,dat ,(funcall rec conf (car d)))) (2 `(@@ ,dat ,@(funcall rec conf d))) (3 `(@@ ,@(funcall rec conf d))) - (otherwise (error "@: expected 0-3 arguments. got: ~a." d)))) + (otherwise (error "@: expected 0-3 arguments. got:~%~a." d)))) (defun compile/?map (rec conf d) ; #(...) ; do this sequence of expressions on each item (when (zerop (length d)) (error "?map: missing args.")) @@ -24,17 +23,17 @@ (labels ((do-map () `(let ((,par ,(gk conf :dat))) (labels - ((map-do-ht () + ((map-do-ht () ,(opstr d #'car) (loop with ,kres = (new$) for ,i from 0 for ,itr being the hash-values of ,par using (hash-key ,k) - do (∈ (:par ,par :cnt ,i :itr ,itr :key ,k) + do (██∈ (:par ,par :cnt ,i :itr ,itr :key ,k) (setf (gethash ,k ,kres) ,expr)) finally (return ,kres))) - (map-do-vec () + (map-do-vec () ,(opstr d #'car) (loop with ,vres = (mav) with ,par = (vec! ,par) for ,i from 0 for ,itr across ,par - do (∈ (:par ,par :cnt ,i :itr ,itr :key ,i) + do (██∈ (:par ,par :cnt ,i :itr ,itr :key ,i) (vex ,vres ,expr)) finally (return ,vres)))) (typecase ,par @@ -43,59 +42,59 @@ (otherwise (error "RT: ?map: bad type. expected hash-table or vector:~%got: ~a." ,par))))))) (typecase expr (list (do-map)) (vector (do-map)) - (otherwise (error "?map: expected vector or cons. got: ~a." expr))))))) + (otherwise (error "?map: expected vector or cons. got:~%~a." expr))))))) (defun compile/?fld (rec conf d) ; (?fld ...) (awg (k i res itr par) ; 0 + ; 0 acc (+ acc _) (labels ((do-fld (init acc itr expr) (unless (and (symbolp acc) (symbolp itr)) - (error "?fld: expected symbols, got: ~a/~a." acc itr)) - (unless (consp expr) (error "?fld: expected cons or got: ~a." expr)) + (error "?fld: expected symbols, got:~%acc: ~a~%itr: ~a." acc itr)) + (unless (consp expr) (error "?fld: expected cons. got:~%~a." expr)) `(let ((,par ,(gk conf :dat)) (,acc ,init)) - (labels ((fld-do-ht () + (labels ((fld-do-ht () ,(opstr d) (loop for ,i from 0 for ,itr being the hash-values of ,par using (hash-key ,k) - do (∈ (:par ,par :cnt ,i :key ,k :itr ,itr) + do (██∈ (:par ,par :cnt ,i :key ,k :itr ,itr) (setf ,acc ,(funcall rec (dat/new conf itr) expr))))) - (fld-do-vec () + (fld-do-vec () ,(opstr d) (loop with ,par = (vec! ,par) for ,itr across ,par for ,i from 0 - do (∈ (:par ,par :cnt ,i :key ,i :itr ,itr) + do (██∈ (:par ,par :cnt ,i :key ,i :itr ,itr) (setf ,acc ,(funcall rec (dat/new conf itr) expr)))))) (typecase ,par (null ,acc) (hash-table (fld-do-ht)) (list (fld-do-vec)) (vector (fld-do-vec)) (simple-vector (fld-do-vec)) - (otherwise (error "RT: ?fld: bad type. expected hash-table or vector:~%got: ~a." ,par)))) + (otherwise (error "RT: ?fld: bad type. expected hash-table or vector. got:~%~a." ,par)))) ,acc))) (case (length d) (2 (etypecase (second d) (symbol (do-fld (car d) res itr `(,(second d) ,res ,itr))) (cons (do-fld (car d) res itr `(,(first (second d)) ,res ,@(cdr (second d))))))) (3 (do-fld (car d) (second d) itr (third d))) - (otherwise (error "?fld: expected 2-3 args. got: ~a." d)))))) + (otherwise (error "?fld: expected 2-3 args. got:~%~a." d)))))) ; TODO: is (key) env fx consistent? (defun compile/?grp (rec conf d) - (unless (< 0 (length d) 3) (error "?grp: expected 1 or 2 args. got: ~a." d)) + (unless (< 0 (length d) 3) (error "?grp: expected 1 or 2 args. got:~%~a." d)) (awg (i k kvres key itr par acc) (labels ((do-dat () (case (length d) (1 itr) (2 (do-key (second d))))) (do-key (cd) (funcall rec (dat/new conf itr) (typecase cd (keyword `(@ ,cd)) (string `(@ ,cd)) (otherwise cd))))) `(let ((,par ,(gk conf :dat)) (,kvres (new$))) - (labels ((grp-do-vec () + (labels ((grp-do-vec () ,(opstr d) (loop with ,par = (vec! ,par) for ,i from 0 for ,itr across ,par - for ,key = (∈ (:par ,par :key ,i :cnt ,i) ,(do-key (car d))) + for ,key = (██∈ (:par ,par :key ,i :cnt ,i) ,(do-key (car d))) for ,acc = (gethash ,key ,kvres (new*)) - do (∈ (:par ,par :cnt ,i :itr ,itr :key ,key) + do (██∈ (:par ,par :cnt ,i :itr ,itr :key ,key) (setf (gethash ,key ,kvres) (psh* ,acc ,(do-dat)))))) - (grp-do-ht () + (grp-do-ht () ,(opstr d) (loop for ,i from 0 for ,itr being the hash-values of ,par using (hash-key ,k) - for ,key = (∈ (:par ,par :key ,k :cnt ,i) ,(do-key (car d))) + for ,key = (██∈ (:par ,par :key ,k :cnt ,i) ,(do-key (car d))) for ,acc = (gethash ,key ,kvres (new*)) - do (∈ (:par ,par :cnt ,i :itr ,itr :key ,key) + do (██∈ (:par ,par :cnt ,i :itr ,itr :key ,key) (setf (gethash ,key ,kvres) (psh* ,acc ,(do-dat))))))) (typecase ,par (null nil) (hash-table (grp-do-ht)) (list (grp-do-vec)) @@ -110,41 +109,38 @@ (defun compile/?select (rec conf d) ; {...} ; sel ; select keys/exprs from ht to new ht (awg (kres par dat) `(let* ((,par ,(gk conf :dat))) - (labels ((select-do-ht (&aux (,kres ,(if (car- dat? d) `(make$ ,par) `(new$)))) - (∈ (:par ,par) + (labels ((select-do-ht (&aux (,kres ,(if (car- dat? d) `(make$ ,par) `(new$)))) ,(opstr d) + (██∈ (:par ,par) ,@(loop for (m kk expr) in (strip-all d) collect `(let ((,dat (@@ ,par ,kk))) (declare (ignorable ,dat)) - (∈ (:key ,kk) + (██∈ (:key ,kk) ,(compile/$add rec (dat/new conf dat) m kres kk expr)))) - ($nil ,kres))) - (select-do-vec () ; TODO: not implemented - (error "vector not implemented"))) + ($nil ,kres)))) (typecase ,par - (null nil) (hash-table (select-do-ht)) (list (select-do-vec)) - (vector (select-do-vec)) (simple-vector (select-do-vec)) - (otherwise (error "RT: {..} bad type. expected hash-table or vector.~%got: ~a." ,par))))))) + (null nil) (hash-table (select-do-ht)) ; TODO: missing list, vector, simple-vector + (otherwise (error "RT: {..} bad type.~%expected sequence. got:~%~a." ,par))))))) ; TODO: ?mapsel (defun compile/*$ (rec conf d) ; #{...} ; sel ; select from vec of hts to vec of hts (awg (i vres kvres itr dat par) `(let ((,par ,(gk conf :dat))) - (labels ((mapsel-do-vec (&aux (,vres (mav))) + (labels ((mapsel-do-vec (&aux (,vres (mav))) ,(opstr d) (loop with ,par of-type vector = (vec! ,par) for ,itr of-type hash-table across ,par for ,i from 0 for ,kvres of-type hash-table = ,(if (car- dat? d) `(make$ ,itr) `(new$)) - do (∈ (:par ,par :cnt ,i :itr ,itr) + do (██∈ (:par ,par :cnt ,i :itr ,itr) ,@(loop for (m kk expr) in (strip-all d) collect `(let ((,dat (@@ ,itr ,kk))) (declare (ignorable ,dat)) - (∈ (:key ,kk) ,(compile/$add rec + (██∈ (:key ,kk) ,(compile/$add rec (dat/new conf dat) m kvres kk expr)))) (vex ,vres ($nil ,kvres)))) ,vres)) (typecase ,par (null nil) (vector (mapsel-do-vec)) (simple-vector (mapsel-do-vec)) (list (mapsel-do-vec)) - (otherwise (error "RT: #{..} bad type. expected vector, got: ~a." ,par))))))) + (otherwise (error "RT: #{..} bad type. expected vector. got:~%~a." ,par))))))) ; TODO: vec! does the wrong thing for non-sequence @@ -154,20 +150,20 @@ (defun compile/$* (rec conf d) ; #[...] ; sel ; select from vec of hts to vec (awg (i vres itr dat par) `(let ((,par ,(gk conf :dat))) - (labels ((sel-do-vec (&aux (,vres (mav))) + (labels ((sel-do-vec (&aux (,vres (mav))) ,(opstr d) (loop with ,par of-type vector = (vec! ,par) for ,itr across ,par for ,i from 0 - do (∈ (:par ,par :cnt ,i :itr ,itr) + do (██∈ (:par ,par :cnt ,i :itr ,itr) ,(when (car- dat? d) (compile/*add rec conf :+ vres itr)) ,@(loop for (m kk expr) in (strip-all d) collect `(let ((,dat (@@ ,itr ,kk))) (declare (ignorable ,dat)) - (∈ (:key ,kk) ,(compile/*add rec + (██∈ (:key ,kk) ,(compile/*add rec (dat/new conf dat) m vres expr)))))) ,vres)) (typecase ,par ; TODO: support hts (null nil) (vector (sel-do-vec)) (simple-vector (sel-do-vec)) (list (sel-do-vec)) - (otherwise (error "RT: #[..] bad type. expected vector, got: ~a." ,par))))))) + (otherwise (error "RT: #[..] bad type. expected vector. got:~%~a." ,par))))))) (defun pre/?filter (q &optional (mm :?)) (unless q (warn "?filter: missing args.")) (labels ((unpack- (o) (dsb (m sk) (unpack-mode o mm) `(,m ,(pre/xpr-sel sk :_))))) @@ -182,7 +178,7 @@ (awg (k i kres vres itr par) `(let ((,par ,(gk conf :dat))) (labels - ((filter-do-vec () + ((filter-do-vec () ,(opstr d) (loop with ,par = (vec! ,par) with ,vres of-type vector = (mav) for ,i from 0 for ,itr across ,par do ,(compile/?xpr rec @@ -190,7 +186,7 @@ `(,@d (vex ,vres ,@(or (xpr/get-modes d :%) `(,itr))) nil)) finally (return ,vres))) - (filter-do-ht () + (filter-do-ht () ,(opstr d) (loop with ,kres of-type hash-table = (new$) for ,i from 0 for ,itr being the hash-values of ,par using (hash-key ,k) do ,(compile/?xpr rec @@ -214,9 +210,9 @@ ,@(when nots `((not (or ,@nots))))))))))) (defun compile/?xpr (rec conf d) ; (xpr sel .. hit miss) (labels ((do-last (d n) (mapcar (λ (d) (funcall rec conf (pre/or-all d))) (last d n)))) - `(∈ (:par ,(gk conf :par t) :cnt ,(gk conf :cnt t) + `(██∈ (:par ,(gk conf :par t) :cnt ,(gk conf :cnt t) :itr ,(gk conf :itr t) :key ,(gk conf :key t)) - ,(case (length d) ((0 (error "xpr: missing args."))) + ,(case (length d) ((0 (error "?xpr: missing args."))) (1 (compile/?xpr/bool rec conf (pre/?filter d))) (2 `(if ,(compile/?xpr/bool rec conf (pre/?filter (butlast d 1))) ,@(do-last d 1))) (otherwise `(if ,(compile/?xpr/bool rec conf @@ -246,13 +242,13 @@ (1 `(with ,(car o))) (2 `(for ,(car o) = ,(rec (second o)) then ,(rec (second o)))) (3 `(for ,(car o) = ,(rec (second o)) then ,(rec (third o)))) - (otherwise (error "?rec: wanted 1-3 args, got: ~a." o)))))) + (otherwise (error "?rec: wanted 1-3 args. got:~%~a." o)))))) (defun compile/?rec (rec conf d) ; (?rec (< (inum) 10) (+ _ 1)) - (unless (< 1 (length d) 4) (error "?rec: expected 2-3 arguments. got: ~a." d)) + (unless (< 1 (length d) 4) (error "?rec: expected 2-3 arguments. got:~%~a." d)) (awg (i ∇-) (let ((d (lpad-lst 3 d))) `(let ((,∇- ,(gk conf :dat)) (,i 0)) - (∈ (:par ,(gk conf :dat) :cnt ,i :key ,i) + (██∈ (:par ,(gk conf :dat) :cnt ,i :key ,i) (loop ,@(compile/?rec/vars rec conf (car d)) while ,(funcall rec (dat/new conf ∇-) (second d)) do (setf ,∇- ,(funcall rec (dat/new conf ∇-) @@ -260,14 +256,15 @@ (values ,∇- ,i))))) (defun proc-qry (q &optional conf*) "compile lqn query" - (awg (dat fn fi) + (awg (dat fn fi qblk) (labels ((rec (conf d* &aux (d (pre/scan-clause d* nil))) (cond ((dat? d) (gk conf :dat)) ((stringp d) d) ; remember that this order is important ((vectorp d) (rec conf `(?map ,@(coerce d 'list)))) ((atom d) d) - ((qop? :|| d) (compile/|| #'rec conf (pre/|| (cdr d)))) + ((qop? :?pipe d) (compile/?pipe #'rec conf (pre/?pipe (cdr d)))) + ((qop? :|| d) (compile/?pipe #'rec conf (pre/?pipe (cdr d)))) ((qop? :$* d) (compile/$* #'rec conf (pre/?select (cdr d)))) ((qop? :*$ d) (compile/*$ #'rec conf (pre/?select (cdr d)))) ((qop? :?select d) (compile/?select #'rec conf (pre/?select (cdr d)))) @@ -285,26 +282,25 @@ ((consp d) (cons (rec conf (pre/scan-clause (car d))) (rec conf (cdr d)))) (t (error "lqn: unexpected clause: ~a~%in: ~a." d q))))) `(λ (,dat ,fn ,fi) - (q∈ (,dat ,fn ,fi) - ,(rec `((:dat . ,dat) ,@conf*) q)))))) + (██q∈ (,dat ,fn ,fi) + ,(rec `((:dat . ,dat) (:qblk . ,qblk) ,@conf*) q)))))) (defun qry/show (q cq) - (format t " -██ COMPILED ██████████████████████████ -██ q: ~s -██ ---------~% ~s -██ END ██████████████████████████~%" q cq)) + (prtcomp (format t " +██████████████████ COMPILED LQN QRY (~a) █████████████████~%~%~s~%~%~s +██████████████████ END ██████████████████████████████████████~%" + (v?) q cq))) (defmacro qryd (dat q &key db) "run lqn query on dat" (let ((cq (proc-qry q))) (when db (qry/show q cq)) `(funcall ,cq ,dat ":internal:" 0))) -(defmacro qry (dat &rest rest) "query data. rest is wrapped in the pipe operator." - `(qryd ,dat (|| ,@rest))) +(defmacro qry (dat &rest rest) "query data. rest is wrapped in the ?pipe operator." + `(qryd ,dat (?pipe ,@rest))) ; TODO: fix arguments/names in qryd, jsnqryf etc. -(defmacro qrydb (dat &rest rest) "query data. rest is wrapped in the pipe operator." - `(qryd ,dat (|| ,@rest) :db t)) +(defmacro qrydb (dat &rest rest) "query data. rest is wrapped in the ?pipe operator." + `(qryd ,dat (?pipe ,@rest) :db t)) (defun qryl (dat q &key db) "compile lqn query and run on dat" (eval `(qryd ,dat ,q :db ,db))) (defmacro jsnqryf (fn q &key db) "run lqn query on json file, fn" diff --git a/src/qry-utils.lisp b/src/qry-utils.lisp index c9b4a01..5b1f8ff 100644 --- a/src/qry-utils.lisp +++ b/src/qry-utils.lisp @@ -283,17 +283,19 @@ ranges are lists that behave like arguments to seq." (defmacro m/replfx ((d &optional (f* (gensym "F")) (safe t)) &body body) (unless d (error "m/replfx: missing args.")) - (awg (rec) `(locally (declare #.*opt*) - (labels ((,rec (,f*) - (cond ,@(loop for (fx tx) in (group 2 body) collect `(,fx ,(if safe tx `(,rec ,tx)))) - ((hash-table-p ,f*) - (loop with kv = (make-hash-table :test (hash-table-test ,f*)) - for k being the hash-key of ,f* using (hash-value v) - do (setf (gethash k kv) (,rec v)) - finally (return kv))) - ((stringp ,f*) ,f*) - ((vectorp ,f*) (map 'vector #',rec ,f*)) - ((consp ,f*) (cons (,rec (car ,f*)) (,rec (cdr ,f*)))) - (t ,f*)))) + (awg (rec) + `(locally (declare #.*opt*) + (labels ((,rec (,f*) + (cond ,@(loop for (fx tx) in (group 2 body) + collect `(,fx ,(if safe tx `(,rec ,tx)))) + ((hash-table-p ,f*) + (loop with kv = (make-hash-table :test (hash-table-test ,f*)) + for k being the hash-key of ,f* using (hash-value v) + do (setf (gethash k kv) (,rec v)) + finally (return kv))) + ((stringp ,f*) ,f*) + ((vectorp ,f*) (map 'vector #',rec ,f*)) + ((consp ,f*) (cons (,rec (car ,f*)) (,rec (cdr ,f*)))) + (t ,f*)))) (,rec ,d))))) diff --git a/src/sh.lisp b/src/sh.lisp index e0239e1..ba804de 100644 --- a/src/sh.lisp +++ b/src/sh.lisp @@ -32,7 +32,7 @@ (defun sh/is-query (q ex) (or q (sh/exit-msg 5 "MISSING query!~%~%~a~&" ex))) (defun sh/parse-query (q) (declare #.*opt*) (handler-case (let ((rd (read-all-str q))) - `(|| ,@(if rd rd '(nil)))) + `(?pipe ,@(if rd rd '(nil)))) (error (e) (sh/exit-msg 10 "failed to PARSE qry:~%~%~a~&" e)))) (defun sh/compile-query (qq) (declare #.*opt*) @@ -64,6 +64,7 @@ (defun sh/out (d opts res &optional (s *standard-output*) (zeros (opt/nils? opts))) (declare (optimize speed (safety 2))) + (prtcomp (labels ((prtxt (res*) (format s "~&~a~%" res*)) (prldn (res*) (handler-case (format s "~&~s~&" (ldnout res*)) @@ -86,7 +87,7 @@ (hash-table (if (opt/jsnopt? opts) (prjsn res*) (prldn res*))) (list (prldn res*)) (otherwise (prtxt res*))))) - (ecase (opt/outfmt? opts d) (:json (prjsn res)) (:ldn (prldn res)) (:txt (dotxt res))))) + (ecase (opt/outfmt? opts d) (:json (prjsn res)) (:ldn (prldn res)) (:txt (dotxt res)))))) ; TODO: auto split args, handle errors (defun cmd (fx &rest args) (declare (string fx)) "run terminal command"