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 +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
|