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