nydp 0.4.2 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +44 -0
- data/lib/lisp/core-010-precompile.nydp +13 -16
- data/lib/lisp/core-012-utils.nydp +3 -2
- data/lib/lisp/core-015-documentation.nydp +54 -23
- data/lib/lisp/core-017-builtin-dox.nydp +14 -12
- data/lib/lisp/core-020-utils.nydp +5 -5
- data/lib/lisp/core-030-syntax.nydp +166 -72
- data/lib/lisp/core-035-flow-control.nydp +38 -11
- data/lib/lisp/core-037-list-utils.nydp +12 -0
- data/lib/lisp/core-039-module.nydp +24 -0
- data/lib/lisp/core-040-utils.nydp +32 -12
- data/lib/lisp/core-041-string-utils.nydp +25 -1
- data/lib/lisp/core-042-date-utils.nydp +21 -1
- data/lib/lisp/core-043-list-utils.nydp +96 -64
- data/lib/lisp/core-070-prefix-list.nydp +1 -1
- data/lib/lisp/core-080-pretty-print.nydp +57 -17
- data/lib/lisp/core-090-hook.nydp +35 -1
- data/lib/lisp/core-100-utils.nydp +82 -2
- data/lib/lisp/core-110-hash-utils.nydp +56 -2
- data/lib/lisp/core-120-settings.nydp +16 -5
- data/lib/lisp/core-130-validations.nydp +51 -0
- data/lib/lisp/core-900-benchmarking.nydp +78 -20
- data/lib/lisp/tests/accum-examples.nydp +28 -1
- data/lib/lisp/tests/aif-examples.nydp +8 -3
- data/lib/lisp/tests/andify-examples.nydp +7 -0
- data/lib/lisp/tests/at-syntax-examples.nydp +17 -0
- data/lib/lisp/tests/best-examples.nydp +9 -0
- data/lib/lisp/tests/builtin-tests.nydp +19 -0
- data/lib/lisp/tests/case-examples.nydp +14 -0
- data/lib/lisp/tests/date-examples.nydp +54 -1
- data/lib/lisp/tests/destructuring-examples.nydp +46 -14
- data/lib/lisp/tests/detect-examples.nydp +12 -0
- data/lib/lisp/tests/dp-examples.nydp +24 -0
- data/lib/lisp/tests/each-tests.nydp +5 -0
- data/lib/lisp/tests/empty-examples.nydp +1 -1
- data/lib/lisp/tests/error-tests.nydp +4 -4
- data/lib/lisp/tests/explain-mac-examples.nydp +1 -1
- data/lib/lisp/tests/filter-forms-examples.nydp +15 -0
- data/lib/lisp/tests/hash-examples.nydp +25 -1
- data/lib/lisp/tests/list-grep-examples.nydp +40 -0
- data/lib/lisp/tests/list-tests.nydp +58 -1
- data/lib/lisp/tests/map-hash-examples.nydp +11 -0
- data/lib/lisp/tests/module-examples.nydp +10 -0
- data/lib/lisp/tests/multi-assign-examples.nydp +6 -0
- data/lib/lisp/tests/parser-tests.nydp +25 -0
- data/lib/lisp/tests/pretty-print-tests.nydp +17 -14
- data/lib/lisp/tests/set-difference-examples.nydp +8 -0
- data/lib/lisp/tests/settings-examples.nydp +17 -1
- data/lib/lisp/tests/string-tests.nydp +70 -1
- data/lib/lisp/tests/syntax-tests.nydp +5 -1
- data/lib/lisp/tests/to-integer-examples.nydp +16 -0
- data/lib/lisp/tests/validation-examples.nydp +15 -0
- data/lib/nydp.rb +10 -3
- data/lib/nydp/assignment.rb +10 -3
- data/lib/nydp/builtin.rb +1 -1
- data/lib/nydp/builtin/abs.rb +8 -0
- data/lib/nydp/builtin/date.rb +15 -1
- data/lib/nydp/builtin/error.rb +1 -1
- data/lib/nydp/builtin/hash.rb +24 -1
- data/lib/nydp/builtin/inspect.rb +1 -1
- data/lib/nydp/builtin/plus.rb +10 -2
- data/lib/nydp/builtin/random_string.rb +2 -2
- data/lib/nydp/builtin/{car.rb → regexp.rb} +2 -2
- data/lib/nydp/builtin/ruby_wrap.rb +72 -0
- data/lib/nydp/builtin/string_match.rb +2 -2
- data/lib/nydp/builtin/string_pad_left.rb +7 -0
- data/lib/nydp/builtin/string_pad_right.rb +7 -0
- data/lib/nydp/builtin/string_replace.rb +3 -3
- data/lib/nydp/builtin/string_split.rb +4 -3
- data/lib/nydp/builtin/to_integer.rb +23 -0
- data/lib/nydp/builtin/to_string.rb +2 -9
- data/lib/nydp/builtin/type_of.rb +9 -6
- data/lib/nydp/closure.rb +0 -3
- data/lib/nydp/cond.rb +23 -1
- data/lib/nydp/context_symbol.rb +14 -6
- data/lib/nydp/core.rb +36 -28
- data/lib/nydp/core_ext.rb +21 -5
- data/lib/nydp/date.rb +26 -18
- data/lib/nydp/function_invocation.rb +34 -26
- data/lib/nydp/helper.rb +35 -3
- data/lib/nydp/interpreted_function.rb +68 -40
- data/lib/nydp/literal.rb +1 -1
- data/lib/nydp/pair.rb +22 -5
- data/lib/nydp/parser.rb +11 -7
- data/lib/nydp/string_atom.rb +3 -4
- data/lib/nydp/symbol_lookup.rb +7 -7
- data/lib/nydp/tokeniser.rb +2 -2
- data/lib/nydp/truth.rb +10 -10
- data/lib/nydp/version.rb +1 -1
- data/lib/nydp/vm.rb +7 -0
- data/nydp.gemspec +2 -4
- data/spec/date_spec.rb +93 -0
- data/spec/embedded_spec.rb +12 -12
- data/spec/foreign_hash_spec.rb +14 -2
- data/spec/hash_non_hash_behaviour_spec.rb +7 -7
- data/spec/hash_spec.rb +24 -2
- data/spec/nydp_spec.rb +14 -2
- data/spec/pair_spec.rb +3 -1
- data/spec/parser_spec.rb +31 -20
- data/spec/rand_spec.rb +3 -3
- data/spec/spec_helper.rb +10 -1
- metadata +24 -37
- data/lib/nydp/builtin/cdr.rb +0 -7
- data/lib/nydp/builtin/cons.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: adb6cc0345ed64c1e0e7ac99c06d9aa1328482e7d51d771cd77b844e1c5a6e14
|
4
|
+
data.tar.gz: 997c1f318ed518f3d2100699c1532db9a140f7109d6e4ddef6e68055466eb23a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a80109cc7bf73c177c6f89697e386a0a12d3645512bd14db2ed036711ef2c0b11d80fef67cff8dbc6f7bfed23d103220b9bc909aa9b34590323375db699c5e3
|
7
|
+
data.tar.gz: 25864fdef654329baef7d494a54b926f6dd236399f131e5943505752784713b03dc9e79640407c1df6af17ac380c483d82e2fae5e35fa3f3636b1226384eaa58
|
data/README.md
CHANGED
@@ -55,6 +55,22 @@ answer = Nydp.apply_function ns, :question, :life, ["The Universe", and_also(eve
|
|
55
55
|
|
56
56
|
You can maintain multiple `ns` instances without mutual interference. In other words, assigning global variables while one `ns` is in scope will not affect the values of variables in any other `ns` (unless you've specifically arranged it to be so by duplicating namespaces or some such sorcery).
|
57
57
|
|
58
|
+
|
59
|
+
#### Facing the Truth
|
60
|
+
|
61
|
+
In conditional statements, nil is false, anything else is true
|
62
|
+
|
63
|
+
```lisp
|
64
|
+
(if) ;; same as (if nil)
|
65
|
+
(if a) ;; same as a
|
66
|
+
(if a b) ;; same as (if a b nil)
|
67
|
+
(if a b c) ;; if a is nil, return c, otherwise return b
|
68
|
+
(if a b c d) ;; same as (if a b (if c d))
|
69
|
+
(if a b c d e) ;; same as (if a b (if c d e))
|
70
|
+
|
71
|
+
;; and so on
|
72
|
+
```
|
73
|
+
|
58
74
|
## Different from Arc :
|
59
75
|
|
60
76
|
#### 1. Macro-expansion runs in lisp
|
@@ -151,8 +167,36 @@ nydp > (map &lastname german-composers) ; ampersand-syntax creates a function
|
|
151
167
|
|
152
168
|
As with all other syntax, you can of course override the `ampersand-syntax` macro to handle your special needs.
|
153
169
|
|
170
|
+
You can combine special syntaxes ("%td" comes from nydp-html gem)
|
171
|
+
|
172
|
+
```lisp
|
173
|
+
|
174
|
+
nydp > (map %td:&lastname german-composers)
|
175
|
+
|
176
|
+
"<td>Bach</td><td>Beethoven</td><td>Wagner</td><td>Mozart</td>"
|
177
|
+
|
178
|
+
```
|
179
|
+
|
180
|
+
So, @%td@ expands to @(percent-syntax || td)@, @&lastname@ to @(ampersand-syntax || lastname)@, and the whole @%td:&lastname@
|
181
|
+
to @(colon-syntax (percent-syntax || td) (ampersand-syntax || lastname))@. Luckily for you, there's a fine @colon-syntax@ macro
|
182
|
+
that knows how to build a function out of these bits and pieces.
|
183
|
+
|
184
|
+
|
154
185
|
Look for `SYMBOL_OPERATORS` in [parser.rb](lib/nydp/parser.rb) to see which syntax is recognised and in which order. The order of these definitions defines special-syntax-operator precedence.
|
155
186
|
|
187
|
+
Any character that is not special syntax will be recognised as part of a symbol. At time of writing, this includes the plus sign, hyphen, and slash.
|
188
|
+
|
189
|
+
```lisp
|
190
|
+
|
191
|
+
;; nonsense code illustrating the use of certain
|
192
|
+
;; characters as function and variable names
|
193
|
+
(def //-+ (x y z)
|
194
|
+
(let -*- (x y)
|
195
|
+
(if z (//-+ x y -*-) -*-)))
|
196
|
+
|
197
|
+
```
|
198
|
+
|
199
|
+
|
156
200
|
#### 3. Special list syntax
|
157
201
|
|
158
202
|
The parser detects alternative list delimiters
|
@@ -1,17 +1,15 @@
|
|
1
|
-
(assign mac-expand
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
(assign mac-expand
|
2
|
+
(fn (names macfn expr)
|
3
|
+
(cond macfn
|
4
|
+
(handle-error
|
5
|
+
(fn (errors)
|
6
|
+
(error "expanding" (inspect expr) "with" (inspect macfn)))
|
7
|
+
(fn ()
|
8
|
+
(pre-compile-with names (apply macfn (cdr expr)))))
|
9
|
+
expr)))
|
6
10
|
|
7
11
|
(assign macs (hash))
|
8
12
|
|
9
|
-
(assign pre-compile-expr
|
10
|
-
(fn (names expr)
|
11
|
-
(mac-expand names
|
12
|
-
(hash-get names (car expr))
|
13
|
-
expr)))
|
14
|
-
|
15
13
|
(assign pre-compile-each
|
16
14
|
(fn (names args)
|
17
15
|
(cond args
|
@@ -33,7 +31,10 @@
|
|
33
31
|
(cond (eq? (car arg) 'quote)
|
34
32
|
arg
|
35
33
|
(pre-compile-each names
|
36
|
-
(
|
34
|
+
(mac-expand names
|
35
|
+
(hash-get names
|
36
|
+
(car arg))
|
37
|
+
arg)))
|
37
38
|
arg)))
|
38
39
|
|
39
40
|
(assign pre-compile-debug
|
@@ -136,7 +137,3 @@
|
|
136
137
|
|
137
138
|
(hash-set macs 'quasiquote
|
138
139
|
(fn (arg) (qq-quasiquote arg 0)))
|
139
|
-
|
140
|
-
(hash-set macs 'do
|
141
|
-
(fn args
|
142
|
-
`((fn nil ,@args))))
|
@@ -8,7 +8,7 @@
|
|
8
8
|
(car args))
|
9
9
|
nil)))
|
10
10
|
|
11
|
-
(def map-helper-0 (f things lc
|
11
|
+
(def map-helper-0 (f things lc)
|
12
12
|
(if (pair? things)
|
13
13
|
(map-helper-0 f (cdr things) (cdr-set lc (cons (f (car things)))))
|
14
14
|
things
|
@@ -30,8 +30,9 @@
|
|
30
30
|
(def map (f things)
|
31
31
|
(map-helper-1 f things (cons)))
|
32
32
|
|
33
|
+
;; push 'v onto the value for 'k in 'h
|
34
|
+
;; the hash-values of h will all be lists, in reverse order of consing
|
33
35
|
(def hash-cons (h k v)
|
34
|
-
; push 'v onto the value for 'k in 'h
|
35
36
|
(hash-set h k (cons v (hash-get h k))))
|
36
37
|
|
37
38
|
(def rev (things last-cdr)
|
@@ -19,6 +19,12 @@
|
|
19
19
|
acc)))
|
20
20
|
form))
|
21
21
|
|
22
|
+
(hash-set macs 'do
|
23
|
+
(fn forms
|
24
|
+
(if (no (cdr forms))
|
25
|
+
(car forms)
|
26
|
+
`((fn nil ,@forms)))))
|
27
|
+
|
22
28
|
((fn (this-chapter-name chapters chapter-new chapter-build chapter-add-to-chapter)
|
23
29
|
(assign chapters (hash))
|
24
30
|
|
@@ -64,7 +70,7 @@
|
|
64
70
|
(assign this-script nil)
|
65
71
|
(assign this-plugin "Nydp Core")
|
66
72
|
|
67
|
-
((fn (dox examples chapters types dox-new dox-build)
|
73
|
+
((fn (dox examples chapters types types-chapters dox-new dox-build)
|
68
74
|
(def dox-build (hsh name what texts args src chapters)
|
69
75
|
(hash-set hsh 'name name )
|
70
76
|
(hash-set hsh 'what what )
|
@@ -79,16 +85,20 @@
|
|
79
85
|
(def dox-new (item)
|
80
86
|
(hash-cons dox (hash-get item 'name) item)
|
81
87
|
(hash-cons types (hash-get item 'what) item)
|
82
|
-
(dox-add-to-chapters item (hash-get item 'chapters)))
|
88
|
+
(dox-add-to-chapters item (hash-get item 'what) (hash-get item 'chapters) (hash)))
|
83
89
|
|
84
90
|
(def dox-add-doc (name what texts args src chapters more)
|
85
91
|
(cond (no (privately))
|
86
92
|
(dox-new (dox-build (if more more (hash)) name what texts args src chapters))))
|
87
93
|
|
88
|
-
(def dox-add-to-chapters (item chapters)
|
94
|
+
(def dox-add-to-chapters (item type chapters already)
|
89
95
|
(cond chapters
|
90
|
-
|
91
|
-
|
96
|
+
(cond (no (hash-get already (car chapters)))
|
97
|
+
(do (hash-set already (car chapters) t)
|
98
|
+
(chapter-add-item item (car chapters))
|
99
|
+
(hash-cons types-chapters (inspect (cons type (car chapters))) item)
|
100
|
+
(dox-add-to-chapters item type (cdr chapters) already))
|
101
|
+
item)
|
92
102
|
item))
|
93
103
|
|
94
104
|
(def dox-add-examples (name example-exprs)
|
@@ -102,6 +112,11 @@
|
|
102
112
|
(def dox-types () (hash-keys types))
|
103
113
|
(def dox-items-by-type (type) (hash-get types type))
|
104
114
|
|
115
|
+
(def get-types-chapters () types-chapters)
|
116
|
+
|
117
|
+
(def dox-items-by-type-and-chapter (dox-type chapter)
|
118
|
+
(hash-get types-chapters (inspect (cons dox-type chapter))))
|
119
|
+
|
105
120
|
(def dox-get-attr (name attr)
|
106
121
|
(cond (dox? name)
|
107
122
|
(hash-get (car (dox-lookup name)) attr)))
|
@@ -111,7 +126,7 @@
|
|
111
126
|
(def dox-examples (name) (hash-get examples name ))
|
112
127
|
(def dox-args (name) (dox-get-attr name 'args ))
|
113
128
|
(def dox-example-names () (hash-keys examples )))
|
114
|
-
(hash) (hash) (hash) (hash) nil)
|
129
|
+
(hash) (hash) (hash) (hash) (hash) nil)
|
115
130
|
|
116
131
|
(def plugin-start (name) (assign this-plugin name) (chapter-end))
|
117
132
|
(def plugin-end (name) (assign this-plugin nil ) (chapter-end))
|
@@ -128,9 +143,9 @@
|
|
128
143
|
(cond (eq? event 'script-end)
|
129
144
|
(script-end name))))))
|
130
145
|
|
146
|
+
;; if the car of 'form is a key of 'hsh, add the cdr of 'form to the value of the key in 'hsh
|
147
|
+
;; otherwise add the form to the list whose key is nil
|
131
148
|
(def filter-form (hsh form)
|
132
|
-
; if the car of 'form is a key of 'hsh, add the cdr of 'form to the value of the key in 'hsh
|
133
|
-
; otherwise add the form to the list whose key is nil
|
134
149
|
(cond (cond (pair? form)
|
135
150
|
(hash-key? hsh (car form)))
|
136
151
|
(hash-cons hsh (car form) (cdr form))
|
@@ -149,31 +164,43 @@
|
|
149
164
|
(def rev-values (hsh)
|
150
165
|
(rev-value-keys (hash-keys hsh) hsh (hash)))
|
151
166
|
|
167
|
+
;; group forms by their first element, if the first element
|
168
|
+
;; is already a key in hsh, collect all other elements under key nil
|
152
169
|
(def filter-forms (hsh forms)
|
153
|
-
; group forms by their first element, if the first element
|
154
|
-
; is already a key in hsh, collect all other elements under key nil
|
155
170
|
(cond forms
|
156
171
|
(filter-forms (filter-form hsh (car forms)) (cdr forms))
|
157
172
|
(rev-values hsh)))
|
158
173
|
|
159
|
-
(def
|
160
|
-
(
|
161
|
-
|
162
|
-
|
174
|
+
(def filter-remove (key forms keyforms otherforms)
|
175
|
+
(cond forms
|
176
|
+
(cond (cond (pair? forms) (cond (pair? (car forms)) (eq? key (caar forms))))
|
177
|
+
(filter-remove key (cdr forms) (cons (car forms) keyforms) otherforms)
|
178
|
+
(filter-remove key (cdr forms) keyforms (cons (car forms) otherforms)))
|
179
|
+
(list (rev keyforms) (rev otherforms))))
|
163
180
|
|
181
|
+
(assign DEF-FORMS '(comment chapter))
|
182
|
+
|
183
|
+
(def build-def-hash ()
|
184
|
+
((fn (h)
|
185
|
+
(map (fn (k) (hash-set h k nil)) DEF-FORMS)
|
186
|
+
h)
|
187
|
+
(hash)))
|
188
|
+
|
189
|
+
(def dox-build-def-name (name) name)
|
190
|
+
|
191
|
+
;; used internally by 'mac
|
164
192
|
(def define-mac-expr (name args body-forms)
|
165
|
-
; used internally by 'mac
|
166
193
|
`(do (hash-set macs ',name (fun ,args ,@(hash-get body-forms nil)))
|
167
|
-
(dox-add-doc ',name
|
194
|
+
(dox-add-doc ',(dox-build-def-name name)
|
168
195
|
'mac
|
169
|
-
',(map car (hash-get body-forms 'comment))
|
196
|
+
',(+ (fetch-and-clear-comments) (map car (hash-get body-forms 'comment)))
|
170
197
|
',args
|
171
198
|
'(mac ,name ,args ,@(hash-get body-forms nil))
|
172
199
|
',(map car (hash-get body-forms 'chapter)))))
|
173
200
|
|
174
201
|
(hash-set macs 'mac
|
175
202
|
(fn (name args . body)
|
176
|
-
(define-mac-expr name args (filter-forms (build-def-hash
|
203
|
+
(define-mac-expr name args (filter-forms (build-def-hash) body))))
|
177
204
|
|
178
205
|
(dox-add-doc 'mac
|
179
206
|
'mac
|
@@ -189,22 +216,26 @@
|
|
189
216
|
'`((fn nil ,@args))
|
190
217
|
'(nydp-core))
|
191
218
|
|
219
|
+
;; override later to use '= instead of 'assign, giving us hash-assignment and other goodies for free
|
192
220
|
(mac def-assign args `(assign ,@args))
|
193
221
|
|
222
|
+
;; used internally by 'def
|
194
223
|
(def define-def-expr (name args body-forms)
|
195
|
-
|
196
|
-
|
197
|
-
|
224
|
+
`(do (def-assign ,name
|
225
|
+
((fn (self-name)
|
226
|
+
(fun ,args ,@(filter-comments (hash-get body-forms nil))))
|
227
|
+
',name))
|
228
|
+
(dox-add-doc ',(dox-build-def-name name)
|
198
229
|
'def
|
199
230
|
',(+ (fetch-and-clear-comments) (map car (hash-get body-forms 'comment)))
|
200
231
|
',args
|
201
232
|
'(def ,name ,args ,@(hash-get body-forms nil))
|
202
233
|
',(map car (hash-get body-forms 'chapter)))))
|
203
234
|
|
235
|
+
;; define a new function in the global namespace
|
204
236
|
(mac def (name args . body)
|
205
|
-
; define a new function in the global namespace
|
206
237
|
(chapter nydp-core)
|
207
|
-
(define-def-expr name args (filter-forms (build-def-hash
|
238
|
+
(define-def-expr name args (filter-forms (build-def-hash) body)))
|
208
239
|
|
209
240
|
(mac comment (txt)
|
210
241
|
(assign comments (cons txt comments))
|
@@ -1,6 +1,7 @@
|
|
1
1
|
(dox-add-doc 'cons 'def '("with args a and b, returns a new cons cell, (a . b)") '(a b) nil '(list-manipulation))
|
2
2
|
(dox-add-doc 'car 'def '("with args a, where a is a cons cell (x . y), return x." "Commonly used to get the first element of a list") '(a) nil '(list-manipulation))
|
3
3
|
(dox-add-doc 'cdr 'def '("with args a, where a is a cons cell (x . y), return y." "Commonly used to get contents of a list, excluding the first element") '(a) nil '(list-manipulation))
|
4
|
+
(dox-add-doc 'log 'def '("write arg to Nydp.logger ; be sure to assign Nydp.logger first!") '(arg) nil '(nydp-core))
|
4
5
|
(dox-add-doc '+ 'def '("with rest-args things, return the sum of the elements of things." "Will also increment dates and concatenate strings and lists") 'things nil '(math))
|
5
6
|
(dox-add-doc '- 'def '("return the result of subtracting all other args from the first arg." "(- a b c d) is equivalent to (- a (+ b c d))") 'things nil '(math))
|
6
7
|
(dox-add-doc '* 'def '("with rest-args things, return the product of the elements of things.") 'things nil '(math))
|
@@ -35,21 +36,22 @@
|
|
35
36
|
(dox-add-doc 'pair? 'def '("t if arg is a cons cell or (equivalently) the start of a list") '(arg) nil '(nydp-core))
|
36
37
|
(dox-add-doc 'hash? 'def '("t if arg is a hash") '(arg) nil '(nydp-core))
|
37
38
|
(dox-add-doc 'sym? 'def '("t if arg is a symbol, nil otherwise") '(arg) nil '(nydp-core))
|
38
|
-
(dox-add-doc 'ensuring 'def '("execute '
|
39
|
-
"'ensure-f will always be executed, even if there is an error in '
|
40
|
-
"returns the return value of '
|
39
|
+
(dox-add-doc 'ensuring 'def '("execute 'try-f, then 'ensure-f afterwards"
|
40
|
+
"'ensure-f will always be executed, even if there is an error in 'try-f"
|
41
|
+
"returns the return value of 'try-f. Similar to try/finally in java, or begin/ensure in ruby.") '(ensure-f try-f) nil '(flow-control))
|
41
42
|
(dox-add-doc 'inspect 'def '("return a string representing 'arg, potentially (but not always) in a way that can be parsed back in to get the original object") '(arg) nil '(nydp-core))
|
42
43
|
(dox-add-doc 'comment 'def '("does nothing at all." "Intercepted inside 'def and 'mac and used for documentation") '(arg) nil '(nydp-core))
|
43
44
|
(dox-add-doc 'parse-in-string 'def '("parse the given string assuming a string-open delimiter has already been encountered") '(str) nil '(nydp-core))
|
44
45
|
(dox-add-doc 'rand 'def '("return a random number ; with no args, between 0 and 1"
|
45
46
|
"with 1 arg, an integer less than arg"
|
46
|
-
"with two args, an integer >= arg 0 and < arg 1") 'args
|
47
|
-
(dox-add-doc 'random-string 'def '("return a random string of length 'len (default 10)") '(len)
|
48
|
-
(dox-add-doc '
|
49
|
-
(dox-add-doc 'string
|
50
|
-
(dox-add-doc 'string-
|
51
|
-
(dox-add-doc 'string-
|
52
|
-
(dox-add-doc 'string-
|
47
|
+
"with two args, an integer >= arg 0 and < arg 1") 'args nil '(math))
|
48
|
+
(dox-add-doc 'random-string 'def '("return a random string of length 'len (default 10)") '(len) nil '(string-manipulation))
|
49
|
+
(dox-add-doc 'regexp 'def '("return a regular expression compiled from the given string") '(str) nil '(string-manipulation))
|
50
|
+
(dox-add-doc 'to-string 'def '("return a human-readable string representation of 'arg") '(arg) nil '(string-manipulation))
|
51
|
+
(dox-add-doc 'string-length 'def '("return the length of 'arg") '(arg) nil '(string-manipulation))
|
52
|
+
(dox-add-doc 'string-replace 'def '("replace 'pattern with 'replacement in 'str") '(pattern replacement str) nil '(string-manipulation))
|
53
|
+
(dox-add-doc 'string-split 'def '("split 'str delimited by 'delim") '(str delim) nil '(string-manipulation))
|
54
|
+
(dox-add-doc 'string-match 'def '("if 'str matches 'pattern, return hash with keys 'match and 'captures ; otherwise nil") '(str pattern) nil '(string-manipulation))
|
53
55
|
(dox-add-doc 'time 'def '("with no args, return the current time."
|
54
56
|
"With one arg, if 'arg-0 is a number, return the current time plus 'arg-0 seconds."
|
55
57
|
"With one arg, if 'arg-0 is a date, return the time at the beginning of the given date."
|
@@ -57,9 +59,9 @@
|
|
57
59
|
"With two args, 'arg-0 must be a time."
|
58
60
|
"If 'arg-1 is a number, return 'arg-0 plus 'arg-1 seconds as a time object."
|
59
61
|
"If 'arg-1 is a time, return the number of seconds between the two (- 'arg-0 arg-1)."
|
60
|
-
"Otherwise, expect 3
|
62
|
+
"Otherwise, expect 3 or more args, to construct a time from"
|
61
63
|
"year, month, date, hours, minutes, seconds, milliseconds, reading arguments in that order,"
|
62
|
-
"where hours, minutes, seconds, and milliseconds are optional")
|
64
|
+
"where hours, minutes, seconds, and milliseconds are optional") 'args nil '(date-time))
|
63
65
|
(dox-add-doc 'thread-locals 'def '("return a hash bound to the current thread") nil nil '(nydp-core))
|
64
66
|
(dox-add-doc 'type-of 'def '("return a symbol for the type of 'arg") '(arg) nil '(nydp-core))
|
65
67
|
(dox-add-doc 'eq? 'def '("return 't if 'arg-0 and 'arg-1 are equal, nil otherwise") '(arg-0 arg-1) nil '(nydp-core))
|
@@ -1,4 +1,4 @@
|
|
1
|
-
(assign script-name "core-
|
1
|
+
(assign script-name "core-020-utils.nydp")
|
2
2
|
|
3
3
|
(dox-add-doc 'if
|
4
4
|
'mac
|
@@ -43,12 +43,12 @@
|
|
43
43
|
'(hash-set h k (cons v (hash-get h k)))
|
44
44
|
'(hash-manipulation))
|
45
45
|
|
46
|
+
;; equivalent to (join-str "~prefix~joint~(car things)" joint (cdr things)) - except
|
47
|
+
;; 'string-pieces hasn't been defined yet, and if it were, it would be defined in terms of
|
48
|
+
;; 'join-str, so it would be circular.
|
49
|
+
;; see 'joinstr for a more powerful and easier-to-use implementation of the same idea
|
46
50
|
(def join-str (prefix joint things)
|
47
51
|
(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
52
|
(if things
|
53
53
|
(join-str (+ (to-string prefix)
|
54
54
|
joint
|
@@ -21,16 +21,26 @@ scoping, assignment, anonymous functions and more...")
|
|
21
21
|
(apply orf
|
22
22
|
(cdr args)))))
|
23
23
|
|
24
|
+
; returns true if 'things is a list and the first item of the
|
25
|
+
; list is the given object
|
24
26
|
(def caris (obj things)
|
25
|
-
; returns true if 'things is a list and the first item of the
|
26
|
-
; list is the given object
|
27
27
|
(and (pair? things)
|
28
|
-
(eq? (car things)
|
28
|
+
(eq? (car things) obj)))
|
29
29
|
|
30
|
+
; evaluate 'body if 'arg is nil
|
30
31
|
(mac unless (arg . body)
|
31
|
-
; evaluate 'body if 'arg is nil
|
32
32
|
`(if (no ,arg) (do ,@body)))
|
33
33
|
|
34
|
+
; looks up a key in @
|
35
|
+
; assumes local lexical context has defined a hash called '@
|
36
|
+
(mac prefix-at-syntax (name . names)
|
37
|
+
`(hash-get @ ',name))
|
38
|
+
|
39
|
+
(mac at-syntax names
|
40
|
+
(if (eq? (car names) '||)
|
41
|
+
`(prefix-at-syntax ,@(cdr names))
|
42
|
+
(error "unknown at-syntax: expected prefix-syntax (eg @name), got ~(join-str (car names) "@" (cdr names))")))
|
43
|
+
|
34
44
|
(def expand-colon-syntax (names)
|
35
45
|
(if (no (cdr names))
|
36
46
|
`(apply ,(car names) args)
|
@@ -84,13 +94,17 @@ scoping, assignment, anonymous functions and more...")
|
|
84
94
|
(cons (list (car things) (cadr things))
|
85
95
|
(pairs (cddr things)))))
|
86
96
|
|
97
|
+
;; like 'let, but creates and assigns multiple local variables.
|
98
|
+
;; for example, "(with (a 1 b 2) (+ a b))" returns 3
|
87
99
|
(mac with (parms . body)
|
88
|
-
|
89
|
-
|
90
|
-
|
100
|
+
`((fun ,(map car (pairs parms))
|
101
|
+
,@body)
|
102
|
+
,@(map cadr (pairs parms))))
|
91
103
|
|
104
|
+
;; create a lexical scope
|
105
|
+
;; where val is assigned to var, execute 'body in that scope
|
92
106
|
(mac let (var val . body)
|
93
|
-
|
107
|
+
`((fun (,var) ,@body) ,val))
|
94
108
|
|
95
109
|
(mac rfn (name parms . body)
|
96
110
|
; creates a named, locally-scoped function
|
@@ -105,17 +119,28 @@ scoping, assignment, anonymous functions and more...")
|
|
105
119
|
; same as 'rfn, but using the name 'self
|
106
120
|
`(rfn self ,parms ,@body))
|
107
121
|
|
122
|
+
;; a mix of rfn and with; creates a locally-scoped named function with
|
123
|
+
;; the given parameter names, and invokes it with the given parameter
|
124
|
+
;; values. It is possible to reference the function by its name from
|
125
|
+
;; within the function (to pass as an argument or for recursive
|
126
|
+
;; invocation)
|
108
127
|
(mac rfnwith (name params . body)
|
109
|
-
; a mix of rfn and with; creates a locally-scoped named function with
|
110
|
-
; the given parameter names, and invokes it with the given parameter
|
111
|
-
; values. It is possible to reference the function by its name from
|
112
|
-
; within the function (to pass as an argument or for recursive
|
113
|
-
; invocation)
|
114
128
|
(let ppairs (pairs params)
|
115
129
|
`(let ,name nil
|
116
130
|
(assign ,name (fun ,(map car ppairs) ,@body))
|
117
131
|
(,name ,@(map cadr ppairs)))))
|
118
132
|
|
133
|
+
;; (andify a b c) is equivalent to
|
134
|
+
;; (fn args (and (apply a args) (apply b args) (apply c args)))
|
135
|
+
;; or more simply
|
136
|
+
;; (fn (x) (and (a x) (b x) (c x)))
|
137
|
+
;; note: alias as 'andf ??
|
138
|
+
(def andify args
|
139
|
+
(fn args2 (rfnwith self (ands args)
|
140
|
+
(if ands (if (apply (car ands) args2)
|
141
|
+
(self (cdr ands)))
|
142
|
+
t))))
|
143
|
+
|
119
144
|
(let uniq-counter 0
|
120
145
|
(def uniq (prefix)
|
121
146
|
(assign uniq-counter (+ uniq-counter 1))
|
@@ -123,9 +148,9 @@ scoping, assignment, anonymous functions and more...")
|
|
123
148
|
(def reset-uniq-counter ()
|
124
149
|
(assign uniq-counter 0)))
|
125
150
|
|
151
|
+
;; creates a lexical scope with a unique symbol assigned to
|
152
|
+
;; each variable in 'vars ; executes the 'body.
|
126
153
|
(mac w/uniq (vars . body)
|
127
|
-
; creates a lexical scope with a unique symbol assigned to
|
128
|
-
; each variable in 'vars ; executes the 'body.
|
129
154
|
(if (pair? vars)
|
130
155
|
`(with ,(apply + (map (fn (n) `(,n (uniq ',n))) vars))
|
131
156
|
,@body)
|
@@ -194,37 +219,79 @@ scoping, assignment, anonymous functions and more...")
|
|
194
219
|
(and (pair? name)
|
195
220
|
(caris 'ampersand-syntax (car name))))
|
196
221
|
|
222
|
+
;; (= (&key (expr)) (val))
|
223
|
+
;; (= ((ampersand-syntax key) (expr)) (val))
|
224
|
+
;; 'place is ((ampersand-syntax || key) (expr))
|
225
|
+
;; we need (hash-set (expr) 'key (val))
|
226
|
+
;; however,
|
227
|
+
;; (= (&key.subkey (expr)) (val))
|
228
|
+
;; 'place is ((ampersand-syntax || (dot-syntax key subkey)) (expr))
|
229
|
+
;; we need (hash-set (hash-get (expr) 'key) 'subkey (val))
|
197
230
|
(def ampersand-expression-assignment (place value)
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
(
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
(
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
(
|
226
|
-
|
227
|
-
|
231
|
+
(let k (cadr:cdar place)
|
232
|
+
(let hsh (cadr place)
|
233
|
+
(if (caris 'dot-syntax k)
|
234
|
+
(dot-syntax-assignment (cons hsh (cdr k)) value)
|
235
|
+
`(hash-set ,hsh ',k ,value)))))
|
236
|
+
|
237
|
+
;; used internally by 'destructuring-assign
|
238
|
+
(def destructuring-assigns (names values acc)
|
239
|
+
(if names
|
240
|
+
(if (pair? names)
|
241
|
+
(destructuring-assigns
|
242
|
+
(cdr names)
|
243
|
+
`(cdr ,values)
|
244
|
+
(cons `(= ,(car names) (car ,values)) acc))
|
245
|
+
(cons `(= ,names ,values) acc))
|
246
|
+
(rev acc)))
|
247
|
+
|
248
|
+
;; used internally by 'assign-expr
|
249
|
+
(def destructuring-assign (name value)
|
250
|
+
(w/uniq destructuring-assign
|
251
|
+
`(let ,destructuring-assign ,value
|
252
|
+
,@(destructuring-assigns name destructuring-assign))))
|
253
|
+
|
254
|
+
;; used internally by '= macro
|
255
|
+
(def assign-expr (nv)
|
256
|
+
(let name (car nv)
|
257
|
+
(let value (cadr nv)
|
258
|
+
(if (isa 'symbol name)
|
259
|
+
`(assign ,name ,value)
|
260
|
+
(caris 'dot-syntax name)
|
261
|
+
(dot-syntax-assignment (cdr name) value)
|
262
|
+
(caris 'hash-get name)
|
263
|
+
(hash-get-assignment (cdr name) value)
|
264
|
+
(ampersand-expression? name)
|
265
|
+
(ampersand-expression-assignment name value)
|
266
|
+
(caris 'at-syntax name)
|
267
|
+
`(hash-set @ ',(caddr name) ,value)
|
268
|
+
(pair? name)
|
269
|
+
(destructuring-assign name value)
|
270
|
+
(error "unknown assignment to place: " (inspect name))))))
|
271
|
+
|
272
|
+
;; generic assignment which unlike builtin 'assign, knows how to assign
|
273
|
+
;; to hash keys
|
274
|
+
;; (= (hash-get (expr) 'key) (val) => (hash-set (expr) 'key (val))
|
275
|
+
;; (= h.k (val)) => (hash-set h 'k (val))
|
276
|
+
;; (= h.j.k (val)) => (hash-set (hash-get h 'j) 'k (val))
|
277
|
+
;; (= (&key (expr)) (val)) => (hash-set (expr) 'key (val))
|
278
|
+
;; (= (&j.k (expr)) (val)) => (hash-set (hash-get (expr) 'j) 'k (val))
|
279
|
+
(mac = assignments
|
280
|
+
`(do ,@(map assign-expr (pairs assignments))))
|
281
|
+
|
282
|
+
;; like 'let, but creates and assigns multiple local variables.
|
283
|
+
;; for example, "(with (a 1 b 2) (+ a b))" returns 3
|
284
|
+
;;
|
285
|
+
;; later variables can references earlier ones:
|
286
|
+
;; (with (a 1 b 2 c (+ a b)) (list a b c)) ;; returns (1 2 3)
|
287
|
+
(mac with (assignments . body)
|
288
|
+
`((fun ,(map car (pairs assignments))
|
289
|
+
(= ,@assignments)
|
290
|
+
,@body) nil))
|
291
|
+
|
292
|
+
;; quiet assignment ; like =, but expression returns nil
|
293
|
+
(mac #= (name value)
|
294
|
+
`(do (= ,name ,value) nil))
|
228
295
|
|
229
296
|
; increment the value at 'place by 'inc (default 1)
|
230
297
|
(mac ++ (place inc) `(= ,place (+ ,place ,(or inc 1))))
|
@@ -283,16 +350,25 @@ scoping, assignment, anonymous functions and more...")
|
|
283
350
|
; (eg hash), the mutated value will be returned. See also 'returnlet
|
284
351
|
(mac returning (val . body) (w/uniq retval `(returnlet ,retval ,val ,@body)))
|
285
352
|
|
286
|
-
(mac
|
287
|
-
|
288
|
-
|
289
|
-
; source: arc.arc
|
290
|
-
`(let it ,expr
|
291
|
-
(if it
|
353
|
+
(mac ifv (var expr . body)
|
354
|
+
`(let ,var ,expr
|
355
|
+
(if ,var
|
292
356
|
,@(if (cddr body)
|
293
|
-
`(,(car body) (
|
357
|
+
`(,(car body) (ifv ,var ,@(cdr body)))
|
294
358
|
body))))
|
295
359
|
|
360
|
+
; like if, except the value of each condition is locally bound to the variable 'it
|
361
|
+
; eg (aif (find thing) (show it))
|
362
|
+
; source: arc.arc
|
363
|
+
(mac aif (expr . body)
|
364
|
+
`(ifv it ,expr ,@body))
|
365
|
+
|
366
|
+
;; returns the n-th item in the list 'things
|
367
|
+
(def nth (n things)
|
368
|
+
(if (eq? n 0)
|
369
|
+
(car things)
|
370
|
+
(nth (- n 1) (cdr things))))
|
371
|
+
|
296
372
|
(def destructure/with (var args n)
|
297
373
|
; provides the argument expression to 'with when
|
298
374
|
; destructuring arguments are present in a 'fun definition
|
@@ -301,34 +377,52 @@ scoping, assignment, anonymous functions and more...")
|
|
301
377
|
args
|
302
378
|
`(,args (nthcdr ,n ,var))))
|
303
379
|
|
304
|
-
|
305
|
-
|
380
|
+
;; issue a warning if any arg name is the name of a macro
|
381
|
+
(def fun/approve-arg-names (orig args body)
|
382
|
+
(if (pair? args)
|
383
|
+
(do (fun/approve-arg-names orig (car args) body)
|
384
|
+
(fun/approve-arg-names orig (cdr args) body))
|
385
|
+
args
|
386
|
+
(if (hash-get macs args)
|
387
|
+
(warnings/new 'arg-shadows-macro "arg " args " shadows macro " args " in arg list " orig " and body " body))))
|
388
|
+
|
389
|
+
;; used internally by 'fun
|
390
|
+
(def destructure/build (given-args new-args body next)
|
306
391
|
(if (pair? given-args)
|
307
392
|
(if (sym? (car given-args))
|
308
393
|
(destructure/build (cdr given-args)
|
309
394
|
(cons (car given-args) new-args)
|
310
|
-
body
|
395
|
+
body
|
396
|
+
next)
|
311
397
|
(w/uniq destructure
|
312
398
|
(destructure/build (cdr given-args)
|
313
399
|
(cons destructure new-args)
|
314
|
-
`((with ,(destructure/with destructure (car given-args) 0) ,@body))
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
(def fun/
|
319
|
-
(
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
400
|
+
`((with ,(destructure/with destructure (car given-args) 0) ,@body))
|
401
|
+
next)))
|
402
|
+
(next (rev new-args given-args) body)))
|
403
|
+
|
404
|
+
(def fun/destructuring-args (args body next)
|
405
|
+
(fun/approve-arg-names args args body)
|
406
|
+
(destructure/build args nil body next))
|
407
|
+
|
408
|
+
(assign fun/expanders
|
409
|
+
(list
|
410
|
+
(cons 'destructuring-args fun/destructuring-args)
|
411
|
+
(cons 'core-builder (fn (args body next) `(fn ,args ,@body)))))
|
412
|
+
|
413
|
+
(def fun/expand (args body expanders)
|
414
|
+
(if expanders
|
415
|
+
((cdar expanders)
|
416
|
+
args
|
417
|
+
body
|
418
|
+
(fn (a b)
|
419
|
+
(fun/expand a b (cdr expanders))))))
|
420
|
+
|
421
|
+
;; build a 'fn form, changing 'args and 'body to
|
422
|
+
;; properly handle any destructuring args if present
|
326
423
|
(mac fun (args . body)
|
327
|
-
|
328
|
-
; properly handle any destructuring args if present
|
329
|
-
(fun/approve-arg-names args args)
|
330
|
-
(destructure/build args nil body))
|
424
|
+
(fun/expand args body fun/expanders))
|
331
425
|
|
332
|
-
|
426
|
+
;; assign (f place) to place
|
333
427
|
(mac zap (f place . args)
|
334
428
|
`(= ,place (,f ,place ,@args)))
|