nydp 0.4.6 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: '06876fcb6832d6737b4763607cfe7b4c0ca003c3'
4
- data.tar.gz: b45d30570c913940f93585241c1dad9cc71c5872
2
+ SHA256:
3
+ metadata.gz: '0389044de6d7b6230da9315bc8dde967e1ddf8ed77df2b8ef4106ce9bfc3e93a'
4
+ data.tar.gz: 133567982e2fbb734ea429e98197e4b7d5bc49c2130f64ec630c095adcd1f250
5
5
  SHA512:
6
- metadata.gz: d874e4fbbba55a5995f699451bbf305fe7667f4058cdab2e713fe64900bc96ed285fe5ae8d0c460c73001f0a44fb22699c634c2017a723e9c79d818779d38b7e
7
- data.tar.gz: 5d5f3aeb4e7c0e65af1024990fdfa5f73a8f4657a06dfd11aaeec172709615a3879f0bdff0efd19475a223add58ee1dd6379951548979eda5b80f30861967e61
6
+ metadata.gz: 2516bbc0473796915710786bb8b43ac339df657438e5a35d8f8d38cb5a7b46c1663b09a8cea266369b168530b63a1f249daf882d2712cd8558febb167bc648ef
7
+ data.tar.gz: 2548a1e1259f053ff25bc490d13f44579720be5f0ea7954915917092a04d0619f0b014221f55ed6b1f86f5046f5a6a7244348ff4805a2282ece150c3993be71f
@@ -21,7 +21,9 @@
21
21
 
22
22
  (hash-set macs 'do
23
23
  (fn forms
24
- `((fn nil ,@forms))))
24
+ (if (no (cdr forms))
25
+ (car forms)
26
+ `((fn nil ,@forms)))))
25
27
 
26
28
  ((fn (this-chapter-name chapters chapter-new chapter-build chapter-add-to-chapter)
27
29
  (assign chapters (hash))
@@ -169,10 +171,20 @@
169
171
  (filter-forms (filter-form hsh (car forms)) (cdr forms))
170
172
  (rev-values hsh)))
171
173
 
