nydp 0.2.3 → 0.2.5

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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/bin/nydp +1 -1
  3. data/lib/lisp/core-000.nydp +1 -0
  4. data/lib/lisp/core-010-precompile.nydp +15 -15
  5. data/lib/lisp/core-012-utils.nydp +6 -5
  6. data/lib/lisp/core-020-utils.nydp +20 -6
  7. data/lib/lisp/core-030-syntax.nydp +14 -16
  8. data/lib/lisp/core-035-flow-control.nydp +26 -8
  9. data/lib/lisp/core-040-utils.nydp +4 -15
  10. data/lib/lisp/core-041-string-utils.nydp +3 -3
  11. data/lib/lisp/core-043-list-utils.nydp +81 -16
  12. data/lib/lisp/core-045-dox-utils.nydp +2 -2
  13. data/lib/lisp/core-060-benchmarking.nydp +92 -27
  14. data/lib/lisp/tests/all-examples.nydp +20 -0
  15. data/lib/lisp/tests/any-examples.nydp +28 -0
  16. data/lib/lisp/tests/builtin-tests.nydp +3 -1
  17. data/lib/lisp/tests/collect-tests.nydp +10 -0
  18. data/lib/lisp/tests/curry-tests.nydp +7 -2
  19. data/lib/lisp/tests/error-tests.nydp +11 -0
  20. data/lib/lisp/tests/foundation-test.nydp +66 -0
  21. data/lib/lisp/tests/len-examples.nydp +1 -0
  22. data/lib/lisp/tests/list-gsub-examples.nydp +25 -0
  23. data/lib/lisp/tests/list-match-examples.nydp +40 -0
  24. data/lib/lisp/tests/list-tests.nydp +13 -0
  25. data/lib/lisp/tests/none-examples.nydp +16 -0
  26. data/lib/lisp/tests/parser-tests.nydp +4 -5
  27. data/lib/lisp/tests/quasiquote-examples.nydp +2 -0
  28. data/lib/lisp/tests/syntax-tests.nydp +3 -2
  29. data/lib/lisp/tests/tuples-examples.nydp +2 -2
  30. data/lib/nydp.rb +50 -18
  31. data/lib/nydp/assignment.rb +3 -1
  32. data/lib/nydp/builtin.rb +15 -13
  33. data/lib/nydp/builtin/error.rb +1 -1
  34. data/lib/nydp/builtin/handle_error.rb +8 -2
  35. data/lib/nydp/builtin/parse_in_string.rb +1 -1
  36. data/lib/nydp/builtin/plus.rb +4 -4
  37. data/lib/nydp/closure.rb +5 -1
  38. data/lib/nydp/compiler.rb +2 -3
  39. data/lib/nydp/cond.rb +134 -13
  40. data/lib/nydp/context_symbol.rb +4 -1
  41. data/lib/nydp/error.rb +8 -0
  42. data/lib/nydp/function_invocation.rb +46 -48
  43. data/lib/nydp/helper.rb +15 -0
  44. data/lib/nydp/interpreted_function.rb +10 -14
  45. data/lib/nydp/lexical_context.rb +13 -2
  46. data/lib/nydp/lexical_context_builder.rb +28 -13
  47. data/lib/nydp/pair.rb +35 -36
  48. data/lib/nydp/parser.rb +3 -0
  49. data/lib/nydp/runner.rb +4 -32
  50. data/lib/nydp/string_atom.rb +3 -2
  51. data/lib/nydp/symbol.rb +1 -1
  52. data/lib/nydp/symbol_lookup.rb +9 -1
  53. data/lib/nydp/truth.rb +1 -1
  54. data/lib/nydp/version.rb +1 -1
  55. data/lib/nydp/vm.rb +2 -2
  56. data/nydp.gemspec +1 -1
  57. data/spec/error_spec.rb +14 -4
  58. data/spec/hash_non_hash_behaviour_spec.rb +19 -12
  59. data/spec/hash_spec.rb +0 -13
  60. data/spec/pair_spec.rb +17 -3
  61. data/spec/spec_helper.rb +13 -1
  62. data/spec/symbol_spec.rb +1 -1
  63. metadata +9 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 546120f25e3fa424942cb1d4f6296da7007fa3a1
