nydp 0.4.0 → 0.4.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +44 -0
- data/lib/lisp/core-010-precompile.nydp +13 -16
- data/lib/lisp/core-012-utils.nydp +21 -6
- data/lib/lisp/core-015-documentation.nydp +60 -19
- data/lib/lisp/core-017-builtin-dox.nydp +50 -39
- data/lib/lisp/core-020-utils.nydp +5 -5
- data/lib/lisp/core-030-syntax.nydp +103 -61
- data/lib/lisp/core-035-flow-control.nydp +18 -9
- data/lib/lisp/core-037-list-utils.nydp +36 -14
- data/lib/lisp/core-039-module.nydp +24 -0
- data/lib/lisp/core-040-utils.nydp +41 -23
- data/lib/lisp/core-041-string-utils.nydp +37 -9
- data/lib/lisp/core-042-date-utils.nydp +21 -1
- data/lib/lisp/core-043-list-utils.nydp +93 -67
- data/lib/lisp/core-045-dox-utils.nydp +5 -0
- data/lib/lisp/core-080-pretty-print.nydp +55 -17
- data/lib/lisp/core-090-hook.nydp +35 -1
- data/lib/lisp/core-100-utils.nydp +130 -28
- data/lib/lisp/core-110-hash-utils.nydp +61 -0
- data/lib/lisp/core-120-settings.nydp +46 -0
- data/lib/lisp/core-130-validations.nydp +51 -0
- data/lib/lisp/{core-060-benchmarking.nydp → core-900-benchmarking.nydp} +108 -5
- 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/cdr-set-examples.nydp +6 -0
- data/lib/lisp/tests/date-examples.nydp +56 -1
- data/lib/lisp/tests/destructuring-examples.nydp +5 -5
- data/lib/lisp/tests/detect-examples.nydp +12 -0
- data/lib/lisp/tests/dp-examples.nydp +24 -0
- data/lib/lisp/tests/empty-examples.nydp +1 -1
- data/lib/lisp/tests/error-tests.nydp +4 -4
- data/lib/lisp/tests/filter-forms-examples.nydp +30 -0
- data/lib/lisp/tests/foundation-test.nydp +12 -0
- data/lib/lisp/tests/hash-examples.nydp +26 -2
- 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/mapreduce-examples.nydp +10 -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 +21 -0
- data/lib/lisp/tests/pretty-print-tests.nydp +16 -13
- data/lib/lisp/tests/set-difference-examples.nydp +8 -0
- data/lib/lisp/tests/set-intersection-examples.nydp +32 -0
- data/lib/lisp/tests/set-union-examples.nydp +24 -0
- data/lib/lisp/tests/settings-examples.nydp +40 -0
- data/lib/lisp/tests/sort-examples.nydp +8 -0
- data/lib/lisp/tests/string-tests.nydp +61 -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/lisp/tests/zap-examples.nydp +12 -0
- data/lib/nydp.rb +13 -7
- 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/cdr_set.rb +1 -6
- data/lib/nydp/builtin/date.rb +15 -1
- data/lib/nydp/builtin/error.rb +1 -1
- data/lib/nydp/builtin/handle_error.rb +1 -1
- data/lib/nydp/builtin/hash.rb +27 -45
- data/lib/nydp/builtin/inspect.rb +1 -1
- data/lib/nydp/builtin/plus.rb +10 -2
- data/lib/nydp/builtin/rand.rb +18 -0
- data/lib/nydp/builtin/random_string.rb +2 -2
- data/lib/nydp/builtin/ruby_wrap.rb +72 -0
- data/lib/nydp/builtin/set_intersection.rb +8 -0
- data/lib/nydp/builtin/set_union.rb +8 -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 +1 -1
- data/lib/nydp/builtin/string_split.rb +1 -2
- 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 +45 -33
- data/lib/nydp/core_ext.rb +54 -0
- data/lib/nydp/date.rb +37 -31
- data/lib/nydp/function_invocation.rb +34 -26
- data/lib/nydp/hash.rb +5 -6
- data/lib/nydp/helper.rb +41 -25
- data/lib/nydp/interpreted_function.rb +68 -40
- data/lib/nydp/literal.rb +1 -1
- data/lib/nydp/pair.rb +25 -9
- data/lib/nydp/parser.rb +8 -6
- data/lib/nydp/string_atom.rb +16 -22
- data/lib/nydp/symbol.rb +40 -27
- data/lib/nydp/symbol_lookup.rb +7 -7
- data/lib/nydp/tokeniser.rb +2 -2
- data/lib/nydp/truth.rb +17 -10
- data/lib/nydp/version.rb +1 -1
- data/lib/nydp/vm.rb +7 -2
- data/nydp.gemspec +2 -4
- data/spec/date_spec.rb +115 -22
- 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/parser_spec.rb +27 -16
- data/spec/rand_spec.rb +45 -0
- data/spec/spec_helper.rb +13 -1
- data/spec/symbol_spec.rb +31 -0
- data/spec/time_spec.rb +1 -1
- metadata +38 -37
- data/lib/nydp/builtin/car.rb +0 -7
- 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
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '06876fcb6832d6737b4763607cfe7b4c0ca003c3'
|
4
|
+
data.tar.gz: b45d30570c913940f93585241c1dad9cc71c5872
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d874e4fbbba55a5995f699451bbf305fe7667f4058cdab2e713fe64900bc96ed285fe5ae8d0c460c73001f0a44fb22699c634c2017a723e9c79d818779d38b7e
|
7
|
+
data.tar.gz: 5d5f3aeb4e7c0e65af1024990fdfa5f73a8f4657a06dfd11aaeec172709615a3879f0bdff0efd19475a223add58ee1dd6379951548979eda5b80f30861967e61
|
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,16 +8,31 @@
|
|
8
8
|
(car args))
|
9
9
|
nil)))
|
10
10
|
|
11
|
-
(def map (f things)
|
12
|
-
; transforms the list 'things by applying 'f to each item
|
13
|
-
; returns the resulting list
|
11
|
+
(def map-helper-0 (f things lc)
|
14
12
|
(if (pair? things)
|
15
|
-
(
|
13
|
+
(map-helper-0 f (cdr things) (cdr-set lc (cons (f (car things)))))
|
16
14
|
things
|
17
|
-
(f things)))
|
15
|
+
(cdr-set lc (f things))))
|
16
|
+
|
17
|
+
(def map-helper-1 (f things acc)
|
18
|
+
(map-helper-0 f things acc)
|
19
|
+
(cdr acc))
|
20
|
+
|
21
|
+
;; transforms the list 'things by applying 'f to each item, returns the resulting list
|
22
|
+
;; conceptually, does the following:
|
23
|
+
;;
|
24
|
+
;; (if (pair? things)
|
25
|
+
;; (cons (f (car things)) (map f (cdr things)))
|
26
|
+
;; things
|
27
|
+
;; (f things))
|
28
|
+
;;
|
29
|
+
;; however the actual version is more complicated to allow for TCO ("modulo-cons" issue)
|
30
|
+
(def map (f things)
|
31
|
+
(map-helper-1 f things (cons)))
|
18
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
|
19
35
|
(def hash-cons (h k v)
|
20
|
-
; push 'v onto the value for 'k in 'h
|
21
36
|
(hash-set h k (cons v (hash-get h k))))
|
22
37
|
|
23
38
|
(def rev (things last-cdr)
|
@@ -1,5 +1,28 @@
|
|
1
1
|
(def privately () nil)
|
2
2
|
|
3
|
+
(assign comments nil)
|
4
|
+
|
5
|
+
(def fetch-and-clear-comments ()
|
6
|
+
((fn (c) (assign comments nil) c) (rev comments)))
|
7
|
+
|
8
|
+
(def filter-comments (form acc)
|
9
|
+
(if (no form)
|
10
|
+
(rev acc)
|
11
|
+
(pair? form)
|
12
|
+
(filter-comments (cdr form)
|
13
|
+
(if (if (pair? (car form))
|
14
|
+
(eq? (caar form)
|
15
|
+
'comment))
|
16
|
+
acc
|
17
|
+
(cons (filter-comments (car form)
|
18
|
+
nil)
|
19
|
+
acc)))
|
20
|
+
form))
|
21
|
+
|
22
|
+
(hash-set macs 'do
|
23
|
+
(fn forms
|
24
|
+
`((fn nil ,@forms))))
|
25
|
+
|
3
26
|
((fn (this-chapter-name chapters chapter-new chapter-build chapter-add-to-chapter)
|
4
27
|
(assign chapters (hash))
|
5
28
|
|
@@ -45,7 +68,7 @@
|
|
45
68
|
(assign this-script nil)
|
46
69
|
(assign this-plugin "Nydp Core")
|
47
70
|
|
48
|
-
((fn (dox examples chapters dox-new dox-build)
|
71
|
+
((fn (dox examples chapters types types-chapters dox-new dox-build)
|
49
72
|
(def dox-build (hsh name what texts args src chapters)
|
50
73
|
(hash-set hsh 'name name )
|
51
74
|
(hash-set hsh 'what what )
|
@@ -59,26 +82,38 @@
|
|
59
82
|
|
60
83
|
(def dox-new (item)
|
61
84
|
(hash-cons dox (hash-get item 'name) item)
|
62
|
-
(
|
85
|
+
(hash-cons types (hash-get item 'what) item)
|
86
|
+
(dox-add-to-chapters item (hash-get item 'what) (hash-get item 'chapters) (hash)))
|
63
87
|
|
64
88
|
(def dox-add-doc (name what texts args src chapters more)
|
65
89
|
(cond (no (privately))
|
66
90
|
(dox-new (dox-build (if more more (hash)) name what texts args src chapters))))
|
67
91
|
|
68
|
-
(def dox-add-to-chapters (item chapters)
|
92
|
+
(def dox-add-to-chapters (item type chapters already)
|
69
93
|
(cond chapters
|
70
|
-
|
71
|
-
|
94
|
+
(cond (no (hash-get already (car chapters)))
|
95
|
+
(do (hash-set already (car chapters) t)
|
96
|
+
(chapter-add-item item (car chapters))
|
97
|
+
(hash-cons types-chapters (inspect (cons type (car chapters))) item)
|
98
|
+
(dox-add-to-chapters item type (cdr chapters) already))
|
99
|
+
item)
|
72
100
|
item))
|
73
101
|
|
74
102
|
(def dox-add-examples (name example-exprs)
|
75
103
|
(hash-cons examples name example-exprs))
|
76
104
|
|
77
|
-
(def dox-lookup (
|
105
|
+
(def dox-lookup (name) (hash-get dox name))
|
78
106
|
|
79
107
|
(def dox? (sym) (hash-key? dox sym))
|
80
108
|
|
81
109
|
(def dox-names () (hash-keys dox))
|
110
|
+
(def dox-types () (hash-keys types))
|
111
|
+
(def dox-items-by-type (type) (hash-get types type))
|
112
|
+
|
113
|
+
(def get-types-chapters () types-chapters)
|
114
|
+
|
115
|
+
(def dox-items-by-type-and-chapter (dox-type chapter)
|
116
|
+
(hash-get types-chapters (inspect (cons dox-type chapter))))
|
82
117
|
|
83
118
|
(def dox-get-attr (name attr)
|
84
119
|
(cond (dox? name)
|
@@ -89,7 +124,7 @@
|
|
89
124
|
(def dox-examples (name) (hash-get examples name ))
|
90
125
|
(def dox-args (name) (dox-get-attr name 'args ))
|
91
126
|
(def dox-example-names () (hash-keys examples )))
|
92
|
-
(hash) (hash) (hash) nil)
|
127
|
+
(hash) (hash) (hash) (hash) (hash) nil)
|
93
128
|
|
94
129
|
(def plugin-start (name) (assign this-plugin name) (chapter-end))
|
95
130
|
(def plugin-end (name) (assign this-plugin nil ) (chapter-end))
|
@@ -106,9 +141,9 @@
|
|
106
141
|
(cond (eq? event 'script-end)
|
107
142
|
(script-end name))))))
|
108
143
|
|
144
|
+
;; if the car of 'form is a key of 'hsh, add the cdr of 'form to the value of the key in 'hsh
|
145
|
+
;; otherwise add the form to the list whose key is nil
|
109
146
|
(def filter-form (hsh form)
|
110
|
-
; if the car of 'form is a key of 'hsh, add the cdr of 'form to the value of the key in 'hsh
|
111
|
-
; otherwise add the form to the list whose key is nil
|
112
147
|
(cond (cond (pair? form)
|
113
148
|
(hash-key? hsh (car form)))
|
114
149
|
(hash-cons hsh (car form) (cdr form))
|
@@ -127,9 +162,9 @@
|
|
127
162
|
(def rev-values (hsh)
|
128
163
|
(rev-value-keys (hash-keys hsh) hsh (hash)))
|
129
164
|
|
165
|
+
;; group forms by their first element, if the first element
|
166
|
+
;; is already a key in hsh, collect all other elements under key nil
|
130
167
|
(def filter-forms (hsh forms)
|
131
|
-
; group forms by their first element, if the first element
|
132
|
-
; is already a key in hsh, collect all other elements under key nil
|
133
168
|
(cond forms
|
134
169
|
(filter-forms (filter-form hsh (car forms)) (cdr forms))
|
135
170
|
(rev-values hsh)))
|
@@ -139,12 +174,14 @@
|
|
139
174
|
(hash-set hsh 'chapter nil)
|
140
175
|
hsh)
|
141
176
|
|
177
|
+
(def dox-build-def-name (name) name)
|
178
|
+
|
179
|
+
;; used internally by 'mac
|
142
180
|
(def define-mac-expr (name args body-forms)
|
143
|
-
; used internally by 'mac
|
144
181
|
`(do (hash-set macs ',name (fun ,args ,@(hash-get body-forms nil)))
|
145
|
-
(dox-add-doc ',name
|
182
|
+
(dox-add-doc ',(dox-build-def-name name)
|
146
183
|
'mac
|
147
|
-
',(map car (hash-get body-forms 'comment))
|
184
|
+
',(+ (fetch-and-clear-comments) (map car (hash-get body-forms 'comment)))
|
148
185
|
',args
|
149
186
|
'(mac ,name ,args ,@(hash-get body-forms nil))
|
150
187
|
',(map car (hash-get body-forms 'chapter)))))
|
@@ -169,17 +206,21 @@
|
|
169
206
|
|
170
207
|
(mac def-assign args `(assign ,@args))
|
171
208
|
|
209
|
+
;; used internally by 'def
|
172
210
|
(def define-def-expr (name args body-forms)
|
173
|
-
|
174
|
-
|
175
|
-
(dox-add-doc ',name
|
211
|
+
`(do (def-assign ,name (fun ,args ,@(filter-comments (hash-get body-forms nil))))
|
212
|
+
(dox-add-doc ',(dox-build-def-name name)
|
176
213
|
'def
|
177
|
-
',(map car (hash-get body-forms 'comment))
|
214
|
+
',(+ (fetch-and-clear-comments) (map car (hash-get body-forms 'comment)))
|
178
215
|
',args
|
179
216
|
'(def ,name ,args ,@(hash-get body-forms nil))
|
180
217
|
',(map car (hash-get body-forms 'chapter)))))
|
181
218
|
|
219
|
+
;; define a new function in the global namespace
|
182
220
|
(mac def (name args . body)
|
183
|
-
; define a new function in the global namespace
|
184
221
|
(chapter nydp-core)
|
185
222
|
(define-def-expr name args (filter-forms (build-def-hash (hash)) body)))
|
223
|
+
|
224
|
+
(mac comment (txt)
|
225
|
+
(assign comments (cons txt comments))
|
226
|
+
nil)
|
@@ -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,18 +36,21 @@
|
|
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
|
-
(dox-add-doc '
|
45
|
-
|
46
|
-
|
47
|
-
(dox-add-doc 'string
|
48
|
-
(dox-add-doc 'string
|
49
|
-
(dox-add-doc 'string-
|
45
|
+
(dox-add-doc 'rand 'def '("return a random number ; with no args, between 0 and 1"
|
46
|
+
"with 1 arg, an integer less than arg"
|
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 'to-string 'def '("return a human-readable string representation of 'arg") '(arg) nil '(string-manipulation))
|
50
|
+
(dox-add-doc 'string-length 'def '("return the length of 'arg") '(arg) nil '(string-manipulation))
|
51
|
+
(dox-add-doc 'string-replace 'def '("replace 'pattern with 'replacement in 'str") '(pattern replacement str) nil '(string-manipulation))
|
52
|
+
(dox-add-doc 'string-split 'def '("split 'str delimited by 'delim") '(str delim) nil '(string-manipulation))
|
53
|
+
(dox-add-doc 'string-match 'def '("if 'str matches 'pattern, return hash with keys 'match and 'captures ; otherwise nil") '(str pattern) nil '(string-manipulation))
|
50
54
|
(dox-add-doc 'time 'def '("with no args, return the current time."
|
51
55
|
"With one arg, if 'arg-0 is a number, return the current time plus 'arg-0 seconds."
|
52
56
|
"With one arg, if 'arg-0 is a date, return the time at the beginning of the given date."
|
@@ -54,35 +58,42 @@
|
|
54
58
|
"With two args, 'arg-0 must be a time."
|
55
59
|
"If 'arg-1 is a number, return 'arg-0 plus 'arg-1 seconds as a time object."
|
56
60
|
"If 'arg-1 is a time, return the number of seconds between the two (- 'arg-0 arg-1)."
|
57
|
-
"Otherwise, expect 3
|
61
|
+
"Otherwise, expect 3 or more args, to construct a time from"
|
58
62
|
"year, month, date, hours, minutes, seconds, milliseconds, reading arguments in that order,"
|
59
|
-
"where hours, minutes, seconds, and milliseconds are optional")
|
60
|
-
(dox-add-doc 'thread-locals
|
61
|
-
(dox-add-doc 'type-of
|
62
|
-
(dox-add-doc 'eq?
|
63
|
-
(dox-add-doc 'cdr-set
|
64
|
-
(dox-add-doc 'hash-get
|
65
|
-
(dox-add-doc 'hash-set
|
66
|
-
(dox-add-doc 'hash-keys
|
67
|
-
(dox-add-doc 'hash-key?
|
68
|
-
(dox-add-doc 'hash-merge
|
69
|
-
(dox-add-doc 'vm-info
|
70
|
-
(dox-add-doc 'pre-compile
|
71
|
-
(dox-add-doc 'script-run
|
72
|
-
|
73
|
-
|
63
|
+
"where hours, minutes, seconds, and milliseconds are optional") 'args nil '(date-time))
|
64
|
+
(dox-add-doc 'thread-locals 'def '("return a hash bound to the current thread") nil nil '(nydp-core))
|
65
|
+
(dox-add-doc 'type-of 'def '("return a symbol for the type of 'arg") '(arg) nil '(nydp-core))
|
66
|
+
(dox-add-doc 'eq? 'def '("return 't if 'arg-0 and 'arg-1 are equal, nil otherwise") '(arg-0 arg-1) nil '(nydp-core))
|
67
|
+
(dox-add-doc 'cdr-set 'def '("set the cdr of the given 'cell to 'arg, returns 'cell") '(cell arg) nil '(list-manipulation))
|
68
|
+
(dox-add-doc 'hash-get 'def '("return the value stored by 'key in 'hsh") '(hsh key) nil '(hash-manipulation))
|
69
|
+
(dox-add-doc 'hash-set 'def '("store 'val under 'key in 'hsh, return 'val") '(hsh key val) nil '(hash-manipulation))
|
70
|
+
(dox-add-doc 'hash-keys 'def '("return the list of keys in 'hsh") '(hsh) nil '(hash-manipulation))
|
71
|
+
(dox-add-doc 'hash-key? 'def '("return 't if 'key is a key of 'hsh") '(hsh key) nil '(hash-manipulation))
|
72
|
+
(dox-add-doc 'hash-merge 'def '("return a new hash containing keys and values from 'h0 and 'h1, where values of 'h1 override values of 'h0") '(h0 h1) nil '(hash-manipulation))
|
73
|
+
(dox-add-doc 'vm-info 'def '("return some information about the state of the current thread") nil nil '(nydp-core))
|
74
|
+
(dox-add-doc 'pre-compile 'def '("transform parsed forms before the compile and eval stages") '(arg) nil '(nydp-compilation))
|
75
|
+
(dox-add-doc 'script-run 'def '("announces the start of a plugin load or a script load."
|
76
|
+
"'event may be one of '(script-start script-end plugin-start plugin-end)"
|
77
|
+
"'name is the name of the script or plugin concerned") '(event name) nil '(nydp-core))
|
74
78
|
|
75
|
-
(dox-add-doc 'chapter-end
|
76
|
-
(dox-add-doc 'chapter-start
|
77
|
-
(dox-add-doc 'chapter-names
|
78
|
-
(dox-add-doc 'chapter-current
|
79
|
-
(dox-add-doc 'chapter-delete
|
80
|
-
(dox-add-doc 'chapter-find
|
81
|
-
(dox-add-doc '
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
79
|
+
(dox-add-doc 'chapter-end 'def '("Announce the end of a chapter. Called by 'plugin-start, 'plugin-end, 'script-start, 'script-end") nil nil '(nydp/documentation))
|
80
|
+
(dox-add-doc 'chapter-start 'def '("Announce the start of a chapter. Creates a new chapter if the named chapter does not already exist") '(chapter-name description) nil '(nydp/documentation))
|
81
|
+
(dox-add-doc 'chapter-names 'def '("Get the names of all the chapters nydp knows about") nil nil '(nydp/documentation))
|
82
|
+
(dox-add-doc 'chapter-current 'def '("Get the name of the chapter in progress right now - this is normally the last value sent to 'chapter-start") nil nil '(nydp/documentation))
|
83
|
+
(dox-add-doc 'chapter-delete 'def '("Remove the named chapter") '(name) nil '(nydp/documentation))
|
84
|
+
(dox-add-doc 'chapter-find 'def '("Get the named chapter") '(name) nil '(nydp/documentation))
|
85
|
+
(dox-add-doc 'set-intersection 'def '("return the intersection of the given lists") 'args nil '(list-manipulation))
|
86
|
+
(dox-add-doc '⋂ 'def '("return the intersection of the given lists") 'args nil '(list-manipulation))
|
87
|
+
(dox-add-doc 'set-union 'def '("return the union of the given lists") 'args nil '(list-manipulation))
|
88
|
+
(dox-add-doc '⋃ 'def '("return the union of the given lists") 'args nil '(list-manipulation))
|
89
|
+
(dox-add-doc 'dox-add-doc 'def '("Store the provided documentation item."
|
90
|
+
"'name is the name of the item"
|
91
|
+
"'what is the type of the item ('def or 'mac or 'thingy ... this is user-definable, not related to 'type-of)"
|
92
|
+
"'texts is a list of strings to store for this item"
|
93
|
+
"'args is the args if the item has the notion of args"
|
94
|
+
"'src the source code of the item if any"
|
95
|
+
"'chapters the chapters to which the item should be added, if any") '(name what texts args src chapters) nil '(nydp/documentation))
|
96
|
+
(dox-add-doc 'dox-add-examples 'def '("Add the given examples to the dox for the named item") '(name example-exprs) nil '(nydp/documentation))
|
97
|
+
(dox-add-doc 'dox-types 'def '("Get the list of types of documented items") nil nil '(nydp/documentation))
|
98
|
+
(dox-add-doc 'dox-lookup 'def '("Get the documentation for the given item") '(name) nil '(nydp/documentation))
|
99
|
+
(dox-add-doc 'dox-items-by-type 'def '("Get the list of dox items of a given type") '(type) nil '(nydp/documentation))
|
@@ -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
100
|
`((fun ,(map car (pairs parms))
|
89
101
|
,@body)
|
90
102
|
,@(map cadr (pairs parms))))
|
91
103
|
|
104
|
+
;; same as ( (fn (var) body) val ) -> ie 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
|
+
`(with (,var ,val) ,@body))
|
94
108
|
|
95
109
|
(mac rfn (name parms . body)
|
96
110
|
; creates a named, locally-scoped function
|
@@ -116,6 +130,17 @@ scoping, assignment, anonymous functions and more...")
|
|
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))
|
@@ -127,7 +152,7 @@ scoping, assignment, anonymous functions and more...")
|
|
127
152
|
; creates a lexical scope with a unique symbol assigned to
|
128
153
|
; each variable in 'vars ; executes the 'body.
|
129
154
|
(if (pair? vars)
|
130
|
-
`(with ,(apply + (map (fn (n) (
|
155
|
+
`(with ,(apply + (map (fn (n) `(,n (uniq ',n))) vars))
|
131
156
|
,@body)
|
132
157
|
`(let ,vars (uniq ',vars) ,@body)))
|
133
158
|
|
@@ -194,29 +219,23 @@ 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
|
-
; (= (&key (expr)) (val))
|
199
|
-
; (= ((ampersand-syntax key) (expr)) (val))
|
200
|
-
; 'place is ((ampersand-syntax || key) (expr))
|
201
|
-
; we need (hash-set (expr) 'key (val))
|
202
|
-
; however,
|
203
|
-
; (= (&key.subkey (expr)) (val))
|
204
|
-
; 'place is ((ampersand-syntax || (dot-syntax key subkey)) (expr))
|
205
|
-
; we need (hash-set (hash-get (expr) 'key) 'subkey (val))
|
206
231
|
(with (k (cadr:cdar place)
|
207
232
|
hsh (cadr place))
|
208
233
|
(if (caris 'dot-syntax k)
|
209
234
|
(dot-syntax-assignment (cons hsh (cdr k)) value)
|
210
235
|
`(hash-set ,hsh ',k ,value))))
|
211
236
|
|
212
|
-
|
213
|
-
|
214
|
-
; to hash keys
|
215
|
-
; (= (hash-get (expr) 'key) (val) => (hash-set (expr) 'key (val))
|
216
|
-
; (= h.k (val)) => (hash-set h 'k (val))
|
217
|
-
; (= h.j.k (val)) => (hash-set (hash-get h 'j) 'k (val))
|
218
|
-
; (= (&key (expr)) (val)) => (hash-set (expr) 'key (val))
|
219
|
-
; (= (&j.k (expr)) (val)) => (hash-set (hash-get (expr) 'j) 'k (val))
|
237
|
+
;; used internally by '= macro
|
238
|
+
(def assign-expr (name value)
|
220
239
|
(if (isa 'symbol name)
|
221
240
|
`(assign ,name ,value)
|
222
241
|
(caris 'dot-syntax name)
|
@@ -224,15 +243,35 @@ scoping, assignment, anonymous functions and more...")
|
|
224
243
|
(caris 'hash-get name)
|
225
244
|
(hash-get-assignment (cdr name) value)
|
226
245
|
(ampersand-expression? name)
|
227
|
-
(ampersand-expression-assignment name value)
|
228
|
-
|
229
|
-
(
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
246
|
+
(ampersand-expression-assignment name value)
|
247
|
+
(caris 'at-syntax name)
|
248
|
+
`(hash-set @ ',(caddr name) ,value)
|
249
|
+
(error "unknown assignment to place: ~(inspect name)")))
|
250
|
+
|
251
|
+
;; generic assignment which unlike builtin 'assign, knows how to assign
|
252
|
+
;; to hash keys
|
253
|
+
;; (= (hash-get (expr) 'key) (val) => (hash-set (expr) 'key (val))
|
254
|
+
;; (= h.k (val)) => (hash-set h 'k (val))
|
255
|
+
;; (= h.j.k (val)) => (hash-set (hash-get h 'j) 'k (val))
|
256
|
+
;; (= (&key (expr)) (val)) => (hash-set (expr) 'key (val))
|
257
|
+
;; (= (&j.k (expr)) (val)) => (hash-set (hash-get (expr) 'j) 'k (val))
|
258
|
+
(mac = (name value . more)
|
259
|
+
(if more
|
260
|
+
`(do ,(assign-expr name value) (= ,@more))
|
261
|
+
(assign-expr name value)))
|
262
|
+
|
263
|
+
;; quiet assignment ; like =, but expression returns nil
|
264
|
+
(mac #= (name value)
|
265
|
+
`(do (= ,name ,value) nil))
|
266
|
+
|
267
|
+
; increment the value at 'place by 'inc (default 1)
|
268
|
+
(mac ++ (place inc) `(= ,place (+ ,place ,(or inc 1))))
|
269
|
+
|
270
|
+
; override previous definition to allow expressions like (def hsh.foo (arg arg2) ...)
|
271
|
+
(mac def-assign args `(= ,@args))
|
272
|
+
|
273
|
+
; evaluate ,val and assign result to ,place only if ,place is already nil
|
274
|
+
(mac or= (place val) `(or ,place (= ,place ,val)))
|
236
275
|
|
237
276
|
(def brace-list-hash-key (k)
|
238
277
|
(if (isa 'symbol k) `(quote ,k)
|
@@ -259,43 +298,42 @@ scoping, assignment, anonymous functions and more...")
|
|
259
298
|
(error "Irregular '& syntax: got suffix ~(inspect (cdr rest)) in ~(join-str pfx "&" rest)")
|
260
299
|
(build-ampersand-syntax (car rest))))
|
261
300
|
|
262
|
-
|
263
|
-
|
264
|
-
arg)
|
301
|
+
; override 'brace-list-mono in order to provide a useful interpretation for "{ x }" syntax
|
302
|
+
(mac brace-list-mono (arg) arg)
|
265
303
|
|
266
|
-
|
267
|
-
|
268
|
-
'(hash))
|
304
|
+
; interprets "{ }" as new hash
|
305
|
+
(mac brace-list-empty () '(hash))
|
269
306
|
|
307
|
+
; parser expands { foo bar } to (brace-list foo bar)
|
270
308
|
(mac brace-list args
|
271
|
-
; parser expands { foo bar } to (brace-list foo bar)
|
272
309
|
(if (no args)
|
273
310
|
`(brace-list-empty)
|
274
311
|
(no (cdr args))
|
275
312
|
`(brace-list-mono ,(car args))
|
276
313
|
(brace-list-build-hash args)))
|
277
314
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
; it gets changed. See also 'returning
|
282
|
-
`(let ,var ,val ,@body ,var))
|
315
|
+
; stores ,val in ,var, executes ,@body, returns ,var. Saves a line of code at the end of
|
316
|
+
; 'let. If 'body assigns to 'var, the assigned value of 'var will be returned. See also 'returning
|
317
|
+
(mac returnlet (var val . body) `(let ,var ,val ,@body ,var))
|
283
318
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
319
|
+
; stores ,val, executes ,@body, and returns ,val. Assumes 'body is going to do something
|
320
|
+
; destructive with 'val, but you want 'val before it gets changed. Note that if 'val is mutated
|
321
|
+
; (eg hash), the mutated value will be returned. See also 'returnlet
|
322
|
+
(mac returning (val . body) (w/uniq retval `(returnlet ,retval ,val ,@body)))
|
288
323
|
|
289
|
-
(mac
|
290
|
-
|
291
|
-
|
292
|
-
; source: arc.arc
|
293
|
-
`(let it ,expr
|
294
|
-
(if it
|
324
|
+
(mac ifv (var expr . body)
|
325
|
+
`(let ,var ,expr
|
326
|
+
(if ,var
|
295
327
|
,@(if (cddr body)
|
296
|
-
`(,(car body) (
|
328
|
+
`(,(car body) (ifv ,var ,@(cdr body)))
|
297
329
|
body))))
|
298
330
|
|
331
|
+
; like if, except the value of each condition is locally bound to the variable 'it
|
332
|
+
; eg (aif (find thing) (show it))
|
333
|
+
; source: arc.arc
|
334
|
+
(mac aif (expr . body)
|
335
|
+
`(ifv it ,expr ,@body))
|
336
|
+
|
299
337
|
(def destructure/with (var args n)
|
300
338
|
; provides the argument expression to 'with when
|
301
339
|
; destructuring arguments are present in a 'fun definition
|
@@ -318,16 +356,20 @@ scoping, assignment, anonymous functions and more...")
|
|
318
356
|
`(fn ,(rev new-args given-args) ,@body)))
|
319
357
|
|
320
358
|
|
321
|
-
(def fun/approve-arg-names (orig args)
|
359
|
+
(def fun/approve-arg-names (orig args body)
|
322
360
|
(if (pair? args)
|
323
|
-
(do (fun/approve-arg-names orig (car args))
|
324
|
-
(fun/approve-arg-names orig (cdr args)))
|
361
|
+
(do (fun/approve-arg-names orig (car args) body)
|
362
|
+
(fun/approve-arg-names orig (cdr args) body))
|
325
363
|
args
|
326
364
|
(if (hash-get macs args)
|
327
|
-
(warnings/new 'arg-shadows-macro "arg " args " shadows macro " args " in arg list " orig))))
|
365
|
+
(warnings/new 'arg-shadows-macro "arg " args " shadows macro " args " in arg list " orig " and body " body))))
|
328
366
|
|
367
|
+
;; build a 'fn form, changing 'args and 'body to
|
368
|
+
;; properly handle any destructuring args if present
|
329
369
|
(mac fun (args . body)
|
330
|
-
|
331
|
-
; properly handle any destructuring args if present
|
332
|
-
(fun/approve-arg-names args args)
|
370
|
+
(fun/approve-arg-names args args body)
|
333
371
|
(destructure/build args nil body))
|
372
|
+
|
373
|
+
;; assign (f place) to place
|
374
|
+
(mac zap (f place . args)
|
375
|
+
`(= ,place (,f ,place ,@args)))
|