172
- (def build-def-hash (hsh)
173
- (hash-set hsh 'comment nil)
174
- (hash-set hsh 'chapter nil)
175
- hsh)
174
+ (def filter-remove (key forms keyforms otherforms)
175
+ (cond forms
176
+ (cond (cond (pair? forms) (cond (pair? (car forms)) (eq? key (caar forms))))
177
+ (filter-remove key (cdr forms) (cons (car forms) keyforms) otherforms)
178
+ (filter-remove key (cdr forms) keyforms (cons (car forms) otherforms)))
179
+ (list (rev keyforms) (rev otherforms))))
180
+
181
+ (assign DEF-FORMS '(comment chapter))
182
+
183
+ (def build-def-hash ()
184
+ ((fn (h)
185
+ (map (fn (k) (hash-set h k nil)) DEF-FORMS)
186
+ h)
187
+ (hash)))
176
188
 
177
189
  (def dox-build-def-name (name) name)
178
190
 
@@ -188,7 +200,7 @@
188
200
 
189
201
  (hash-set macs 'mac
190
202
  (fn (name args . body)
191
- (define-mac-expr name args (filter-forms (build-def-hash (hash)) body))))
203
+ (define-mac-expr name args (filter-forms (build-def-hash) body))))
192
204
 
193
205
  (dox-add-doc 'mac
194
206
  'mac
@@ -204,11 +216,15 @@
204
216
  '`((fn nil ,@args))
205
217
  '(nydp-core))
206
218
 
219
+ ;; override later to use '= instead of 'assign, giving us hash-assignment and other goodies for free
207
220
  (mac def-assign args `(assign ,@args))
208
221
 
209
222
  ;; used internally by 'def
210
223
  (def define-def-expr (name args body-forms)
211
- `(do (def-assign ,name (fun ,args ,@(filter-comments (hash-get body-forms nil))))
224
+ `(do (def-assign ,name
225
+ ((fn (self-name)
226
+ (fun ,args ,@(filter-comments (hash-get body-forms nil))))
227
+ ',name))
212
228
  (dox-add-doc ',(dox-build-def-name name)
213
229
  'def
214
230
  ',(+ (fetch-and-clear-comments) (map car (hash-get body-forms 'comment)))
@@ -219,7 +235,7 @@
219
235
  ;; define a new function in the global namespace
220
236
  (mac def (name args . body)
221
237
  (chapter nydp-core)
222
- (define-def-expr name args (filter-forms (build-def-hash (hash)) body)))
238
+ (define-def-expr name args (filter-forms (build-def-hash) body)))
223
239
 
224
240
  (mac comment (txt)
225
241
  (assign comments (cons txt comments))
@@ -46,6 +46,7 @@
46
46
  "with 1 arg, an integer less than arg"
47
47
  "with two args, an integer >= arg 0 and < arg 1") 'args nil '(math))
48
48
  (dox-add-doc 'random-string 'def '("return a random string of length 'len (default 10)") '(len) nil '(string-manipulation))
49
+ (dox-add-doc 'regexp 'def '("return a regular expression compiled from the given string") '(str) nil '(string-manipulation))
49
50
  (dox-add-doc 'to-string 'def '("return a human-readable string representation of 'arg") '(arg) nil '(string-manipulation))
50
51
  (dox-add-doc 'string-length 'def '("return the length of 'arg") '(arg) nil '(string-manipulation))
51
52
  (dox-add-doc 'string-replace 'def '("replace 'pattern with 'replacement in 'str") '(pattern replacement str) nil '(string-manipulation))
@@ -97,14 +97,14 @@ scoping, assignment, anonymous functions and more...")
97
97
  ;; like 'let, but creates and assigns multiple local variables.
98
98
  ;; for example, "(with (a 1 b 2) (+ a b))" returns 3
99
99
  (mac with (parms . body)
100
- `((fun ,(map car (pairs parms))
101
- ,@body)
102
- ,@(map cadr (pairs parms))))
100
+ `((fun ,(map car (pairs parms))
101
+ ,@body)
102
+ ,@(map cadr (pairs parms))))
103
103
 
104
- ;; same as ( (fn (var) body) val ) -> ie create a lexical scope
104
+ ;; create a lexical scope
105
105
  ;; where val is assigned to var, execute 'body in that scope
106
106
  (mac let (var val . body)
107
- `(with (,var ,val) ,@body))
107
+ `((fun (,var) ,@body) ,val))
108
108
 
109
109
  (mac rfn (name parms . body)
110
110
  ; creates a named, locally-scoped function
@@ -119,12 +119,12 @@ scoping, assignment, anonymous functions and more...")
119
119
  ; same as 'rfn, but using the name 'self
120
120
  `(rfn self ,parms ,@body))
121
121
 
122
+ ;; a mix of rfn and with; creates a locally-scoped named function with
123
+ ;; the given parameter names, and invokes it with the given parameter
124
+ ;; values. It is possible to reference the function by its name from
125
+ ;; within the function (to pass as an argument or for recursive
126
+ ;; invocation)
122
127
  (mac rfnwith (name params . body)
123
- ; a mix of rfn and with; creates a locally-scoped named function with
124
- ; the given parameter names, and invokes it with the given parameter
125
- ; values. It is possible to reference the function by its name from
126
- ; within the function (to pass as an argument or for recursive
127
- ; invocation)
128
128
  (let ppairs (pairs params)
129
129
  `(let ,name nil
130
130
  (assign ,name (fun ,(map car ppairs) ,@body))
@@ -148,9 +148,9 @@ scoping, assignment, anonymous functions and more...")
148
148
  (def reset-uniq-counter ()
149
149
  (assign uniq-counter 0)))
150
150
 
151
+ ;; creates a lexical scope with a unique symbol assigned to
152
+ ;; each variable in 'vars ; executes the 'body.
151
153
  (mac w/uniq (vars . body)
152
- ; creates a lexical scope with a unique symbol assigned to
153
- ; each variable in 'vars ; executes the 'body.
154
154
  (if (pair? vars)
155
155
  `(with ,(apply + (map (fn (n) `(,n (uniq ',n))) vars))
156
156
  ,@body)
@@ -228,25 +228,46 @@ scoping, assignment, anonymous functions and more...")
228
228
  ;; 'place is ((ampersand-syntax || (dot-syntax key subkey)) (expr))
229
229
  ;; we need (hash-set (hash-get (expr) 'key) 'subkey (val))
230
230
  (def ampersand-expression-assignment (place value)
231
- (with (k (cadr:cdar place)
232
- hsh (cadr place))
233
- (if (caris 'dot-syntax k)
234
- (dot-syntax-assignment (cons hsh (cdr k)) value)
235
- `(hash-set ,hsh ',k ,value))))
231
+ (let k (cadr:cdar place)
232
+ (let hsh (cadr place)
233
+ (if (caris 'dot-syntax k)
234
+ (dot-syntax-assignment (cons hsh (cdr k)) value)
235
+ `(hash-set ,hsh ',k ,value)))))
236
+
237
+ ;; used internally by 'destructuring-assign
238
+ (def destructuring-assigns (names values acc)
239
+ (if names
240
+ (if (pair? names)
241
+ (destructuring-assigns
242
+ (cdr names)
243
+ `(cdr ,values)
244
+ (cons `(= ,(car names) (car ,values)) acc))
245
+ (cons `(= ,names ,values) acc))
246
+ (rev acc)))
247
+
248
+ ;; used internally by 'assign-expr
249
+ (def destructuring-assign (name value)
250
+ (w/uniq destructuring-assign
251
+ `(let ,destructuring-assign ,value
252
+ ,@(destructuring-assigns name destructuring-assign))))
236
253
 
237
254
  ;; used internally by '= macro
238
- (def assign-expr (name value)
239
- (if (isa 'symbol name)
240
- `(assign ,name ,value)
241
- (caris 'dot-syntax name)
242
- (dot-syntax-assignment (cdr name) value)
243
- (caris 'hash-get name)
244
- (hash-get-assignment (cdr name) value)
245
- (ampersand-expression? name)
246
- (ampersand-expression-assignment name value)
247
- (caris 'at-syntax name)
248
- `(hash-set @ ',(caddr name) ,value)
249
- (error "unknown assignment to place: ~(inspect name)")))
255
+ (def assign-expr (nv)
256
+ (let name (car nv)
257
+ (let value (cadr nv)
258
+ (if (isa 'symbol name)
259
+ `(assign ,name ,value)
260
+ (caris 'dot-syntax name)
261
+ (dot-syntax-assignment (cdr name) value)
262
+ (caris 'hash-get name)
263
+ (hash-get-assignment (cdr name) value)
264
+ (ampersand-expression? name)
265
+ (ampersand-expression-assignment name value)
266
+ (caris 'at-syntax name)
267
+ `(hash-set @ ',(caddr name) ,value)
268
+ (pair? name)
269
+ (destructuring-assign name value)
270
+ (error "unknown assignment to place: " (inspect name))))))
250
271
 
251
272
  ;; generic assignment which unlike builtin 'assign, knows how to assign
252
273
  ;; to hash keys
@@ -255,10 +276,18 @@ scoping, assignment, anonymous functions and more...")
255
276
  ;; (= h.j.k (val)) => (hash-set (hash-get h 'j) 'k (val))
256
277
  ;; (= (&key (expr)) (val)) => (hash-set (expr) 'key (val))
257
278
  ;; (= (&j.k (expr)) (val)) => (hash-set (hash-get (expr) 'j) 'k (val))
258
- (mac = (name value . more)
259
- (if more
260
- `(do ,(assign-expr name value) (= ,@more))
261
- (assign-expr name value)))
279
+ (mac = assignments
280
+ `(do ,@(map assign-expr (pairs assignments))))
281
+
282
+ ;; like 'let, but creates and assigns multiple local variables.
283
+ ;; for example, "(with (a 1 b 2) (+ a b))" returns 3
284
+ ;;
285
+ ;; later variables can references earlier ones:
286
+ ;; (with (a 1 b 2 c (+ a b)) (list a b c)) ;; returns (1 2 3)
287
+ (mac with (assignments . body)
288
+ `((fun ,(map car (pairs assignments))
289
+ (= ,@assignments)
290
+ ,@body) nil))
262
291
 
263
292
  ;; quiet assignment ; like =, but expression returns nil
264
293
  (mac #= (name value)
@@ -334,6 +363,12 @@ scoping, assignment, anonymous functions and more...")
334
363
  (mac aif (expr . body)
335
364
  `(ifv it ,expr ,@body))
336
365
 
366
+ ;; returns the n-th item in the list 'things
367
+ (def nth (n things)
368
+ (if (eq? n 0)
369
+ (car things)
370
+ (nth (- n 1) (cdr things))))
371
+
337
372
  (def destructure/with (var args n)
338
373
  ; provides the argument expression to 'with when
339
374
  ; destructuring arguments are present in a 'fun definition
@@ -342,33 +377,51 @@ scoping, assignment, anonymous functions and more...")
342
377
  args
343
378
  `(,args (nthcdr ,n ,var))))
344
379
 
345
- (def destructure/build (given-args new-args body)
346
- ; used internally by 'fun
380
+ ;; issue a warning if any arg name is the name of a macro
381
+ (def fun/approve-arg-names (orig args body)
382
+ (if (pair? args)
383
+ (do (fun/approve-arg-names orig (car args) body)
384
+ (fun/approve-arg-names orig (cdr args) body))
385
+ args
386
+ (if (hash-get macs args)
387
+ (warnings/new 'arg-shadows-macro "arg " args " shadows macro " args " in arg list " orig " and body " body))))
388
+
389
+ ;; used internally by 'fun
390
+ (def destructure/build (given-args new-args body next)
347
391
  (if (pair? given-args)
348
392
  (if (sym? (car given-args))
349
393
  (destructure/build (cdr given-args)
350
394
  (cons (car given-args) new-args)
351
- body)
395
+ body
396
+ next)
352
397
  (w/uniq destructure
353
398
  (destructure/build (cdr given-args)
354
399
  (cons destructure new-args)
355
- `((with ,(destructure/with destructure (car given-args) 0) ,@body)))))
356
- `(fn ,(rev new-args given-args) ,@body)))
400
+ `((with ,(destructure/with destructure (car given-args) 0) ,@body))
401
+ next)))
402
+ (next (rev new-args given-args) body)))
357
403
 
404
+ (def fun/destructuring-args (args body next)
405
+ (fun/approve-arg-names args args body)
406
+ (destructure/build args nil body next))
358
407
 
359
- (def fun/approve-arg-names (orig args body)
360
- (if (pair? args)
361
- (do (fun/approve-arg-names orig (car args) body)
362
- (fun/approve-arg-names orig (cdr args) body))
363
- args
364
- (if (hash-get macs args)
365
- (warnings/new 'arg-shadows-macro "arg " args " shadows macro " args " in arg list " orig " and body " body))))
408
+ (assign fun/expanders
409
+ (list
410
+ (cons 'destructuring-args fun/destructuring-args)
411
+ (cons 'core-builder (fn (args body next) `(fn ,args ,@body)))))
412
+
413
+ (def fun/expand (args body expanders)
414
+ (if expanders
415
+ ((cdar expanders)
416
+ args
417
+ body
418
+ (fn (a b)
419
+ (fun/expand a b (cdr expanders))))))
366
420
 
367
421
  ;; build a 'fn form, changing 'args and 'body to
368
422
  ;; properly handle any destructuring args if present
369
423
  (mac fun (args . body)
370
- (fun/approve-arg-names args args body)
371
- (destructure/build args nil body))
424
+ (fun/expand args body fun/expanders))
372
425
 
373
426
  ;; assign (f place) to place
374
427
  (mac zap (f place . args)
@@ -13,9 +13,9 @@
13
13
  `(ensuring (fn () ,protection)
14
14
  (fn () ,@body)))
15
15
 
16
+ ;; tests 'test, as long as 'test is non-nil,
17
+ ;; repeatedly executes 'body
16
18
  (mac while (test . body)
17
- ; tests 'test, as long as 'test is non-nil,
18
- ; repeatedly executes 'body
19
19
  (w/uniq (rfname pred)
20
20
  `(rfnwith ,rfname (,pred ,test)
21
21
  (when ,pred
@@ -65,13 +65,31 @@
65
65
  (let ,v (hash-get ,h ,k)
66
66
  (or ,v (returnlet ,v ,val (hash-set ,h ,k ,v)))))))
67
67
 
68
+ ;; same as 'def, but caches the result, keyed on args, so for a given set of args the result
69
+ ;; is only ever calculated once
70
+ ;;
71
+ ;; WARNING: in current incarnation, won't work with destructuring args
68
72
  (mac defmemo (name args . body)
69
- ; same as 'def, but caches the result, keyed on args, so for a given set of args the result
70
- ; is only ever calculated once
71
- (let forms (filter-forms (build-def-hash (hash)) body)
73
+ (let forms (filter-forms (build-def-hash) body)
72
74
  (w/uniq h
73
75
  `(let ,h (hash)
74
76
  (def ,name ,args
75
77
  ,@(map (fn (c) (cons 'comment c)) forms.comment)
76
78
  ,@(map (fn (c) (cons 'chapter c)) forms.chapter)
77
79
  (cache-get ,h (list ,@args) (do ,@(hash-get forms nil))))))))
80
+
81
+ ;; memoises a function expression
82
+ ;; args: the function arguments
83
+ ;; body: a list of function body expressions
84
+ ;; next: a function to assemble a function expression from 'args and 'body
85
+ ;; returns whatever 'next returns, where 'body is memoised based on the value of 'args
86
+ (def memoise (args body next)
87
+ (let (memo newbody) (filter-remove '#memoise body)
88
+ (if memo
89
+ (w/uniq h
90
+ `(let ,h (hash) ,(next args `((cache-get ,h (list ,@args) (do ,@newbody))))))
91
+ (next args body))))
92
+
93
+ (assign fun/expanders
94
+ (cons
95
+ (cons 'memoise memoise) fun/expanders))
@@ -101,3 +101,13 @@
101
101
  (dp ,@(cdr args))
102
102
  ,nearg)))
103
103
  nil))
104
+
105
+ ;; returns a function that returns a number sequence. Example:
106
+ ;; (let c (counter)
107
+ ;; (p (c)) ;;=> 0
108
+ ;; (p (c)) ;;=> 1
109
+ ;; (p (c))) ;;=> 2
110
+ ;;
111
+ (def counter ()
112
+ (let i -1
113
+ (fn () (++ i))))
@@ -57,20 +57,21 @@
57
57
  (def reject (f things)
58
58
  (collect !f things))
59
59
 
60
- ;; returns the n-th item in the list 'things
61
- (def nth (n things)
62
- (if (eq? n 0)
63
- (car things)
64
- (nth (- n 1) (cdr things))))
60
+ (def each/build-expression (var things body othervars otherparams)
61
+ (w/uniq (xs c)
62
+ `(rfnwith ,c (,xs ,things ,@othervars)
63
+ (if (pair? ,xs)
64
+ (let ,var (car ,xs)
65
+ ,@body
66
+ (,c (cdr ,xs) ,@otherparams))))))
65
67
 
66
68
  ;; repeatedly assigns an element of 'things to 'var,
67
69
  ;; and executes 'body each time
68
70
  (mac each (var things . body)
69
- (w/uniq (xs c)
70
- `(rfnwith ,c (,xs ,things)
71
- (if (pair? ,xs)
72
- (do (let ,var (car ,xs) ,@body)
73
- (,c (cdr ,xs)))))))
71
+ (each/build-expression var things body))
72
+
73
+ (mac each-with-index (ivar var things . body)
74
+ (each/build-expression var things body `(,ivar 0) `((+ ,ivar 1))))
74
75
 
75
76
  (def reduce (f things)
76
77
  (rfnwith rd (acc (car things) list (cdr things))
@@ -243,7 +244,6 @@
243
244
 
244
245
  ;; like map, but function 'f takes two arguments: the thing and the 0-based index of the thing
245
246
  (def map-with-index (f things)
246
- (let i -1
247
- (map (fn (thing)
248
- (f thing (++ i)))
247
+ (let c (counter)
248
+ (map (fn (thing) (f thing (c)))
249
249
  things)))
@@ -29,5 +29,5 @@
29
29
  (define-prefix-list-macro "^λ.*" vars expr
30
30
  ;; allows (map λa(upcase a.name) people)
31
31
  ;; as shortcut for (map (fn (a) (upcase a.name)) people)
32
- (let var-list (map sym (collect !empty? (cdr:string-split vars)))
32
+ (let var-list (map sym (collect !empty? (cdr:string-split vars "")))
33
33
  `(fn ,var-list ,expr)))
@@ -43,6 +43,8 @@
43
43
  (fn (thing)
44
44
  (if (isa 'string thing)
45
45
  (pp/esc-str-literal thing)
46
+ (isa 'symbol thing)
47
+ "\~|~(just thing)|"
46
48
  "\~~(pp thing)")))
47
49
 
48
50
  (def pp/string-pieces (pp things) "\"~(joinstr "" (map (pp/string-piece pp) things))\"")
@@ -20,25 +20,25 @@
20
20
 
21
21
  (examples-for destructure/build
22
22
  ("with no args"
23
- (destructure/build nil nil '(x))
23
+ (destructure/build nil nil '(x) (fn (a b) `(fn ,a ,@b)))
24
24
  (fn nil x))
25
25
 
26
26
  ("with one arg"
27
- (destructure/build '(a) nil '(x))
27
+ (destructure/build '(a) nil '(x) (fn (a b) `(fn ,a ,@b)))
28
28
  (fn (a) x))
29
29
 
30
30
  ("with one rest-arg"
31
- (destructure/build 'args nil '(x))
31
+ (destructure/build 'args nil '(x) (fn (a b) `(fn ,a ,@b)))
32
32
  (fn args x))
33
33
 
34
34
  ("with one destructuring arg"
35
35
  (do (reset-uniq-counter)
36
- (destructure/build '((a b)) nil '(x)))
36
+ (destructure/build '((a b)) nil '(x) (fn (a b) `(fn ,a ,@b))))
37
37
  (fn (destructure-1) (with (a (nth 0 destructure-1) b (nth 1 destructure-1)) x)))
38
38
 
39
39
  ("with complex args"
40
40
  (do (reset-uniq-counter)
41
- (destructure/build '(a (b c) (d (e f)) g . h) nil '(x)))
41
+ (destructure/build '(a (b c) (d (e f)) g . h) nil '(x) (fn (a b) `(fn ,a ,@b))))
42
42
  (fn (a destructure-1 destructure-2 g . h)
43
43
  (with (d (nth 0 destructure-2)
44
44
  (e f) (nth 1 destructure-2))
@@ -49,12 +49,23 @@
49
49
  (examples-for fun
50
50
  ("complete expansion, handles recursive destructures"
51
51
  (do (reset-uniq-counter)
52
- (pre-compile '(fun ((a (b c)) d . e) x)))
52
+ (pre-compile '(fun ((a (b c)) d . e) (do-the-thing a b c d e))))
53
53
  (fn (destructure-1 d . e)
54
54
  ((fn (a destructure-2)
55
- ((fn (b c) x)
56
- (nth 0 destructure-2)
57
- (nth 1 destructure-2))) (nth 0 destructure-1) (nth 1 destructure-1))))
55
+ ((fn (b c)
56
+ ((fn nil
57
+ (assign b (nth 0 destructure-2))
58
+ (assign c (nth 1 destructure-2))))
59
+ ((fn nil
60
+ (assign a (nth 0 destructure-1))
61
+ ((fn (destructuring-assign-3)
62
+ (assign b (car destructuring-assign-3))
63
+ (assign c (car (cdr destructuring-assign-3))))
64
+ (nth 1 destructure-1))))
65
+ (do-the-thing a b c d e))
66
+ nil))
67
+ nil)))
68
+
58
69
 
59
70
  ("nested improper arguments"
60
71
  (let (a (b c . d) e) (list "A" (list "B" "C" "D0" "D1" "D2") "E")
@@ -79,3 +90,24 @@
79
90
  (let (g (h (i j) k)) (list "w" (list "o" (list "r" "l") "d"))
80
91
  (string-pieces a b c d e f g h i j k)))
81
92
  "hello world"))
93
+
94
+ (examples-for =
95
+ ("destructures LHS"
96
+ (let a 1
97
+ (let b 2
98
+ (let c 3
99
+ (let d 4
100
+ (let e 5
101
+ (= (a (b e) c . d) (list 'this '(that those) 'another 11 22 33))
102
+ (list a b c d e))))))
103
+ (this that another (11 22 33) those)))
104
+
105
+ (examples-for with
106
+ ("destructures its args, also allows references to earlier args"
107
+ (with ((a (b . c) d . e) '(1 (2 3 4 5) 6 7 8 9)
108
+ x a
109
+ y c
110
+ z (fn (n) (if (eq? n 1) 1 (* n (z (- n 1)))))
111
+ g (z 6))
112
+ (list a b c d e x y g))
113
+ (1 2 (3 4 5) 6 (7 8 9) 1 (3 4 5) 720)))
@@ -2,3 +2,8 @@
2
2
  ("iterates over each item in list"
3
3
  (let acc 0 (each x '(1 2 3 4) (assign acc (+ x acc))) acc)
4
4
  10))
5
+
6
+ (examples-for each-with-index
7
+ ("iterates over each item in list"
8
+ (returnlet acc nil (each-with-index i x '(a b c d) (push (list i x) acc)))
9
+ ( (3 d) (2 c) (1 b) (0 a) )))
@@ -13,7 +13,7 @@
13
13
 
14
14
  ("expands thrice for n = 3"
15
15
  (explain-mac 3 '(afn (a) (let b (+ 2 a) (* b b))))
16
- (with (self nil) (assign self (fn (a) (let b (+ 2 a) (* b b))))))
16
+ ((fun (self) (assign self (fn (a) (let b (+ 2 a) (* b b))))) nil))
17
17
 
18
18
  ("expands four times for n = 4"
19
19
  (explain-mac 4 '(afn (a) (let b (+ 2 a) (* b b))))
@@ -1,3 +1,18 @@
1
+ (examples-for filter-remove
2
+ ("removes (memoise) from a list of forms"
3
+ (filter-remove 'memoise '((trace)
4
+ ;; this is a comment
5
+ (memoise)
6
+ (let x a
7
+ (+ x b)
8
+ (bingo dingbat))))
9
+ (((memoise))
10
+ ((trace)
11
+ (comment "this is a comment")
12
+ (let x a
13
+ (+ x b)
14
+ (bingo dingbat))))))
15
+
1
16
  (examples-for filter-forms
2
17
  ("groups forms by their 'car if the 'car is a key in the given hash"
3
18
  (let ff (filter-forms { car nil comment nil mac nil }
@@ -70,6 +70,10 @@
70
70
  (parse-in-string (joinstr "" (list "hello, " '~ "(world), take me to your " '~ "dealer please")))
71
71
  (string-pieces "hello, " (world) ", take me to your " dealer " please"))
72
72
 
73
+ ("parses a plain string whose entire content is a single interpolation"
74
+ (parse-in-string (joinstr "" (list '~ "(hello world)")))
75
+ (hello world))
76
+
73
77
  ("parses a plain string of html text with interpolations"
74
78
  (parse-in-string "<div id='content_item_~~{id}'><label>~~{data-name-1}</label> ~~{data-text-1}</div>")
75
79
  (string-pieces "<div id='content_item_" (brace-list id) "'><label>" (brace-list data-name-1) "</label> " (brace-list data-text-1) "</div>"))
@@ -279,7 +279,7 @@ toto")
279
279
 
280
280
  ("special syntax"
281
281
  (pp '(string-pieces "hello " (bang-syntax || (dot-syntax x y (ampersand-syntax foo bar))) " and welcome to " (prefix-list "%%" (a b c d)) " and friends!"))
282
- "\"hello ~~!x.y.foo&bar and welcome to ~~%%(a b c d) and friends!\"")
282
+ "\"hello ~~|!x.y.foo&bar| and welcome to ~~%%(a b c d) and friends!\"")
283
283
 
284
284
  ("percent-syntax"
285
285
  (pp '(percent-syntax || (dot-syntax x y)))
@@ -55,6 +55,10 @@ and args (\"world\" 36 6)"
55
55
  (collect !empty? (string-split "word"))
56
56
  ("w" "o" "r" "d"))
57
57
 
58
+ ("splits on regexp"
59
+ (string-split "hello, darkness ; my old friend\nI've come : to talk - with you again..." (regexp "\[\\n;:\\-,\]"))
60
+ ("hello" " darkness " " my old friend" "I've come " " to talk " " with you again..."))
61
+
58
62
  ("returns empty leading, internal, and trailing segments"
59
63
  (string-split "and" "and")
60
64
  ("" ""))
@@ -0,0 +1,7 @@
1
+ class Nydp::Builtin::Regexp
2
+ include Nydp::Builtin::Base, Singleton
3
+
4
+ def builtin_invoke vm, args
5
+ vm.push_arg Regexp.compile(args.car.to_s)
6
+ end
7
+ end
@@ -3,7 +3,9 @@ class Nydp::Builtin::StringSplit
3
3
 
4
4
  def builtin_invoke vm, args
5
5
  target = args.car.to_s
6
- separator = args.cdr.car.to_s
6
+ separator = args.cdr.car
7
+ separator = separator.to_s unless separator.is_a? Regexp
8
+
7
9
  result = target.split separator, -1
8
10
 
9
11
  vm.push_arg Nydp::Pair.from_list result
data/lib/nydp/core.rb CHANGED
@@ -59,6 +59,7 @@ module Nydp
59
59
  Symbol.mk("handle-error" , ns).assign(Nydp::Builtin::HandleError.instance)
60
60
  Symbol.mk("parse-in-string" , ns).assign(Nydp::Builtin::ParseInString.instance)
61
61
  Symbol.mk("random-string" , ns).assign(Nydp::Builtin::RandomString.instance)
62
+ Symbol.mk("regexp" , ns).assign(Nydp::Builtin::Regexp.instance)
62
63
  Symbol.mk("to-string" , ns).assign(Nydp::Builtin::ToString.instance)
63
64
  Symbol.mk("to-integer" , ns).assign(Nydp::Builtin::ToInteger.instance)
64
65
  Symbol.mk("string-length" , ns).assign(Nydp::Builtin::StringLength.instance)
data/lib/nydp/date.rb CHANGED
@@ -29,9 +29,9 @@ module Nydp
29
29
  def <=> other ; is_date?(other) && ruby_date <=> other.ruby_date ; end
30
30
  def eql? d ; self == d ; end
31
31
  def hash ; ruby_date.hash ; end
32
- def is_date? other ; other.is_a? Nydp::Date ; end
33
- def - other ; r2n(ruby_date - (is_date?(other) ? other.ruby_date : other)) ; end
34
- def + int ; int.is_a?(Fixnum) ? r2n(ruby_date + int) : r2n(change(*int.to_ruby)) ; end
32
+ def is_date? other ; other.is_a? Nydp::Date ; end
33
+ def - other ; r2n(ruby_date - (is_date?(other) ? other.ruby_date : other)) ; end
34
+ def + int ; int.is_a?(Integer) ? r2n(ruby_date + int) : r2n(change(*int.to_ruby)) ; end
35
35
 
36
36
  @@pass_through = %i{ monday? tuesday? wednesday? thursday? friday? saturday? sunday? }
37
37
  @@keys = Set.new %i{
@@ -39,7 +39,7 @@ module Nydp
39
39
  @expr.map { |x| x.lexical_reach n}.max
40
40
  end
41
41
 
42
- def inspect ; @expr.map { |x| x.inspect }.join ' ' ; end
42
+ def inspect ; @expr.map { |x| x.inspect }.join(' ') ; end
43
43
  def source ; @source ; end
44
44
  def to_s ; source.to_s ; end
45
45
  end
data/lib/nydp/helper.rb CHANGED
@@ -83,7 +83,7 @@ module Nydp
83
83
 
84
84
  def literal? expr
85
85
  case expr
86
- when String, Float, Integer, Fixnum, Nydp::Symbol, Nydp::Truth, Nydp::Nil
86
+ when String, Float, Integer, Integer, Nydp::Symbol, Nydp::Truth, Nydp::Nil
87
87
  true
88
88
  else
89
89
  false
data/lib/nydp/parser.rb CHANGED
@@ -131,14 +131,16 @@ module Nydp
131
131
  fragments = [sym(:"string-pieces")]
132
132
  string_token = token_stream.next_string_fragment(open_delimiter, close_delimiter, INTERPOLATION_SIGN, INTERPOLATION_ESCAPES)
133
133
  raise "unterminated string" if string_token.nil?
134
- fragments << string_token.string
134
+ fragments << string_token.string if string_token.string != ""
135
135
  while !(string_token.is_a? StringFragmentCloseToken)
136
136
  fragments << expression(token_stream)
137
137
  string_token = token_stream.next_string_fragment('', close_delimiter, INTERPOLATION_SIGN, INTERPOLATION_ESCAPES)
138
- fragments << string_token.string
138
+ fragments << string_token.string if string_token.string != ""
139
139
  end
140
140
 
141
- if fragments.size == 2
141
+ if fragments.size == 1
142
+ return ""
143
+ elsif fragments.size == 2
142
144
  return fragments[1]
143
145
  else
144
146
  return Pair.from_list fragments
data/lib/nydp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Nydp
2
- VERSION = "0.4.6"
2
+ VERSION = "0.5.0"
3
3
  end
data/spec/pair_spec.rb CHANGED
@@ -18,7 +18,9 @@ describe Nydp::Pair do
18
18
 
19
19
  describe :== do
20
20
  it "should be true for two empty lists" do
21
- expect(Nydp::Pair.new(NIL, NIL)).to eq Nydp::Pair.new(NIL, NIL)
21
+ expect(Nydp::Pair.new(Nydp::NIL, Nydp::NIL)).to eq Nydp::Pair.new(Nydp::NIL, Nydp::NIL)
22
+
23
+ expect(Nydp::Pair.new(nil, nil)).to eq Nydp::Pair.new(nil, nil)
22
24
  end
23
25
 
24
26
  it "there is no empty list, only NIL" do
data/spec/parser_spec.rb CHANGED
@@ -141,8 +141,8 @@ describe Nydp::Parser do
141
141
  parsed = parse("foo.2:3:4")
142
142
  expect(parsed.inspect).to eq "(colon-syntax (dot-syntax foo 2) 3 4)"
143
143
 
144
- expect(parsed.map &:class).to eq [Nydp::Symbol, Nydp::Pair, Fixnum, Fixnum]
145
- expect(parsed.cdr.car.map &:class).to eq [Nydp::Symbol, Nydp::Symbol, Fixnum]
144
+ expect(parsed.map &:class).to eq [Nydp::Symbol, Nydp::Pair, Integer, Integer]
145
+ expect(parsed.cdr.car.map &:class).to eq [Nydp::Symbol, Nydp::Symbol, Integer]
146
146
  end
147
147
 
148
148
  it "should handle prefix and postfix syntax also" do
@@ -263,7 +263,7 @@ describe Nydp::Parser do
263
263
  it "parses a string with a simple interpolation" do
264
264
  str = "foo "
265
265
  empty = ""
266
- expect(parse '"foo ~foo"').to eq pair_list([string_pieces, str, foo, empty])
266
+ expect(parse '"foo ~foo"').to eq pair_list([string_pieces, str, foo])
267
267
  end
268
268
 
269
269
  it "parses a string with a more complex interpolation" do
@@ -284,7 +284,7 @@ describe Nydp::Parser do
284
284
 
285
285
  it "parses a string with only an interpolation" do
286
286
  empty = ""
287
- expect(parse '"~foo"').to eq pair_list([string_pieces, empty, foo, empty])
287
+ expect(parse '"~foo"').to eq foo
288
288
  end
289
289
 
290
290
  it "should even parse comments" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nydp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.6
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Conan Dalton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-05 00:00:00.000000000 Z
11
+ date: 2021-03-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -195,6 +195,7 @@ files:
195
195
  - lib/nydp/builtin/quit.rb
196
196
  - lib/nydp/builtin/rand.rb
197
197
  - lib/nydp/builtin/random_string.rb
198
+ - lib/nydp/builtin/regexp.rb
198
199
  - lib/nydp/builtin/ruby_wrap.rb
199
200
  - lib/nydp/builtin/script_run.rb
200
201
  - lib/nydp/builtin/set_intersection.rb
@@ -282,8 +283,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
282
283
  - !ruby/object:Gem::Version
283
284
  version: '0'
284
285
  requirements: []
285
- rubyforge_project:
286
- rubygems_version: 2.5.2.3
286
+ rubygems_version: 3.0.3
287
287
  signing_key:
288
288
  specification_version: 4
289
289
  summary: A civilised yet somewhat dangerous kind of Lisp for a new generation