nydp 0.4.6 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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