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 +5 -5
- data/lib/lisp/core-015-documentation.nydp +24 -8
- data/lib/lisp/core-017-builtin-dox.nydp +1 -0
- data/lib/lisp/core-030-syntax.nydp +100 -47
- data/lib/lisp/core-035-flow-control.nydp +23 -5
- data/lib/lisp/core-040-utils.nydp +10 -0
- data/lib/lisp/core-043-list-utils.nydp +13 -13
- data/lib/lisp/core-070-prefix-list.nydp +1 -1
- data/lib/lisp/core-080-pretty-print.nydp +2 -0
- data/lib/lisp/tests/destructuring-examples.nydp +41 -9
- data/lib/lisp/tests/each-tests.nydp +5 -0
- data/lib/lisp/tests/explain-mac-examples.nydp +1 -1
- data/lib/lisp/tests/filter-forms-examples.nydp +15 -0
- data/lib/lisp/tests/parser-tests.nydp +4 -0
- data/lib/lisp/tests/pretty-print-tests.nydp +1 -1
- data/lib/lisp/tests/string-tests.nydp +4 -0
- data/lib/nydp/builtin/regexp.rb +7 -0
- data/lib/nydp/builtin/string_split.rb +3 -1
- data/lib/nydp/core.rb +1 -0
- data/lib/nydp/date.rb +3 -3
- data/lib/nydp/function_invocation.rb +1 -1
- data/lib/nydp/helper.rb +1 -1
- data/lib/nydp/parser.rb +5 -3
- data/lib/nydp/version.rb +1 -1
- data/spec/pair_spec.rb +3 -1
- data/spec/parser_spec.rb +4 -4
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz: '
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: '0389044de6d7b6230da9315bc8dde967e1ddf8ed77df2b8ef4106ce9bfc3e93a'
|
4
|
+
data.tar.gz: 133567982e2fbb734ea429e98197e4b7d5bc49c2130f64ec630c095adcd1f250
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
173
|
-
(
|
174
|
-
|
175
|
-
|
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
|
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
|
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
|
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
|
-
|
101
|
-
|
102
|
-
|
100
|
+
`((fun ,(map car (pairs parms))
|
101
|
+
,@body)
|
102
|
+
,@(map cadr (pairs parms))))
|
103
103
|
|
104
|
-
;;
|
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
|
-
`(
|
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
|
-
(
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
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 (
|
239
|
-
(
|
240
|
-
|
241
|
-
(
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
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 =
|
259
|
-
(
|
260
|
-
|
261
|
-
|
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
|
-
|
346
|
-
|
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
|
-
|
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
|
-
(
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
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/
|
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
|
-
|
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
|
-
|
61
|
-
(
|
62
|
-
|
63
|
-
|
64
|
-
|
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
|
-
(
|
70
|
-
|
71
|
-
|
72
|
-
|
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
|
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)))
|
@@ -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)
|
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)
|
56
|
-
|
57
|
-
|
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
|
-
(
|
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
|
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
|
("" ""))
|
@@ -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
|
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
|
33
|
-
def - other ; r2n(ruby_date - (is_date?(other) ? other.ruby_date : other))
|
34
|
-
def + int ; int.is_a?(
|
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{
|
data/lib/nydp/helper.rb
CHANGED
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 ==
|
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
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,
|
145
|
-
expect(parsed.cdr.car.map &:class).to eq [Nydp::Symbol, Nydp::Symbol,
|
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
|
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
|
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
|
+
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:
|
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
|
-
|
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
|