4
- data.tar.gz: afc6a8ac316812422abd8b4d8aa0e7c870ab73fd
3
+ metadata.gz: dc628274c2cf2f44cd05559766575d3cc9920d69
4
+ data.tar.gz: 619d6083cf6dab728793950bbc005fe3b281be56
5
5
  SHA512:
6
- metadata.gz: a8d144329085f686df6e0b3b12be6fb207e08fe0edca7633088d3a59095cdf1c0953636b8faf352037bdd22fc13dbc822604a76b6f6709b1e3d74787362ad34c
7
- data.tar.gz: 6c0875dfd8712fc2fb22dd987cc4cf323d7e4c39b6444e4da0b6e8790706e3f7714f0e1fdac563edad9ce1104cb1e38600becb3fdcadd668b498d0c2b5c9384c
6
+ metadata.gz: 391b384008f3e7e23505cb0871ab667435aea31a0841f71f3572316bdf1fc731a142f6dff7f0e2be26cf2eb60750bd60cf8ae89f298f9670f387b24fa2fd6141
7
+ data.tar.gz: 4390de26c600a52fbcf82bd91045acd3ed8791aeddcbec340cd227982632a28cdf2cbb1db42f2608f48b04010d3526870d5bfbfcc8161bf6601edd290394b5e5
data/bin/nydp CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  require 'nydp'
4
4
 
5
- Nydp.repl verbose: ($*.include? "-v")
5
+ Nydp.repl verbose: ($*.include? "-v"), exit: ($*.include? "-x"), silent: ($*.include? "-s")
@@ -6,6 +6,7 @@
6
6
  ;; README.md however for some significant differences
7
7
 
8
8
  (assign list (fn args args))
9
+ (assign noop (fn args nil))
9
10
  (assign caar (fn (arg) (car (car arg))))
10
11
  (assign cadr (fn (arg) (car (cdr arg))))
11
12
  (assign cdar (fn (arg) (cdr (car arg))))
@@ -70,11 +70,11 @@
70
70
  (qq-skip-unquote-splicing arg rest level)))
71
71
 
72
72
  (def qq-do-unquote-splicing (arg rest level)
73
- (cond (no rest)
74
- arg
73
+ (cond rest
75
74
  (list '+
76
75
  (pre-compile arg)
77
- (qq-quasiquote rest level))))
76
+ (qq-quasiquote rest level))
77
+ arg))
78
78
 
