nydp 0.1.0 → 0.1.1
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 +4 -4
- data/README.md +108 -1
- data/lib/lisp/core-000.nydp +18 -0
- data/lib/lisp/{core-01-precompile.nydp → core-010-precompile.nydp} +4 -10
- data/lib/lisp/core-015-documentation.nydp +89 -0
- data/lib/lisp/core-020-utils.nydp +22 -0
- data/lib/lisp/{core-03-syntax.nydp → core-030-syntax.nydp} +1 -5
- data/lib/lisp/{core-04-utils.nydp → core-040-utils.nydp} +57 -8
- data/lib/lisp/{core-05-test-runner.nydp → core-050-test-runner.nydp} +0 -0
- data/lib/lisp/{core-06-benchmarking.nydp → core-060-benchmarking.nydp} +0 -0
- data/lib/lisp/core-070-prefix-list.nydp +33 -0
- data/lib/lisp/core-080-pretty-print.nydp +101 -0
- data/lib/lisp/tests/boot-tests.nydp +8 -25
- data/lib/lisp/tests/dox-tests.nydp +103 -0
- data/lib/lisp/tests/list-tests.nydp +66 -0
- data/lib/lisp/tests/pretty-print-tests.nydp +25 -0
- data/lib/lisp/tests/string-tests.nydp +31 -0
- data/lib/lisp/tests/unparse-tests.nydp +7 -0
- data/lib/nydp/builtin/hash.rb +18 -0
- data/lib/nydp/builtin/puts.rb +6 -2
- data/lib/nydp/core.rb +1 -0
- data/lib/nydp/hash.rb +3 -10
- data/lib/nydp/pair.rb +6 -0
- data/lib/nydp/parser.rb +1 -1
- data/lib/nydp/version.rb +1 -1
- data/spec/hash_spec.rb +46 -0
- data/spec/pair_spec.rb +8 -0
- metadata +17 -10
- data/lib/lisp/core-00.nydp +0 -13
- data/lib/lisp/core-02-utils.nydp +0 -6
- data/lib/lisp/core-07-prefix-list.nydp +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 031f54326dfa57ae2a067c931bd600bd9e2cc6c0
|
4
|
+
data.tar.gz: aa49dab4d81173e02e968958028c1cad2948079c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e263b9ce4dff11cd6ac7e7d7ef5787ad553807eb1f2048bbd357973ddbbc910feaaf7c340c0bb8347f31d90e07c4e5b23af3992ed31cb8e61edef8e878c480b5
|
7
|
+
data.tar.gz: 0966de059bcf3658fe137c9a436bf817d84b5bc4ad443b8afd14e22fbecc7e392c23732d6a5a5db8862345bd5ba70b7ae09e87e67e0a910484792e1882e27eda
|
data/README.md
CHANGED
@@ -275,10 +275,117 @@ error
|
|
275
275
|
nydp > (parse "; blah blah")
|
276
276
|
|
277
277
|
==> (comment "blah blah")
|
278
|
+
```
|
279
|
+
|
280
|
+
Except in 'mac and 'def forms, by default, `comment` is a macro that expands to nil. If you have a better idea, go for it.
|
281
|
+
|
282
|
+
#### 8 Prefix lists
|
283
|
+
|
284
|
+
The parser emits a special form if it detects a prefix-list, that is, a list with non-delimiter characters immediately preceding
|
285
|
+
the opening delimiter. For example:
|
286
|
+
|
287
|
+
```lisp
|
288
|
+
nydp > (parse "%w(a b c)")
|
289
|
+
|
290
|
+
==> (prefix-list "%w" (a b c))
|
291
|
+
```
|
292
|
+
|
293
|
+
This allows for preprocessing lists in a way not possible for macros. nydp uses this feature to implement shortcut oneline
|
294
|
+
functions, as in
|
295
|
+
|
296
|
+
```lisp
|
297
|
+
nydp > (parse "λx(len x)")
|
298
|
+
|
299
|
+
==> ((prefix-list "λx" (len x)))
|
300
|
+
|
301
|
+
nydp > (pre-compile '(prefix-list "λx" (len x)))
|
302
|
+
|
303
|
+
==> (fn (x) (len x))
|
304
|
+
```
|
305
|
+
|
306
|
+
Each character after 'λ becomes a function argument:
|
307
|
+
|
308
|
+
```lisp
|
309
|
+
nydp > (parse "λxy(* x y)")
|
310
|
+
|
311
|
+
==> ((prefix-list "λxy" (* x y)))
|
312
|
+
|
313
|
+
nydp > (pre-compile '(prefix-list "λxy" (* x y)))
|
314
|
+
|
315
|
+
==> (fn (x y) (* x y))
|
316
|
+
```
|
317
|
+
|
318
|
+
Use 'define-prefix-list-macro to define a new handler for a prefix-list. Here's the code for the 'λ shortcut:
|
319
|
+
|
320
|
+
```lisp
|
321
|
+
(define-prefix-list-macro "^λ.+" vars expr
|
322
|
+
(let var-list (map sym (cdr:string-split vars))
|
323
|
+
`(fn ,var-list ,expr)))
|
324
|
+
```
|
325
|
+
|
326
|
+
In this case, the regex matches an initial 'λ ; there is no constraint however on the kind of regex a prefix-list-macro might use.
|
327
|
+
|
328
|
+
|
329
|
+
#### 9 Self-documenting
|
278
330
|
|
279
|
-
|
331
|
+
Once the 'dox system is bootstrapped, any further use of 'mac or 'def will create documentation.
|
332
|
+
|
333
|
+
Any comments at the start of the form body will be used to generate help text. For example:
|
334
|
+
|
335
|
+
```lisp
|
336
|
+
nydp > (def foo (x y)
|
337
|
+
; return the foo of x and y
|
338
|
+
(* x y))
|
339
|
+
|
340
|
+
nydp > (dox foo)
|
341
|
+
|
342
|
+
Function : foo
|
343
|
+
args : (x y)
|
344
|
+
return the foo of x and y
|
345
|
+
|
346
|
+
source
|
347
|
+
======
|
348
|
+
(def foo (x y)
|
349
|
+
(* x y))
|
280
350
|
```
|
281
351
|
|
352
|
+
'dox is a macro that generates code to output documentation to stdout. 'dox-lookup is a function that returns structured documentation.
|
353
|
+
|
354
|
+
```lisp
|
355
|
+
nydp > (dox-lookup 'foo)
|
356
|
+
((foo def ("return the foo of x and y") (x y) (def foo (x y) (* x y))))
|
357
|
+
```
|
358
|
+
|
359
|
+
Not as friendly, but more amenable to programmatic manipulation. Each subsequent definition of 'foo (if you override it, define
|
360
|
+
it as a macro, or define it again in some other context) will generate a new documentation structure, which will simply be preprended to
|
361
|
+
the existing list.
|
362
|
+
|
363
|
+
#### 10 Pretty-Printing
|
364
|
+
|
365
|
+
'dox above uses the pretty printer to display code source. The pretty-printer is hard-coded to handle some special cases,
|
366
|
+
so it will unparse special syntax, prefix-lists, quote, quasiquote, unquote, and unquote-splicing.
|
367
|
+
|
368
|
+
You can examine its behaviour at the repl:
|
369
|
+
|
370
|
+
```lisp
|
371
|
+
nydp > (p: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!"))
|
372
|
+
|
373
|
+
==> "hello ~!x.y.foo&bar and welcome to ~%%(a b c d) and friends!"
|
374
|
+
|
375
|
+
nydp > (p:pp:dox-src 'pp/find-breaks)
|
376
|
+
|
377
|
+
(def pp/find-breaks (form)
|
378
|
+
(if (eq? 'if (car form))
|
379
|
+
(let if-args (cdr form)
|
380
|
+
(cons (list 'if (car if-args)) (map list (cdr if-args))))
|
381
|
+
(or
|
382
|
+
(pp/find-breaks/mac form)
|
383
|
+
(list form))))
|
384
|
+
```
|
385
|
+
|
386
|
+
The pretty-printer is still rather primitive in that it only indents according to some hard-coded rules, and according to argument-count
|
387
|
+
for documented macros. It has no means of wrapping forms that get too long, or that extend beyond a certain predefined margin or column number.
|
388
|
+
|
282
389
|
## Installation
|
283
390
|
|
284
391
|
Add this line to your application's Gemfile:
|
@@ -0,0 +1,18 @@
|
|
1
|
+
; -*- lisp -*-
|
2
|
+
;;
|
3
|
+
;; Acknowledgements to Paul Graham, Robert Morris, and their ancestor programmers.
|
4
|
+
;; nydp's main inspiration is arc, and many nydp features (including, but not limited
|
5
|
+
;; to, 'do, 'rfn, 'loop, 'for) were directly inspired by (aka stolen from) arc.arc
|
6
|
+
;;
|
7
|
+
|
8
|
+
(assign list (fn args args))
|
9
|
+
(assign caar (fn (arg) (car (car arg))))
|
10
|
+
(assign cadr (fn (arg) (car (cdr arg))))
|
11
|
+
(assign cdar (fn (arg) (cdr (car arg))))
|
12
|
+
(assign cddr (fn (arg) (cdr (cdr arg))))
|
13
|
+
(assign cadar (fn (arg) (car (cdr (car arg)))))
|
14
|
+
(assign caddr (fn (arg) (car (cdr (cdr arg)))))
|
15
|
+
(assign cdddr (fn (arg) (cdr (cdr (cdr arg)))))
|
16
|
+
(assign cadddr (fn (arg) (car (cdr (cdr (cdr arg))))))
|
17
|
+
(assign no (fn (arg) (cond arg nil t)))
|
18
|
+
(assign just (fn (arg) arg))
|
@@ -42,6 +42,7 @@
|
|
42
42
|
|
43
43
|
(debug-pre-compile nil)
|
44
44
|
|
45
|
+
; we override this later to provide automatic documentation
|
45
46
|
(hash-set macs 'def
|
46
47
|
(fn (name args . body)
|
47
48
|
(list 'assign
|
@@ -118,13 +119,6 @@
|
|
118
119
|
(hash-set macs 'quasiquote
|
119
120
|
(fn (arg) (qq-quasiquote arg 0)))
|
120
121
|
|
121
|
-
(hash-set macs '
|
122
|
-
|
123
|
-
|
124
|
-
(mac if args
|
125
|
-
(cond (no args) nil
|
126
|
-
(cond (cdr args)
|
127
|
-
(cond (cddr args)
|
128
|
-
`(cond ,(car args) ,(cadr args) (if ,@(cddr args)))
|
129
|
-
`(cond ,(car args) ,(cadr args)))
|
130
|
-
(car args))))
|
122
|
+
(hash-set macs 'do
|
123
|
+
(fn args
|
124
|
+
`((fn nil ,@args))))
|
@@ -0,0 +1,89 @@
|
|
1
|
+
((fn (dox)
|
2
|
+
(def dox-add-doc (name what texts args src)
|
3
|
+
(hash-set dox
|
4
|
+
name
|
5
|
+
(cons (list name what texts args src)
|
6
|
+
(hash-get dox sym))))
|
7
|
+
|
8
|
+
(def dox-lookup (sym) (hash-get dox sym))
|
9
|
+
|
10
|
+
(def dox? (sym) (hash-key? dox sym))
|
11
|
+
|
12
|
+
(def dox-names () (hash-keys dox))
|
13
|
+
|
14
|
+
(def dox-what-is? (name)
|
15
|
+
(cond (dox? name)
|
16
|
+
(cadr (car (dox-lookup name)))))
|
17
|
+
|
18
|
+
(def dox-src (name)
|
19
|
+
(cond (dox? name)
|
20
|
+
(car (cddr (cddr (car (dox-lookup name)))))))
|
21
|
+
|
22
|
+
(def dox-arg-names (name)
|
23
|
+
(cond (dox? name)
|
24
|
+
(cadddr (car (dox-lookup name))))))
|
25
|
+
(hash))
|
26
|
+
|
27
|
+
(def isa-comment? (thing)
|
28
|
+
(cond (pair? thing)
|
29
|
+
(eq? (car thing) 'comment)))
|
30
|
+
|
31
|
+
(def rev-accum (things acc)
|
32
|
+
(cond (no things)
|
33
|
+
acc
|
34
|
+
(rev-accum (cdr things)
|
35
|
+
(cons (car things)
|
36
|
+
acc))))
|
37
|
+
|
38
|
+
(def rev (things) (rev-accum things nil))
|
39
|
+
|
40
|
+
(def dox-gather-comments (body acc)
|
41
|
+
(cond (isa-comment? (car body))
|
42
|
+
(dox-gather-comments (cdr body)
|
43
|
+
(cons (cadar body)
|
44
|
+
acc))
|
45
|
+
(list (rev acc) body)))
|
46
|
+
|
47
|
+
(def define-mac-expr (name args documentation body)
|
48
|
+
; used internally by 'mac
|
49
|
+
`(do (hash-set macs ',name (fn ,args ,@body))
|
50
|
+
(dox-add-doc ',name
|
51
|
+
'mac
|
52
|
+
',documentation
|
53
|
+
',args
|
54
|
+
'(mac ,name ,args ,@body))))
|
55
|
+
|
56
|
+
(hash-set macs 'mac
|
57
|
+
(fn (name args . body)
|
58
|
+
(apply define-mac-expr
|
59
|
+
name
|
60
|
+
args
|
61
|
+
(dox-gather-comments body))))
|
62
|
+
|
63
|
+
(dox-add-doc 'mac
|
64
|
+
'mac
|
65
|
+
'("define a new global macro")
|
66
|
+
'(name args . body)
|
67
|
+
(dox-src 'define-mac-expr))
|
68
|
+
|
69
|
+
(dox-add-doc 'do
|
70
|
+
'mac
|
71
|
+
'("perform a series of operations")
|
72
|
+
'args
|
73
|
+
'`((fn nil ,@args)))
|
74
|
+
|
75
|
+
(def define-def-expr (name args documentation body)
|
76
|
+
; used internally by 'def
|
77
|
+
`(do (assign ,name (fn ,args ,@body))
|
78
|
+
(dox-add-doc ',name
|
79
|
+
'def
|
80
|
+
',documentation
|
81
|
+
',args
|
82
|
+
'(def ,name ,args ,@body))))
|
83
|
+
|
84
|
+
(mac def (name args . body)
|
85
|
+
; define a new function in the global namespace
|
86
|
+
(apply define-def-expr
|
87
|
+
name
|
88
|
+
args
|
89
|
+
(dox-gather-comments body)))
|
@@ -0,0 +1,22 @@
|
|
1
|
+
(mac if args
|
2
|
+
; with arguments a, return a
|
3
|
+
; with arguments a b, return b if a is true, otherwise nil
|
4
|
+
; with arguments a b c, return b if a is true, otherwise return c
|
5
|
+
; with arguments a b c d, return b if a is true, otherwise return d if c is true, otherwise nil
|
6
|
+
; with arguments a b c d e, return b if a is true, otherwise return d if c is true, otherwise e
|
7
|
+
; and so on for subsequent arguments
|
8
|
+
(cond (no args) nil
|
9
|
+
(cond (cdr args)
|
10
|
+
(cond (cddr args)
|
11
|
+
`(cond ,(car args) ,(cadr args) (if ,@(cddr args)))
|
12
|
+
`(cond ,(car args) ,(cadr args)))
|
13
|
+
(car args))))
|
14
|
+
|
15
|
+
(def map (f things)
|
16
|
+
; transforms the list 'things by applying 'f to each item
|
17
|
+
; returns the resulting list
|
18
|
+
(if (no things)
|
19
|
+
nil
|
20
|
+
(pair? things)
|
21
|
+
(cons (f (car things)) (map f (cdr things)))
|
22
|
+
(map f (list things))))
|
@@ -27,9 +27,6 @@
|
|
27
27
|
(car args))
|
28
28
|
't))
|
29
29
|
|
30
|
-
(mac do args
|
31
|
-
`((fn nil ,@args)))
|
32
|
-
|
33
30
|
(mac when (condition . body)
|
34
31
|
`(cond ,condition (do ,@body)))
|
35
32
|
|
@@ -84,9 +81,8 @@
|
|
84
81
|
name)
|
85
82
|
(list 'quote name)))
|
86
83
|
|
87
|
-
;; (build-hash-getters '(a b c))
|
88
|
-
;; => (hash-get (hash-get a 'b) 'c)
|
89
84
|
(def build-hash-getters (names acc)
|
85
|
+
;; (build-hash-getters '(a b c)) => (hash-get (hash-get a 'b) 'c)
|
90
86
|
(if (no acc)
|
91
87
|
(build-hash-getters (cdr names) (car names))
|
92
88
|
names
|
@@ -4,18 +4,11 @@
|
|
4
4
|
(f (car things))))
|
5
5
|
|
6
6
|
(def zip (a b)
|
7
|
+
; takes two lists, (p q r) and (1 2 3), returns ((p 1) (q 2) (r 3))
|
7
8
|
(if a
|
8
9
|
(cons (list (car a) (car b))
|
9
10
|
(zip (cdr a) (cdr b)))))
|
10
11
|
|
11
|
-
(def reversify (things acc)
|
12
|
-
(if (no things)
|
13
|
-
acc
|
14
|
-
(reversify (cdr things)
|
15
|
-
(cons (car things) acc))))
|
16
|
-
|
17
|
-
(def rev (things) (reversify things nil))
|
18
|
-
|
19
12
|
(mac push (x things)
|
20
13
|
`(assign ,things (cons ,x ,things)))
|
21
14
|
|
@@ -29,6 +22,13 @@
|
|
29
22
|
(flattenize things))
|
30
23
|
acc))
|
31
24
|
|
25
|
+
(def string-strip (txt)
|
26
|
+
(string-replace "\\s+$"
|
27
|
+
""
|
28
|
+
(string-replace "^\\s+"
|
29
|
+
""
|
30
|
+
txt)))
|
31
|
+
|
32
32
|
(def joinstr (txt . things)
|
33
33
|
(let joinables (flatten things)
|
34
34
|
(apply +
|
@@ -60,6 +60,7 @@
|
|
60
60
|
(iso (car x) (car y))
|
61
61
|
(iso (cdr x) (cdr y)))))
|
62
62
|
|
63
|
+
(def x1 (thing) thing)
|
63
64
|
(def isa (type obj) (eq? (type-of obj) type))
|
64
65
|
(def sym? (arg) (isa 'symbol arg))
|
65
66
|
(def string? (arg) (isa 'string arg))
|
@@ -141,3 +142,51 @@
|
|
141
142
|
(cdr list))
|
142
143
|
acc))
|
143
144
|
(car things) (cdr things)))
|
145
|
+
|
146
|
+
(def dox-show-src (src)
|
147
|
+
; show 'src as source code.
|
148
|
+
; expect to override this later when pretty-printing is available
|
149
|
+
(inspect src))
|
150
|
+
|
151
|
+
(def dox-show-info (name what texts args src)
|
152
|
+
; show the given dox info
|
153
|
+
; 'info arg is a dox object from the dox system
|
154
|
+
(p)
|
155
|
+
(cond (eq? what 'mac) (p "Macro : ~name" ))
|
156
|
+
(cond (eq? what 'def) (p "Function : ~name" ))
|
157
|
+
(p "args : ~(inspect args)")
|
158
|
+
(p (joinstr "\n" texts))
|
159
|
+
(p "")
|
160
|
+
(p "source")
|
161
|
+
(p "======")
|
162
|
+
(p (dox-show-src src))
|
163
|
+
(p))
|
164
|
+
|
165
|
+
(mac dox (name)
|
166
|
+
; show dox for the given name
|
167
|
+
`(let infos (dox-lookup ',name)
|
168
|
+
(if (or (no infos)
|
169
|
+
(eq? (len infos) 0))
|
170
|
+
(p "No documentation for " ',name)
|
171
|
+
(each info infos
|
172
|
+
(apply dox-show-info info)))))
|
173
|
+
|
174
|
+
(def proper? (list)
|
175
|
+
; t if this is a proper list (last cdr is nil)
|
176
|
+
; nil otherwise (last cdr is neither cons nor nil)
|
177
|
+
(or (no list)
|
178
|
+
(and (pair? list)
|
179
|
+
(proper? (cdr list)))))
|
180
|
+
|
181
|
+
(def firstn (n things)
|
182
|
+
; returns the first 'n items in the list 'things
|
183
|
+
(if (eq? n 0) nil
|
184
|
+
(cons (car things)
|
185
|
+
(firstn (- n 1)
|
186
|
+
(cdr things)))))
|
187
|
+
|
188
|
+
(def nthcdr (n things)
|
189
|
+
; returns the nth cdr of the list 'things
|
190
|
+
(if (> n 0)
|
191
|
+
(nthcdr (- n 1) (cdr things))
|
192
|
+
things))
|
File without changes
|
File without changes
|
@@ -0,0 +1,33 @@
|
|
1
|
+
|
2
|
+
(assign prefix-list-prefixes ())
|
3
|
+
|
4
|
+
(def prefix-match-fn (txt)
|
5
|
+
(fn (rule) (string-match txt (car rule))))
|
6
|
+
|
7
|
+
(def find-prefix-rule (prefix)
|
8
|
+
(cdr:detect (prefix-match-fn prefix)
|
9
|
+
prefix-list-prefixes))
|
10
|
+
|
11
|
+
(mac prefix-list (prefix list)
|
12
|
+
; looks up a handler in 'prefix-list-prefixes
|
13
|
+
; whose 'car matches the prefix, and whose 'cdr
|
14
|
+
; is a function, which behaves like a macro, in that
|
15
|
+
; it processes the prefix name and the prefixed list,
|
16
|
+
; returning more code
|
17
|
+
(let handler (find-prefix-rule prefix)
|
18
|
+
(and handler (handler prefix list))))
|
19
|
+
|
20
|
+
(mac define-prefix-list-macro (regex prefix-var list-var . body)
|
21
|
+
; define a macro to process a prefix-list where the prefix matches the given regex
|
22
|
+
; param: 'regex is the regex which should match the list prefix
|
23
|
+
; param: 'prefix-var is the variable whose value will be the actual matched prefix
|
24
|
+
; param: 'list-var is the variable whose value will be the corresponding list
|
25
|
+
; param: 'body the code which will actually transform the list
|
26
|
+
`(push (cons ,regex (fn (,prefix-var ,list-var) ,@body))
|
27
|
+
prefix-list-prefixes))
|
28
|
+
|
29
|
+
(define-prefix-list-macro "^λ.+" vars expr
|
30
|
+
;; allows (map λa(upcase a.name) people)
|
31
|
+
;; as shortcut for (map (fn (a) (upcase a.name)) people)
|
32
|
+
(let var-list (map sym (cdr:string-split vars))
|
33
|
+
`(fn ,var-list ,expr)))
|
@@ -0,0 +1,101 @@
|
|
1
|
+
(assign pp/special-forms (hash))
|
2
|
+
(assign pp/line-break (uniq 'line-break))
|
3
|
+
|
4
|
+
(def pp/escape-char (char)
|
5
|
+
(if (eq? char "\"") "\\\""
|
6
|
+
(eq? char "\~") "\\\~"
|
7
|
+
(eq? char "\\") "\\\\"
|
8
|
+
(eq? char "\n") "\\n"
|
9
|
+
char))
|
10
|
+
|
11
|
+
(def pp/escape-string-literal (txt)
|
12
|
+
(joinstr "" (map pp/escape-char (string-split txt))))
|
13
|
+
|
14
|
+
(def pp/string-piece (thing)
|
15
|
+
(if (isa 'string thing) (pp/escape-string-literal thing)
|
16
|
+
"\~~(pp thing)"))
|
17
|
+
|
18
|
+
(def pp/string-pieces (things) "\"~(joinstr "" (map pp/string-piece things))\"")
|
19
|
+
|
20
|
+
(def pp/literal (thing)
|
21
|
+
(if (eq? thing '||)
|
22
|
+
""
|
23
|
+
(isa 'string thing)
|
24
|
+
(pp/escape-string-literal thing)
|
25
|
+
(inspect thing)))
|
26
|
+
|
27
|
+
(mac pp/def (name args . body)
|
28
|
+
`(do
|
29
|
+
(hash-set pp/special-forms ',name
|
30
|
+
(fn ,args ,@body))
|
31
|
+
(dox-add-doc ',name
|
32
|
+
'pp/def
|
33
|
+
'("pretty-printer for forms starting with ~(quote ,name)")
|
34
|
+
',args
|
35
|
+
'(pp/def ,name ,args ,@body))))
|
36
|
+
|
37
|
+
(mac pp/syntax syntaxes
|
38
|
+
(if syntaxes
|
39
|
+
`(do (pp/def ,(car syntaxes) (form indent)
|
40
|
+
(joinstr ,(cadr syntaxes) (map pp (cdr form))))
|
41
|
+
(pp/syntax ,@(cddr syntaxes)))))
|
42
|
+
|
43
|
+
(pp/def string-pieces (form indent) (pp/string-pieces (cdr form)))
|
44
|
+
(pp/def quasiquote (form indent) "`~(pp/main (cadr form) indent)" )
|
45
|
+
(pp/def quote (form indent) "'~(pp/main (cadr form) indent)" )
|
46
|
+
(pp/def unquote (form indent) ",~(pp/main (cadr form) indent)" )
|
47
|
+
(pp/def unquote-splicing (form indent) ",@~(pp/main (cadr form) indent)")
|
48
|
+
(pp/def comment (form indent) ";~(cadr form)\n")
|
49
|
+
(pp/def prefix-list (form indent) "~(cadr form)~(pp (caddr form))")
|
50
|
+
|
51
|
+
(pp/syntax
|
52
|
+
colon-syntax ":"
|
53
|
+
dot-syntax "."
|
54
|
+
bang-syntax "!"
|
55
|
+
ampersand-syntax "&"
|
56
|
+
dollar-syntax "$"
|
57
|
+
colon-colon-syntax "::"
|
58
|
+
arrow-syntax "->"
|
59
|
+
rocket-syntax "=>" )
|
60
|
+
|
61
|
+
(def pp/spaces (n) (if (> n 0) " ~(pp/spaces (- n 1))" ""))
|
62
|
+
|
63
|
+
(def pp/dotify (form)
|
64
|
+
(if (pair? (cdr form))
|
65
|
+
(cons (car form) (pp/dotify (cdr form)))
|
66
|
+
(no:cdr form)
|
67
|
+
form
|
68
|
+
(list (car form) '. (cdr form))))
|
69
|
+
|
70
|
+
(def pp/find-breaks/mac (form)
|
71
|
+
(if (eq? (dox-what-is? (car form)) 'mac)
|
72
|
+
(let arg-count (+ 1 (len (dox-arg-names (car form))))
|
73
|
+
(cons (firstn arg-count form)
|
74
|
+
(map list (nthcdr arg-count form))))))
|
75
|
+
|
76
|
+
(def pp/find-breaks (form)
|
77
|
+
(if (eq? 'if (car form))
|
78
|
+
(let if-args (cdr form)
|
79
|
+
(cons (list 'if (car if-args)) (map list (cdr if-args))))
|
80
|
+
(or (pp/find-breaks/mac form)
|
81
|
+
(list form))))
|
82
|
+
|
83
|
+
(def pp/inline (forms indent)
|
84
|
+
(joinstr " " (map λf(pp/main f (+ indent 1)) forms)))
|
85
|
+
|
86
|
+
(def pp/pair (form indent)
|
87
|
+
(let special-form (hash-get pp/special-forms (car form))
|
88
|
+
(if special-form
|
89
|
+
(special-form form indent)
|
90
|
+
(let form-with-breaks (pp/find-breaks form)
|
91
|
+
"(~(joinstr "\n~(pp/spaces (+ 4 indent))" (map λf(pp/inline f (+ indent 1)) (pp/dotify form-with-breaks))))"))))
|
92
|
+
|
93
|
+
(def pp/main (form indent)
|
94
|
+
(if (pair? form) (pp/pair form indent)
|
95
|
+
(pp/literal form)))
|
96
|
+
|
97
|
+
(def pp (form) (pp/main form 0))
|
98
|
+
|
99
|
+
(def dox-show-src (src)
|
100
|
+
; use the pretty-printer to elegantly display the given source code
|
101
|
+
(pp src))
|
@@ -66,6 +66,14 @@
|
|
66
66
|
(let zi 10 "finds the ~{zi}th item")
|
67
67
|
"finds the 10th item")
|
68
68
|
|
69
|
+
("detects key presence"
|
70
|
+
(hash-key? { foo 1 bar 2 } 'foo)
|
71
|
+
t)
|
72
|
+
|
73
|
+
("detects key absence"
|
74
|
+
(hash-key? { foo 1 bar 2 } 'zed)
|
75
|
+
nil)
|
76
|
+
|
69
77
|
("unquotes hash keys"
|
70
78
|
(with (zi 'foo chi 'bar yi 'grr)
|
71
79
|
(let hsh { ,zi 10 ,chi 11 ,yi 12 }
|
@@ -78,11 +86,6 @@
|
|
78
86
|
(list "hello world" (hash-get hsh "hello world") "yesterday" (hash-get hsh "yesterday"))))
|
79
87
|
("hello world" 10 "yesterday" 11)))
|
80
88
|
|
81
|
-
(suite "strings"
|
82
|
-
("length"
|
83
|
-
(len "foo-bar")
|
84
|
-
7))
|
85
|
-
|
86
89
|
(suite "list management"
|
87
90
|
("'pair breaks a list into pairs"
|
88
91
|
(pairs '(1 a 2 b 3 c))
|
@@ -100,26 +103,6 @@
|
|
100
103
|
(rev '(a b (c d e) f g))
|
101
104
|
(g f (c d e) b a))
|
102
105
|
|
103
|
-
("joins elements into a string"
|
104
|
-
(joinstr "" '("foo" "bar" "bax"))
|
105
|
-
"foobarbax")
|
106
|
-
|
107
|
-
("joins separate elements into a string"
|
108
|
-
(joinstr "/" "foo" "bar" "bax")
|
109
|
-
"foo/bar/bax")
|
110
|
-
|
111
|
-
("joins a single thing"
|
112
|
-
(joinstr "/" "foo")
|
113
|
-
"foo")
|
114
|
-
|
115
|
-
("joins nested and separate elements into a string"
|
116
|
-
(joinstr "/" "foo" "bar" '(twiddle diddle) "bax")
|
117
|
-
"foo/bar/twiddle/diddle/bax")
|
118
|
-
|
119
|
-
("joins elements into a string"
|
120
|
-
(joinstr " - " '(1 2 3))
|
121
|
-
"1 - 2 - 3")
|
122
|
-
|
123
106
|
("'flatten returns a flat list of things"
|
124
107
|
(flatten '((poo (x) (* x x)) (1 2 3)))
|
125
108
|
(poo x * x x 1 2 3)))
|
@@ -0,0 +1,103 @@
|
|
1
|
+
(mac this-is-a-well-documented-macro (a b c)
|
2
|
+
; documentation for me!
|
3
|
+
`(foo ,a ,b ,c))
|
4
|
+
|
5
|
+
(mac this-is-an-undocumented-macro (a b c)
|
6
|
+
`(baz ,a ,b ,c))
|
7
|
+
|
8
|
+
(def this-is-a-well-documented-def (a b c)
|
9
|
+
; documentation for me!
|
10
|
+
(foo a b c))
|
11
|
+
|
12
|
+
(def this-is-an-undocumented-def (a b c)
|
13
|
+
(baz a b c))
|
14
|
+
|
15
|
+
(register-test
|
16
|
+
'(suite "Documentation Tests"
|
17
|
+
(suite "comment detection"
|
18
|
+
("identify comment"
|
19
|
+
(isa-comment? '(comment "yes, it is"))
|
20
|
+
t)
|
21
|
+
|
22
|
+
("identify non-comment"
|
23
|
+
(isa-comment? "not this time")
|
24
|
+
nil))
|
25
|
+
|
26
|
+
(suite "gather comments from 'body argument"
|
27
|
+
("no comment"
|
28
|
+
(dox-gather-comments '((this) (that)))
|
29
|
+
(nil ((this) (that))))
|
30
|
+
|
31
|
+
("one comment"
|
32
|
+
(dox-gather-comments '((comment "hello") (this) (that)))
|
33
|
+
(("hello") ((this) (that))))
|
34
|
+
|
35
|
+
("more comments"
|
36
|
+
(dox-gather-comments '((comment "hello")
|
37
|
+
(comment "more details")
|
38
|
+
(comment "very rigourous")
|
39
|
+
(this)
|
40
|
+
(that)))
|
41
|
+
(("hello" "more details" "very rigourous") ((this) (that)))))
|
42
|
+
|
43
|
+
(suite "mac"
|
44
|
+
("a documented macro"
|
45
|
+
(dox-lookup 'this-is-a-well-documented-macro)
|
46
|
+
((this-is-a-well-documented-macro
|
47
|
+
mac
|
48
|
+
("documentation for me!")
|
49
|
+
(a b c)
|
50
|
+
(mac this-is-a-well-documented-macro (a b c)
|
51
|
+
`(foo ,a ,b ,c)))))
|
52
|
+
|
53
|
+
("arg list"
|
54
|
+
(dox-arg-names 'this-is-a-well-documented-macro)
|
55
|
+
(a b c))
|
56
|
+
|
57
|
+
("src"
|
58
|
+
(dox-src 'this-is-a-well-documented-macro)
|
59
|
+
(mac this-is-a-well-documented-macro (a b c) (quasiquote (foo (unquote a) (unquote b) (unquote c)))))
|
60
|
+
|
61
|
+
("is a def"
|
62
|
+
(dox-what-is? 'this-is-a-well-documented-macro)
|
63
|
+
mac)
|
64
|
+
|
65
|
+
("an undocumented macro"
|
66
|
+
(dox-lookup 'this-is-an-undocumented-macro)
|
67
|
+
((this-is-an-undocumented-macro
|
68
|
+
mac
|
69
|
+
nil
|
70
|
+
(a b c)
|
71
|
+
(mac this-is-an-undocumented-macro (a b c)
|
72
|
+
`(baz ,a ,b ,c)))))
|
73
|
+
|
74
|
+
(suite "def"
|
75
|
+
("a documented def"
|
76
|
+
(dox-lookup 'this-is-a-well-documented-def)
|
77
|
+
((this-is-a-well-documented-def
|
78
|
+
def
|
79
|
+
("documentation for me!")
|
80
|
+
(a b c)
|
81
|
+
(def this-is-a-well-documented-def (a b c)
|
82
|
+
(foo a b c)))))
|
83
|
+
|
84
|
+
("arg list"
|
85
|
+
(dox-arg-names 'this-is-a-well-documented-def)
|
86
|
+
(a b c))
|
87
|
+
|
88
|
+
("is a def"
|
89
|
+
(dox-what-is? 'this-is-a-well-documented-def)
|
90
|
+
def)
|
91
|
+
|
92
|
+
("src"
|
93
|
+
(dox-src 'this-is-a-well-documented-def)
|
94
|
+
(def this-is-a-well-documented-def (a b c) (foo a b c)))
|
95
|
+
|
96
|
+
("an undocumented def"
|
97
|
+
(dox-lookup 'this-is-an-undocumented-def)
|
98
|
+
((this-is-an-undocumented-def
|
99
|
+
def
|
100
|
+
nil
|
101
|
+
(a b c)
|
102
|
+
(def this-is-an-undocumented-def (a b c)
|
103
|
+
(baz a b c)))))))))
|
@@ -0,0 +1,66 @@
|
|
1
|
+
(register-test
|
2
|
+
'(suite "List Tests"
|
3
|
+
(suite "firstn"
|
4
|
+
("returns no items for n = 0"
|
5
|
+
(firstn 0 '(a b c d))
|
6
|
+
nil)
|
7
|
+
|
8
|
+
("returns first n items for n > 0 and n < size of list"
|
9
|
+
(firstn 3 '(a b c d e))
|
10
|
+
(a b c))
|
11
|
+
|
12
|
+
("returns all items for n > size of list"
|
13
|
+
(firstn 33 '(a b c d e))
|
14
|
+
(a b c d e)))
|
15
|
+
|
16
|
+
(suite "nthcdr"
|
17
|
+
("returns all items for n = 0"
|
18
|
+
(nthcdr 0 '(a b c d))
|
19
|
+
(a b c d))
|
20
|
+
|
21
|
+
("returns nth cdr of list for n > 0 and n < size of list"
|
22
|
+
(nthcdr 3 '(a b c d e))
|
23
|
+
(d e))
|
24
|
+
|
25
|
+
("returns nothing for n > size of list"
|
26
|
+
(nthcdr 33 '(a b c d e))
|
27
|
+
nil))
|
28
|
+
|
29
|
+
(suite "car/cdr combinations"
|
30
|
+
("caar of list" (caar '((x y) (1 2))) x )
|
31
|
+
("caar of nil" (caar nil) nil )
|
32
|
+
("cadr of list" (cadr '((x y) (1 2))) (1 2) )
|
33
|
+
("cadr of nil" (cadr nil) nil )
|
34
|
+
("cdar of list" (cdar '((x y) (1 2))) (y) )
|
35
|
+
("cdar of nil" (cdar nil) nil )
|
36
|
+
("cddr of list" (cddr '(x y 1 2)) (1 2) )
|
37
|
+
("cddr of nil" (cddr nil) nil )
|
38
|
+
("cadar of list" (cadar '((x y) (1 2))) y )
|
39
|
+
("cadar of nil" (cadar nil) nil )
|
40
|
+
("caddr of list" (caddr '(x y 1 2)) 1 )
|
41
|
+
("caddr of nil" (caddr nil) nil )
|
42
|
+
("cdddr of list" (cdddr '(x y 1 2)) (2) )
|
43
|
+
("cdddr of nil" (cdddr nil) nil )
|
44
|
+
("cadddr of list" (cadddr '(x y 1 2 3)) 2 )
|
45
|
+
("cadddr of nil" (cadddr nil) nil ))
|
46
|
+
|
47
|
+
(suite "proper?"
|
48
|
+
("t for a proper list"
|
49
|
+
(proper? '(a b c d))
|
50
|
+
t)
|
51
|
+
|
52
|
+
("t for a proper list, even if we write it funny"
|
53
|
+
(proper? '(a b . (c d)))
|
54
|
+
t)
|
55
|
+
|
56
|
+
("t for a proper list, even if we write it funny with nil"
|
57
|
+
(proper? '(a b . nil))
|
58
|
+
t)
|
59
|
+
|
60
|
+
("nil for an improper list"
|
61
|
+
(proper? '(a b . c))
|
62
|
+
nil)
|
63
|
+
|
64
|
+
("nil for a very improper list"
|
65
|
+
(proper? '(a b . (c . d)))
|
66
|
+
nil))))
|
@@ -0,0 +1,25 @@
|
|
1
|
+
(register-test
|
2
|
+
'(suite "Pretty Printing Tests"
|
3
|
+
("a macro invocation"
|
4
|
+
(pp '(mac pp/def (name args . body) `(hash-set pp/special-forms ',name (fn ,args ,@body))))
|
5
|
+
"(mac pp/def (name args body)\n `(hash-set pp/special-forms ',name (fn ,args ,@body)))")
|
6
|
+
|
7
|
+
("a 'def invocation"
|
8
|
+
(pp '(def pp (form) (pp/main form 0)))
|
9
|
+
"(def pp (form)\n (pp/main form 0))")
|
10
|
+
|
11
|
+
("combined with dox system"
|
12
|
+
(pp:dox-src 'pp/find-breaks)
|
13
|
+
"(def pp/find-breaks (form)
|
14
|
+
(if (eq? 'if (car form))
|
15
|
+
(let if-args (cdr form)
|
16
|
+
(cons (list 'if (car if-args)) (map list (cdr if-args))))
|
17
|
+
(or
|
18
|
+
(pp/find-breaks/mac form)
|
19
|
+
(list form))))")
|
20
|
+
|
21
|
+
("special syntax"
|
22
|
+
(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!"))
|
23
|
+
"\"hello ~~!x.y.foo&bar and welcome to ~~%%(a b c d) and friends!\"")
|
24
|
+
|
25
|
+
))
|
@@ -0,0 +1,31 @@
|
|
1
|
+
(register-test
|
2
|
+
'(suite "String Tests"
|
3
|
+
(suite "length"
|
4
|
+
("nonzero" (len "foo-bar") 7)
|
5
|
+
("zero" (len "") 0))
|
6
|
+
|
7
|
+
(suite "joinstr"
|
8
|
+
("joins elements into a string"
|
9
|
+
(joinstr "" '("foo" "bar" "bax"))
|
10
|
+
"foobarbax")
|
11
|
+
|
12
|
+
("joins separate elements into a string"
|
13
|
+
(joinstr "/" "foo" "bar" "bax")
|
14
|
+
"foo/bar/bax")
|
15
|
+
|
16
|
+
("joins a single thing"
|
17
|
+
(joinstr "/" "foo")
|
18
|
+
"foo")
|
19
|
+
|
20
|
+
("joins nested and separate elements into a string"
|
21
|
+
(joinstr "/" "foo" "bar" '(twiddle diddle) "bax")
|
22
|
+
"foo/bar/twiddle/diddle/bax")
|
23
|
+
|
24
|
+
("joins elements into a string"
|
25
|
+
(joinstr " - " '(1 2 3))
|
26
|
+
"1 - 2 - 3"))
|
27
|
+
|
28
|
+
(suite "strip"
|
29
|
+
("removes leading whitespace" (string-strip " hello!") "hello!" )
|
30
|
+
("removes trailing whitespace" (string-strip "(world) ") "(world)" )
|
31
|
+
("removes leading and trailing whitespace" (string-strip "\n\nme\n\n") "me" ))))
|
@@ -0,0 +1,7 @@
|
|
1
|
+
(register-test '(suite "pair to-string"
|
2
|
+
("unquote" (to-string '(unquote a)) ",a" )
|
3
|
+
("quote" (to-string '(quote a)) "'a" )
|
4
|
+
("quasiquote" (to-string '(quasiquote a)) "`a" )
|
5
|
+
("unquote-splicing" (to-string '(unquote-splicing a)) ",@a" )
|
6
|
+
("brace-list" (to-string '(brace-list a b c d)) "{ a b c d }" )
|
7
|
+
))
|
data/lib/nydp/builtin/hash.rb
CHANGED
@@ -74,6 +74,24 @@ class Nydp::Builtin::HashKeys
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
+
class Nydp::Builtin::HashKeyPresent
|
78
|
+
include Nydp::Helper, Nydp::Builtin::Base
|
79
|
+
attr_accessor :ns
|
80
|
+
def initialize ns ; @ns = ns; end
|
81
|
+
def builtin_invoke vm, args
|
82
|
+
hash = args.car
|
83
|
+
key = args.cdr.car
|
84
|
+
truth = case hash
|
85
|
+
when Nydp::Hash
|
86
|
+
hash.key? key
|
87
|
+
else
|
88
|
+
hash.key? n2r key
|
89
|
+
end
|
90
|
+
vm.push_arg(truth ? Nydp.T : Nydp.NIL)
|
91
|
+
end
|
92
|
+
def name ; "hash-key?" ; end
|
93
|
+
end
|
94
|
+
|
77
95
|
class Nydp::Builtin::HashMerge
|
78
96
|
include Nydp::Helper, Nydp::Builtin::Base
|
79
97
|
|
data/lib/nydp/builtin/puts.rb
CHANGED
@@ -2,8 +2,12 @@ class Nydp::Builtin::Puts
|
|
2
2
|
include Nydp::Builtin::Base
|
3
3
|
|
4
4
|
def builtin_invoke vm, args
|
5
|
-
|
6
|
-
|
5
|
+
if Nydp.NIL.is? args
|
6
|
+
puts
|
7
|
+
else
|
8
|
+
s = args.map { |a| a.to_s }
|
9
|
+
puts s.join ' '
|
10
|
+
end
|
7
11
|
vm.push_arg args.car
|
8
12
|
end
|
9
13
|
|
data/lib/nydp/core.rb
CHANGED
@@ -63,6 +63,7 @@ module Nydp
|
|
63
63
|
Symbol.mk(:"hash-get", ns).assign(Nydp::Builtin::HashGet.new ns)
|
64
64
|
Symbol.mk(:"hash-set", ns).assign(Nydp::Builtin::HashSet.new)
|
65
65
|
Symbol.mk(:"hash-keys", ns).assign(Nydp::Builtin::HashKeys.new(ns))
|
66
|
+
Symbol.mk(:"hash-key?", ns).assign(Nydp::Builtin::HashKeyPresent.new(ns))
|
66
67
|
Symbol.mk(:"hash-merge", ns).assign(Nydp::Builtin::HashMerge.new)
|
67
68
|
Symbol.mk(:"vm-info", ns).assign Nydp::Builtin::VmInfo.new
|
68
69
|
Symbol.mk(:"pre-compile", ns).assign Nydp::Builtin::PreCompile.new
|
data/lib/nydp/hash.rb
CHANGED
@@ -3,15 +3,8 @@ class Nydp::Hash < ::Hash
|
|
3
3
|
|
4
4
|
def nydp_type ; :hash ; end
|
5
5
|
def to_ruby
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
Nydp::StringAtom.new(k)
|
10
|
-
when Symbol
|
11
|
-
Nydp::Symbol.new(k)
|
12
|
-
else
|
13
|
-
k
|
14
|
-
end]
|
15
|
-
}
|
6
|
+
h = Hash.new
|
7
|
+
self.each { |k,v| h[n2r k] = n2r v }
|
8
|
+
h
|
16
9
|
end
|
17
10
|
end
|
data/lib/nydp/pair.rb
CHANGED
@@ -75,6 +75,12 @@ class Nydp::Pair
|
|
75
75
|
else
|
76
76
|
"'#{cdr.to_s}"
|
77
77
|
end
|
78
|
+
elsif car.is_a?(Nydp::Symbol) && car.is?(:"brace-list")
|
79
|
+
if Nydp.NIL.is? cdr.cdr
|
80
|
+
"{}"
|
81
|
+
else
|
82
|
+
"{ #{cdr.to_s_rest} }"
|
83
|
+
end
|
78
84
|
elsif car.is_a?(Nydp::Symbol) && car.is?(:quasiquote)
|
79
85
|
if Nydp.NIL.is? cdr.cdr
|
80
86
|
"`#{cdr.car.to_s}"
|
data/lib/nydp/parser.rb
CHANGED
data/lib/nydp/version.rb
CHANGED
data/spec/hash_spec.rb
CHANGED
@@ -24,6 +24,7 @@ describe Nydp::Hash do
|
|
24
24
|
|
25
25
|
rhash = hash.to_ruby
|
26
26
|
expect(rhash[:boo]).to eq 42
|
27
|
+
expect(rhash.keys) .to eq [:boo]
|
27
28
|
end
|
28
29
|
|
29
30
|
it "converts ruby string key to nydp string key" do
|
@@ -32,6 +33,7 @@ describe Nydp::Hash do
|
|
32
33
|
|
33
34
|
rhash = hash.to_ruby
|
34
35
|
expect(rhash["boo"]).to eq 42
|
36
|
+
expect(rhash.keys) .to eq ["boo"]
|
35
37
|
end
|
36
38
|
|
37
39
|
it "uses integer keys unconverted" do
|
@@ -40,6 +42,7 @@ describe Nydp::Hash do
|
|
40
42
|
|
41
43
|
rhash = hash.to_ruby
|
42
44
|
expect(rhash[21]).to eq 42
|
45
|
+
expect(rhash.keys) .to eq [21]
|
43
46
|
end
|
44
47
|
end
|
45
48
|
|
@@ -92,6 +95,28 @@ describe Nydp::Hash do
|
|
92
95
|
end
|
93
96
|
end
|
94
97
|
|
98
|
+
describe "key?" do
|
99
|
+
it "returns t when key is present" do
|
100
|
+
h = Nydp::Hash.new
|
101
|
+
k = sym "jerry"
|
102
|
+
v = 42
|
103
|
+
h[k] = v
|
104
|
+
|
105
|
+
Nydp::Builtin::HashKeyPresent.new(ns).invoke vm, pair_list([h, k])
|
106
|
+
|
107
|
+
expect(vm.pop_arg).to eq Nydp.T
|
108
|
+
end
|
109
|
+
|
110
|
+
it "returns nil when key is absent" do
|
111
|
+
h = Nydp::Hash.new
|
112
|
+
k = sym "benjamin"
|
113
|
+
|
114
|
+
Nydp::Builtin::HashKeyPresent.new(ns).invoke vm, pair_list([h, k])
|
115
|
+
|
116
|
+
expect(vm.pop_arg).to eq Nydp.NIL
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
95
120
|
describe "hash keys" do
|
96
121
|
it "returns a list of keys" do
|
97
122
|
h = Nydp::Hash.new
|
@@ -154,6 +179,27 @@ describe Nydp::Hash do
|
|
154
179
|
end
|
155
180
|
end
|
156
181
|
|
182
|
+
describe "key?" do
|
183
|
+
it "returns t when key is present" do
|
184
|
+
ahash[:simon] = 24
|
185
|
+
k = sym("simon")
|
186
|
+
args = [ ahash, k ]
|
187
|
+
|
188
|
+
Nydp::Builtin::HashKeyPresent.new(ns).invoke vm, pair_list(args)
|
189
|
+
|
190
|
+
expect(vm.pop_arg).to eq Nydp.T
|
191
|
+
end
|
192
|
+
|
193
|
+
it "returns nil when key is absent" do
|
194
|
+
k = sym("simon")
|
195
|
+
args = [ ahash, k ]
|
196
|
+
|
197
|
+
Nydp::Builtin::HashKeyPresent.new(ns).invoke vm, pair_list(args)
|
198
|
+
|
199
|
+
expect(vm.pop_arg).to eq Nydp.NIL
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
157
203
|
describe "hash keys" do
|
158
204
|
it "returns a list of keys" do
|
159
205
|
ahash[:k0] = 42
|
data/spec/pair_spec.rb
CHANGED
@@ -8,6 +8,14 @@ describe Nydp::Pair do
|
|
8
8
|
let(:foo) { Nydp::Symbol.mk :foo, ns }
|
9
9
|
let(:dot) { Nydp::Symbol.mk ".".to_sym, ns }
|
10
10
|
|
11
|
+
describe "#map" do
|
12
|
+
it "behaves like ruby #map" do
|
13
|
+
list = pair_list [1,2,3]
|
14
|
+
mapped = list.map { |x| x * 2 }
|
15
|
+
expect(mapped).to eq [2,4,6]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
11
19
|
describe :== do
|
12
20
|
it "should be true for two empty lists" do
|
13
21
|
expect(Nydp::Pair.new(NIL, NIL)).to eq Nydp::Pair.new(NIL, NIL)
|
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.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Conan Dalton
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-10-
|
11
|
+
date: 2015-10-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -84,23 +84,30 @@ files:
|
|
84
84
|
- Rakefile
|
85
85
|
- bin/nydp
|
86
86
|
- bin/nydp-tests
|
87
|
-
- lib/lisp/core-
|
88
|
-
- lib/lisp/core-
|
89
|
-
- lib/lisp/core-
|
90
|
-
- lib/lisp/core-
|
91
|
-
- lib/lisp/core-
|
92
|
-
- lib/lisp/core-
|
93
|
-
- lib/lisp/core-
|
94
|
-
- lib/lisp/core-
|
87
|
+
- lib/lisp/core-000.nydp
|
88
|
+
- lib/lisp/core-010-precompile.nydp
|
89
|
+
- lib/lisp/core-015-documentation.nydp
|
90
|
+
- lib/lisp/core-020-utils.nydp
|
91
|
+
- lib/lisp/core-030-syntax.nydp
|
92
|
+
- lib/lisp/core-040-utils.nydp
|
93
|
+
- lib/lisp/core-050-test-runner.nydp
|
94
|
+
- lib/lisp/core-060-benchmarking.nydp
|
95
|
+
- lib/lisp/core-070-prefix-list.nydp
|
96
|
+
- lib/lisp/core-080-pretty-print.nydp
|
95
97
|
- lib/lisp/tests/boot-tests.nydp
|
96
98
|
- lib/lisp/tests/builtin-tests.nydp
|
99
|
+
- lib/lisp/tests/dox-tests.nydp
|
97
100
|
- lib/lisp/tests/dynamic-scope-test.nydp
|
98
101
|
- lib/lisp/tests/each-tests.nydp
|
99
102
|
- lib/lisp/tests/error-tests.nydp
|
100
103
|
- lib/lisp/tests/foundation-test.nydp
|
101
104
|
- lib/lisp/tests/invocation-tests.nydp
|
105
|
+
- lib/lisp/tests/list-tests.nydp
|
102
106
|
- lib/lisp/tests/parser-tests.nydp
|
107
|
+
- lib/lisp/tests/pretty-print-tests.nydp
|
108
|
+
- lib/lisp/tests/string-tests.nydp
|
103
109
|
- lib/lisp/tests/syntax-tests.nydp
|
110
|
+
- lib/lisp/tests/unparse-tests.nydp
|
104
111
|
- lib/nydp.rb
|
105
112
|
- lib/nydp/assignment.rb
|
106
113
|
- lib/nydp/builtin.rb
|
data/lib/lisp/core-00.nydp
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
; -*- lisp -*-
|
2
|
-
;;
|
3
|
-
;; Acknowledgements to Paul Graham. Some nydp features (including,
|
4
|
-
;; but not limited to, 'do, 'rfn, 'loop, 'for) are stolen directly from arc.arc
|
5
|
-
;;
|
6
|
-
|
7
|
-
(assign list (fn args args))
|
8
|
-
(assign caar (fn (arg) (car (car arg))))
|
9
|
-
(assign cadr (fn (arg) (car (cdr arg))))
|
10
|
-
(assign cdar (fn (arg) (cdr (car arg))))
|
11
|
-
(assign cddr (fn (arg) (cdr (cdr arg))))
|
12
|
-
(assign no (fn (arg) (cond arg nil t)))
|
13
|
-
(assign just (fn (arg) arg))
|
data/lib/lisp/core-02-utils.nydp
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
|
2
|
-
(assign prefix-list-prefixes ())
|
3
|
-
|
4
|
-
(def prefix-match-fn (txt)
|
5
|
-
(fn (rule) (string-match txt (car rule))))
|
6
|
-
|
7
|
-
(def find-prefix-rule (prefix)
|
8
|
-
(cdr:detect (prefix-match-fn prefix)
|
9
|
-
prefix-list-prefixes))
|
10
|
-
|
11
|
-
(mac prefix-list (prefix list)
|
12
|
-
(let handler (find-prefix-rule prefix)
|
13
|
-
(and handler (handler prefix list))))
|
14
|
-
|
15
|
-
(mac define-prefix-list-macro (regex prefix-var list-var . body)
|
16
|
-
`(push (cons ,regex (fn (,prefix-var ,list-var) ,@body))
|
17
|
-
prefix-list-prefixes))
|
18
|
-
|
19
|
-
;;
|
20
|
-
;; so you can write (map λa(upcase a.name) people)
|
21
|
-
;;
|
22
|
-
;; instead of (map (fn (a) (upcase a.name)) people)
|
23
|
-
;;
|
24
|
-
(define-prefix-list-macro "^λ.+" vars expr
|
25
|
-
(let var-list (map sym (cdr:string-split vars))
|
26
|
-
`(fn ,var-list ,expr)))
|