79
79
  (def qq-skip-unquote-splicing (arg rest level)
80
80
  (list 'cons
@@ -117,18 +117,18 @@
117
117
  (pre-compile xs)
118
118
  (list 'list ''unquote (qq-quasiquote xs (- level 1)))))
119
119
 
120
- (def qq-quasiquote (xs level)
121
- (cond (no xs)
122
- nil
123
- (cond (pair? xs)
124
- (cond (eq? (car xs) 'unquote)
125
- (qq-maybe-unquote (cadr xs) level)
126
- (cond (eq? (car xs) 'unquote-splicing)
127
- (qq-handle-unquote-splicing (cadr xs) nil level)
128
- (cond (eq? (car xs) 'quasiquote)
129
- (list 'list ''quasiquote (qq-quasiquote (cdr xs) (+ level 1)))
130
- (qq-unquote? (car xs) (cdr xs) level))))
131
- (list 'quote xs))))
120
+ (def qq-quasiquote (things level)
121
+ (cond things
122
+ (cond (pair? things)
123
+ (cond (eq? (car things) 'unquote)
124
+ (qq-maybe-unquote (cadr things) level)
125
+ (cond (eq? (car things) 'unquote-splicing)
126
+ (qq-handle-unquote-splicing (cadr things) nil level)
127
+ (cond (eq? (car things) 'quasiquote)
128
+ (list 'list ''quasiquote (qq-quasiquote (cdr things) (+ level 1)))
129
+ (qq-unquote? (car things) (cdr things) level))))
130
+ (list 'quote things))
131
+ nil))
132
132
 
133
133
  (hash-set macs 'quasiquote
134
134
  (fn (arg) (qq-quasiquote arg 0)))
@@ -1,11 +1,12 @@
1
1
 
2
2
  (hash-set macs 'if (fn args
3
- (cond (no args) nil
3
+ (cond args
4
4
  (cond (cdr args)
5
5
  (cond (cddr args)
6
6
  `(cond ,(car args) ,(cadr args) (if ,@(cddr args)))
7
7
  `(cond ,(car args) ,(cadr args)))
8
- (car args)))))
8
+ (car args))
9
+ nil)))
9
10
 
10
11
  (def map (f things)
11
12
  ; transforms the list 'things by applying 'f to each item
@@ -20,10 +21,10 @@
20
21
  (hash-set h k (cons v (hash-get h k))))
21
22
 
22
23
  (def rev-accum (things acc)
23
- (cond (no things)
24
- acc
24
+ (cond things
25
25
  (rev-accum (cdr things)
26
26
  (cons (car things)
27
- acc))))
27
+ acc))
28
+ acc))
28
29
 
29
30
  (def rev (things) (rev-accum things nil))
@@ -9,12 +9,13 @@
9
9
  "with arguments a b c d e, return b if a is true, otherwise return d if c is true, otherwise e"
10
10
  "and so on for subsequent arguments")
11
11
  'args
12
- '(cond (no args) nil
12
+ '(cond args
13
13
  (cond (cdr args)
14
14
  (cond (cddr args)
15
15
  `(cond ,(car args) ,(cadr args) (if ,@(cddr args)))
16
16
  `(cond ,(car args) ,(cadr args)))
17
- (car args)))
17
+ (car args))
18
+ nil)
18
19
  '(flow-control))
19
20
 
20
21
  (dox-add-doc 'map
@@ -22,11 +23,10 @@
22
23
  '("transforms the list 'things by applying 'f to each item"
23
24
  "returns the resulting list")
24
25
  '(f things)
25
- '(if (no things)
26
- nil
27
- (pair? things)
26
+ '(if (pair? things)
28
27
  (cons (f (car things)) (map f (cdr things)))
29
- (map f (list things)))
28
+ things
29
+ (f things))
30
30
  '(list-manipulation))
31
31
 
32
32
  (dox-add-doc 'rev
@@ -42,3 +42,17 @@
42
42
  '(h k v)
43
43
  '(hash-set h k (cons v (hash-get h k)))
44
44
  '(hash-manipulation))
45
+
46
+ (def join-str (prefix joint things)
47
+ (chapter string-manipulation)
48
+ ; equivalent to (join-str "~prefix~joint~(car things)" joint (cdr things)) - except
49
+ ; 'string-pieces hasn't been defined yet, and if it were, it would be defined in terms of
50
+ ; 'join-str, so it would be circular.
51
+ ; see 'joinstr for a more powerful and easier-to-use implementation of the same idea
52
+ (if things
53
+ (join-str (+ (to-string prefix)
54
+ joint
55
+ (to-string (car things)))
56
+ joint
57
+ (cdr things))
58
+ prefix))
@@ -47,7 +47,7 @@ scoping, assignment, anonymous functions and more...")
47
47
  (fn (,var) ,@body)))
48
48
 
49
49
  (def-colon-syntax || names
50
- (error "Irregular ': syntax: got ~(inspect names) : not prefix-syntax : in ~(joinstr ":" names)"))
50
+ (error "Irregular ': syntax: got ~(inspect names) : not prefix-syntax : in ~(join-str (car names) ":" (cdr names))"))
51
51
 
52
52
  (mac colon-syntax names
53
53
  ; handle syntax of the form a:b, which the parser expands to
@@ -68,9 +68,9 @@ scoping, assignment, anonymous functions and more...")
68
68
  ; For example,
69
69
  ; (!eq? a 10) is the same as (no:eq? a 10), which is the same as (no (eq? a 10))
70
70
  (if (no (eq? pfx '||))
71
- (error "Irregular '! syntax: got prefix ~(inspect pfx) in ~(joinstr "!" (cons pfx rest))"))
71
+ (error "Irregular '! syntax: got prefix ~(inspect pfx) in ~(join-str pfx "!" rest)"))
72
72
  (if (cdr rest)
73
- (error "Irregular '! syntax: got suffix ~(inspect (cdr rest)) in ~(joinstr "!" (cons pfx rest))")
73
+ (error "Irregular '! syntax: got suffix ~(inspect (cdr rest)) in ~(join-str pfx "!" rest)")
74
74
  (if (caris 'colon-syntax (car rest))
75
75
  `(colon-syntax no ,@(cdar rest))
76
76
  `(colon-syntax no ,(car rest)))))
@@ -79,10 +79,10 @@ scoping, assignment, anonymous functions and more...")
79
79
  `(cond ,condition (do ,@body)))
80
80
 
81
81
  (def pairs (things)
82
- (if (no things) nil
83
- (no (cdr things)) (list (list (car things)))
84
- (cons (list (car things) (cadr things))
85
- (pairs (cddr things)))))
82
+ (if (no things) nil
83
+ (no (cdr things)) (list (list (car things)))
84
+ (cons (list (car things) (cadr things))
85
+ (pairs (cddr things)))))
86
86
 
87
87
  (mac with (parms . body)
88
88
  `((fn ,(map car (pairs parms))
@@ -117,13 +117,11 @@ scoping, assignment, anonymous functions and more...")
117
117
  (,name ,@(map cadr ppairs)))))
118
118
 
119
119
  (let uniq-counter 0
120
- (def uniq (prefix)
121
- (sym (joinstr "-"
122
- (list prefix
123
- (assign uniq-counter
124
- (+ uniq-counter 1))))))
125
- (def reset-uniq-counter ()
126
- (assign uniq-counter 0)))
120
+ (def uniq (prefix)
121
+ (assign uniq-counter (+ uniq-counter 1))
122
+ (sym (join-str prefix "-" (list uniq-counter))))
123
+ (def reset-uniq-counter ()
124
+ (assign uniq-counter 0)))
127
125
 
128
126
  (mac w/uniq (vars . body)
129
127
  ; creates a lexical scope with a unique symbol assigned to
@@ -226,9 +224,9 @@ scoping, assignment, anonymous functions and more...")
226
224
  (mac ampersand-syntax (pfx . rest)
227
225
  ; parser expands a&b to (ampersand-syntax a b)
228
226
  (if (no (eq? pfx '||))
229
- (error "Irregular '& syntax: got prefix ~(inspect pfx) in ~(joinstr "&" (cons pfx rest))"))
227
+ (error "Irregular '& syntax: got prefix ~(inspect pfx) in ~(join-str pfx "&" rest)"))
230
228
  (if (cdr rest)
231
- (error "Irregular '& syntax: got suffix ~(inspect (cdr rest)) in ~(joinstr "&" (cons pfx rest))")
229
+ (error "Irregular '& syntax: got suffix ~(inspect (cdr rest)) in ~(join-str pfx "&" rest)")
232
230
  (build-ampersand-syntax (car rest))))
233
231
 
234
232
  (mac brace-list-mono (arg)
@@ -2,9 +2,10 @@
2
2
 
3
3
  (mac on-err (handler . body)
4
4
  ; executes 'body. If an error is raised, executes 'handler. Inside
5
- ; 'handler, the parameter 'err refers to the error that was raised.
6
- `(handle-error (fn (err) ,handler)
7
- (fn () ,@body)))
5
+ ; 'handler, the parameter 'errors is a list of error messages extracted from
6
+ ; the sequence of errors that led here (Exception#cause in ruby or Throwable.getCause() in java)
7
+ `(handle-error (fn (errors) ,handler)
8
+ (fn () ,@body)))
8
9
 
9
10
  (mac ensure (protection . body)
10
11
  ; executes 'body. Afterwards, executes 'protection.
@@ -39,12 +40,29 @@
39
40
  (loop (assign ,v ,gi) (< ,v ,gm) (assign ,v (+ ,v 1))
40
41
  ,@body))))
41
42
 
42
- (def curry (func . args1)
43
+ (mac curry (func . args1)
43
44
  ; return a new function which is the original function with
44
45
  ; the given args1 already applied
45
46
  ; arguments to the new function are whatever arguments remain
46
47
  ; for the old function
47
- (fn args
48
- (apply func
49
- (joinlists args1
50
- args))))
48
+ `(fn args (apply ,func ,@args1 args)))
49
+
50
+ (mac cache-get (hsh key val)
51
+ ; if ,key is already in ,hsh - return the associated value.
52
+ ; if ,key is not already in ,hsh - evaluate ,val, store the result
53
+ ; under ,key in ,hsh, and return it
54
+ (w/uniq (h k v)
55
+ `(with (,h ,hsh ,k ,key)
56
+ (let ,v (hash-get ,h ,k)
57
+ (or ,v (returnlet ,v ,val (hash-set ,h ,k ,v)))))))
58
+
59
+ (mac defmemo (name args . body)
60
+ ; same as 'def, but caches the result, keyed on args, so for a given set of args the result
61
+ ; is only ever calculated once
62
+ (let forms (filter-forms (build-def-hash (hash)) body)
63
+ (w/uniq h
64
+ `(let ,h (hash)
65
+ (def ,name ,args
66
+ ,@(if forms.comment (map (fn (c) list 'comment c)) forms.comment)
67
+ ,(if forms.chapter `(chapter ,forms.chapter))
68
+ (cache-get ,h (list ,@args) (do ,@(hash-get forms nil))))))))
@@ -1,17 +1,5 @@
1
1
  (chapter-start 'nydp-core "essential functions for getting anything done")
2
2
 
3
- (def joinstr (txt . things)
4
- ; flatten 'things into a single list (ie unnest lists)
5
- ; convert each item to a string
6
- ; return a single string which is the concatenation of each
7
- ; stringified item, with given 'txt inserted in between
8
- ; each item
9
- (let joinables (flatten things)
10
- (apply +
11
- (to-string (car joinables))
12
- (flatten (zip (map (fn (_) txt) (cdr joinables))
13
- (map to-string (cdr joinables)))))))
14
-
15
3
  (def iso (x y)
16
4
  (or (eq? x y)
17
5
  (and (pair? x)
@@ -21,6 +9,7 @@
21
9
 
22
10
  (def x1 (thing) thing)
23
11
  (def sym? (arg) (isa 'symbol arg))
12
+ (def num? (arg) (isa 'number arg))
24
13
  (def string? (arg) (isa 'string arg))
25
14
  (mac just (arg) arg)
26
15
  (def quotify (arg) `(quote ,arg))
@@ -32,11 +21,11 @@
32
21
  (chapter list-manipulation)
33
22
  (chapter string-manipulation)
34
23
  (chapter hash-manipulation)
35
- (if (no things) 0
36
- (pair? things) (list-length things)
24
+ (if (pair? things) (list-length things)
37
25
  (string? things) (string-length things)
38
26
  (hash? things) (list-length:hash-keys things)
39
- nil))
27
+ things nil
28
+ 0))
40
29
 
41
30
  (assign dynamics (hash))
42
31
 
@@ -11,9 +11,9 @@
11
11
  ; each item
12
12
  (let joinables (flatten things)
13
13
  (apply +
14
- (to-string (car joinables))
15
- (flatten (zip (map (fn (_) txt) (cdr joinables))
16
- (map to-string (cdr joinables)))))))
14
+ (to-string:car joinables)
15
+ (flatten (map (fn (x) (list txt x))
16
+ (cdr joinables))))))
17
17
 
18
18
  (def j items
19
19
  ; delegate to 'joinstr with an empty join string
@@ -1,18 +1,20 @@
1
1
  (chapter-start 'list-manipulation)
2
2
 
3
3
  (def list-length (things)
4
- (if (no things) 0
5
- (atom? things) 1
6
- (+ 1 (list-length:cdr things))))
4
+ (if (atom? things) 1
5
+ things (+ 1 (list-length (cdr things)))
6
+ 0))
7
7
 
8
8
  (def list-slices (things slice-size)
9
9
  ; slice 'things into a list of lists each with maximum 'slice-size items
10
10
  (chapter pagination)
11
- (if (< (len things) slice-size)
12
- (cons things nil)
13
- (cons (firstn slice-size things)
14
- (list-slices (nthcdr slice-size things)
15
- slice-size))))
11
+ (if things
12
+ (if (> slice-size (len things))
13
+ (list things)
14
+ (cons (firstn slice-size things)
15
+ (list-slices (nthcdr slice-size things)
16
+ slice-size)))
17
+ nil))
16
18
 
17
19
  (def intersperse (inbetween things)
18
20
  ; return a new list with 'inbetween in between every element of 'things
@@ -43,6 +45,16 @@
43
45
  (f items)
44
46
  items)))
45
47
 
48
+ (assign select collect)
49
+
50
+ (def compact (things)
51
+ ; return a new list containing only non-nil items from the given list
52
+ (collect present? things))
53
+
54
+ (def +nz args
55
+ ; return the sum of all non-nil values (consider nil as zero)
56
+ (apply + (compact args)))
57
+
46
58
  (def reject (f things)
47
59
  ; return all the items in 'things for which 'f returns nil
48
60
  (collect !f things))
@@ -53,14 +65,13 @@
53
65
  (car things)
54
66
  (nth (- n 1) (cdr things))))
55
67
 
56
- (mac each (var things code)
68
+ (mac each (var things . body)
57
69
  ; repeatedly assigns an element of 'things to 'var,
58
- ; and executes 'code each time
70
+ ; and executes 'body each time
59
71
  (w/uniq (xs c)
60
72
  `((rfn ,c (,xs)
61
73
  (if (pair? ,xs)
62
- (do
63
- (let ,var (car ,xs) ,code)
74
+ (do (let ,var (car ,xs) ,@body)
64
75
  (,c (cdr ,xs)))))
65
76
  ,things)))
66
77
 
@@ -81,10 +92,10 @@
81
92
 
82
93
  (def firstn (n things)
83
94
  ; returns the first 'n items in the list 'things
84
- (if (eq? n 0) nil
85
- (cons (car things)
86
- (firstn (- n 1)
87
- (cdr things)))))
95
+ (if (eq? n 0) nil
96
+ things (cons (car things)
97
+ (firstn (- n 1)
98
+ (cdr things)))))
88
99
 
89
100
  (def nthcdr (n things)
90
101
  ; returns the nth cdr of the list 'things
@@ -155,3 +166,57 @@
155
166
 
156
167
  (def min things (best < things))
157
168
  (def max things (best > things))
169
+
170
+ (def map-recurse (on-atom on-list things)
171
+ ((afn (xs)
172
+ (if (pair? xs)
173
+ (on-list self xs)
174
+ xs
175
+ (on-atom xs)))
176
+ things))
177
+
178
+ (def list-gsub (list old new)
179
+ ; recursively replaces 'old with 'new inside 'list
180
+ (map-recurse (fn (s) (if (eq? s old) new s))
181
+ (fn (m things)
182
+ (if (eq? things old)
183
+ new
184
+ (map m things)))
185
+ list))
186
+
187
+ (def all? (f things)
188
+ ; if 'things is a list, true when all items are non-nil
189
+ ; if 'things is an atom, true when non-nil
190
+ (if (pair? things)
191
+ (and (f:car things)
192
+ (or (no:cdr things)
193
+ (all? f (cdr things))))
194
+ (f things)))
195
+
196
+ (def any? (f things)
197
+ ; if 'things is a list, true when at least one item is non-nil
198
+ ; if 'things is an atom, true when non-nil
199
+ (if (pair? things)
200
+ (or (f:car things)
201
+ (and (cdr things)
202
+ (any? f (cdr things))))
203
+ (f things)))
204
+
205
+ (def none? (f things)
206
+ ; if 'things is a list, true when all items are nil
207
+ ; if 'things is an atom, true when nil
208
+ (if (pair? things)
209
+ (and (no:f:car things)
210
+ (none? f (cdr things)))
211
+ (no:f things)))
212
+
213
+ (def list-match? (matchers things)
214
+ ; 'matchers is a list of functions
215
+ ; 'things is a list of items to match
216
+ ; true when each function in 'matchers returns non-nil for the corresponding value in 'things
217
+ (if (pair? matchers)
218
+ (and ((car matchers) (car things))
219
+ (list-match? (cdr matchers) (cdr things)))
220
+ matchers
221
+ (matchers things)
222
+ t))