nydp 0.1.4 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a7f1dacf6f22c7cd5db09de064fe3cdd11a76654
4
- data.tar.gz: 530d35d6fc54b082edb788eec8ccb15078c09582
3
+ metadata.gz: 37191dabf60a754266ff7898dad970be1f0cedcd
4
+ data.tar.gz: fa74bdef9dff4ec5be87e23630064e6a9603ea13
5
5
  SHA512:
6
- metadata.gz: 84db7216bd92545097e6b0dc3f827620c45b80261d3bbdfb18e7f0dfb70dca2b5d3078dfd07be3a0ef5fa107ad2363f9cc66e94a21b1a4b8b09a40c0cb87451a
7
- data.tar.gz: 07c739e5165a3c857a43d8c2e04088562897dcede3283a9ae572620a09f24b6cf8836efcb84f8fcd0985a424c24db675c77acff178ed03a43692bd857877d82b
6
+ metadata.gz: d32cdb68d796ca1434fed7e1e5603e718f00dcadca3779e738e870308e9a4b66a64a5e0d6c5dedb2c09cb0e929fc7560f23b40e8aa32ed42ffbcb702164c3197
7
+ data.tar.gz: 762f0e8f0b52151b8e85d8b0e4221979207609587f96f061b58fb02c18d55e8a759a10642ffc67cfeb35a7fbea53b4fdd16d42c915606240059b22b4d1f4b01f
data/README.md CHANGED
@@ -65,7 +65,6 @@ After parsing its input, `'nydp` passes the result as an argument to the `pre-co
65
65
  You can override `pre-compile` to transform the expression in any way you wish. By default, the `boot.nydp` implementation of `pre-compile` performs macro-expansion.
66
66
 
67
67
 
68
-
69
68
  ```lisp
70
69
  (def pre-compile (expr)
71
70
  (map pre-compile
@@ -80,7 +79,6 @@ nydp > (pre-compile '(yoyo 42))
80
79
  ==> (do-yoyo 42)
81
80
  ```
82
81
 
83
-
84
82
  #### 2. Special symbol syntax
85
83
 
86
84
  The parser detects syntax embedded in smybol names and emits a form whose first element names the syntax used. Here's an example:
@@ -230,7 +228,7 @@ However, this doesn't need to be built-in, it can be done with macros alone. On
230
228
  (def fun (a b . others) ...)
231
229
  ```
232
230
 
233
- In this example, `'others` is either nil, or a list containing the third and subsequent arguments to the call to `'fun`. For many examples of this kind of invocation, see [invocation-tests](lib/lisp/tests/invocation-tests.nydp) in the `tests` directory.
231
+ In this example, `others` is either nil, or a list containing the third and subsequent arguments to the call to `fun`. For many examples of this kind of invocation, see [invocation-tests](lib/lisp/tests/invocation-tests.nydp) in the `tests` directory.
234
232
 
235
233
 
236
234
 
@@ -398,6 +396,37 @@ nydp > (p:pp:dox-src 'pp/find-breaks)
398
396
  The pretty-printer is still rather primitive in that it only indents according to some hard-coded rules, and according to argument-count
399
397
  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.
400
398
 
399
+ #### 11 DSLs
400
+
401
+ The `pre-compile` system (described earlier in "Macro-expansion runs in lisp") is available for implementing local, mini-languages. To do this, use `pre-compile-with`
402
+ in a macro. `pre-compile-with` expects a hash with expansion rules, and an expression to expand using these rules. For example, to build a "describe" dsl :
403
+
404
+ ```lisp
405
+ (= describe-dsl (hash))
406
+ (= describe-dsl.def (fn (a b c) `(a-special-kind-of-def ,a ,b ,c)))
407
+ (= describe-dsl.p (fn (w) `(alternative-p ,w)))
408
+
409
+ (mac describe (name expr outcome)
410
+ `(add-description ',name
411
+ (pre-compile-with describe-dsl ',expr)
412
+ ',outcome))
413
+ ```
414
+
415
+ In this example, `describe-dsl` establishes rules for expanding `def` and for `p` which will shadow their usual meanings, but only in the context
416
+ of a `describe` form.
417
+
418
+ This technique is useful to avoid cluttering the global macro-namespace with rules that are used only in a specific context. A word of warning:
419
+ if you shadow a popular name, for example `let`, `map` or `do`, you are likely to run into trouble when some non-shadowed macro inside your
420
+ dsl context expands into something you have shadowed; in this case your shadowy definitions will be used to further expand the result.
421
+
422
+ For example, if you shadow `with`, but not `let`, and then you use a `let` form within a sample of the dsl you are specifying ; the `let`
423
+ form expands into a `with` form, thinking the `with` will expand in the usual way, but in fact no, your private dsl is going to expand
424
+ this `with` in your private special way, possibly in a way that's incompatible with the form produced by `let`.
425
+
426
+ If, notwithstanding the aforementioned, the outcome works the way you expected it to, then you have the wrong kind of genius and your
427
+ license to program should be revoked.
428
+
429
+
401
430
  ## Installation
402
431
 
403
432
  Add this line to your application's Gemfile:
@@ -1,22 +1,27 @@
1
1
 
2
-
3
- (assign mac-expand (fn (macfn name body)
2
+ (assign mac-expand (fn (names macfn name body)
4
3
  (cond macfn
5
- (pre-compile (apply macfn body))
4
+ (pre-compile-with names
5
+ (apply macfn body))
6
6
  (cons name body))))
7
7
 
8
8
  (assign macs (hash))
9
9
 
10
10
  (assign pre-compile-expr
11
- (fn (name body)
12
- (mac-expand (hash-get macs name) name body)))
11
+ (fn (names name body)
12
+ (mac-expand names
13
+ (hash-get names name)
14
+ name
15
+ body)))
13
16
 
14
17
  (assign pre-compile-each
15
- (fn (args)
18
+ (fn (names args)
16
19
  (cond args
17
20
  (cond (pair? args)
18
- (cons (pre-compile (car args))
19
- (pre-compile-each (cdr args)))
21
+ (cons (pre-compile-with names
22
+ (car args))
23
+ (pre-compile-each names
24
+ (cdr args)))
20
25
  args))))
21
26
 
22
27
  (assign pre-compile-msg
@@ -25,23 +30,36 @@
25
30
  compiled))
26
31
 
27
32
  (assign pre-compile-raw
28
- (fn (arg)
33
+ (fn (names arg)
29
34
  (cond (pair? arg)
30
35
  (cond (eq? (car arg) 'quote)
31
36
  arg
32
- (pre-compile-each (pre-compile-expr (car arg) (cdr arg))))
37
+ (pre-compile-each names
38
+ (pre-compile-expr names
39
+ (car arg)
40
+ (cdr arg))))
33
41
  arg)))
34
42
 
35
43
  (assign pre-compile-debug
36
- (fn (arg)
37
- (pre-compile-msg arg (pre-compile-raw arg))))
44
+ (fn (names arg)
45
+ (pre-compile-msg arg
46
+ (pre-compile-raw names
47
+ arg))))
38
48
 
39
49
  (assign debug-pre-compile
40
50
  (fn (arg)
41
- (assign pre-compile (cond arg pre-compile-debug pre-compile-raw))))
51
+ (assign pre-compile-with
52
+ (cond arg
53
+ pre-compile-debug
54
+ pre-compile-raw))))
42
55
 
43
56
  (debug-pre-compile nil)
44
57
 
58
+ ; builtin pre-compile does nothing; override here to provide macro-expansion
59
+ (assign pre-compile
60
+ (fn (arg)
61
+ (pre-compile-with macs arg)))
62
+
45
63
  ; we override this later to provide automatic documentation
46
64
  (hash-set macs 'def
47
65
  (fn (name args . body)
@@ -28,6 +28,8 @@
28
28
  (def dox-examples (name)
29
29
  (hash-get examples name))
30
30
 
31
+ (def dox-example-names () (hash-keys examples))
32
+
31
33
  (def dox-arg-names (name)
32
34
  (cond (dox? name)
33
35
  (cadddr (car (dox-lookup name))))))
@@ -81,9 +83,11 @@
81
83
  'args
82
84
  '`((fn nil ,@args)))
83
85
 
86
+ (mac def-assign args `(assign ,@args))
87
+
84
88
  (def define-def-expr (name args documentation body)
85
89
  ; used internally by 'def
86
- `(do (assign ,name (fn ,args ,@body))
90
+ `(do (def-assign ,name (fn ,args ,@body))
87
91
  (dox-add-doc ',name
88
92
  'def
89
93
  ',documentation
@@ -168,12 +168,16 @@
168
168
  ,(build-hash-get-key:car rnames)
169
169
  ,value-expr)))
170
170
 
171
+ (def isa (type obj) (eq? (type-of obj) type))
172
+
171
173
  (mac = (name value)
172
174
  (if (isa 'symbol name)
173
175
  `(assign ,name ,value)
174
176
  (caris 'dot-syntax name)
175
177
  (dot-syntax-assignment (cdr name) value)))
176
178
 
179
+ (mac def-assign args `(= ,@args))
180
+
177
181
  (def brace-list-hash-key (k)
178
182
  (if (isa 'symbol k) `(quote ,k)
179
183
  (caris 'unquote k) (cadr k)
@@ -199,8 +203,11 @@
199
203
  (build-ampersand-syntax (car rest))))
200
204
 
201
205
  (mac brace-list-mono (arg) arg)
206
+ (mac brace-list-empty () '(hash))
202
207
 
203
208
  (mac brace-list args
204
- (if (no (cdr args))
209
+ (if (no args)
210
+ `(brace-list-empty)
211
+ (no (cdr args))
205
212
  `(brace-list-mono ,(car args))
206
213
  (brace-list-build-hash args)))
@@ -1,3 +1,4 @@
1
+
1
2
  (def eachr (f things)
2
3
  (when things
3
4
  (eachr f (cdr things))
@@ -78,7 +79,6 @@
78
79
  (iso (cdr x) (cdr y)))))
79
80
 
80
81
  (def x1 (thing) thing)
81
- (def isa (type obj) (eq? (type-of obj) type))
82
82
  (def sym? (arg) (isa 'symbol arg))
83
83
  (def string? (arg) (isa 'string arg))
84
84
  (mac just (arg) arg)
@@ -51,8 +51,6 @@
51
51
 
52
52
  (mac examples-for (name . examples)
53
53
  (let suite-name "examples for ~(pp name)"
54
- `(do
55
- (register-test '(suite ,suite-name ,@examples))
56
- (dox-add-examples ',name
57
- ',(collect (curry !caris 'comment)
58
- examples)))))
54
+ (let plain-examples (collect (fn (x) (isa 'string (car x))) examples)
55
+ `(do (register-test '(suite ,suite-name ,@plain-examples))
56
+ (dox-add-examples ',name ',plain-examples)))))
@@ -54,6 +54,7 @@
54
54
  (pp/def brace-list (form indent) "{~(pp/inline (cdr form) indent)}")
55
55
 
56
56
  (pp/syntax
57
+ percent-syntax "%"
57
58
  colon-syntax ":"
58
59
  dot-syntax "."
59
60
  bang-syntax "!"
@@ -0,0 +1,31 @@
1
+ (examples-for date
2
+ ("creates a single date" (to-string (date 1965 6 8)) "1965-06-08" )
3
+ ("navigates to next day" (let d (date 2004 3 11) (to-string d.tomorrow)) "2004-03-12" )
4
+ ("navigates to previous day" (let d (date 2006 6 22) (to-string d.yesterday)) "2006-06-21" )
5
+ ("navigates to previous year" (let d (date 1971 12 18) (to-string d.last-year)) "1970-12-18" )
6
+ ("navigates to next year" (let d (date 1974 1 11) (to-string d.next-year)) "1975-01-11" )
7
+ ("navigates to previous month" (let d (date 1971 12 18) (to-string d.last-month)) "1971-11-18" )
8
+ ("navigates to next month" (let d (date 1974 1 11) (to-string d.next-month)) "1974-02-11" )
9
+ ("jumps a year to previous month" (let d (date 1974 1 11) (to-string d.last-month)) "1973-12-11" )
10
+ ("navigates to previous week" (let d (date 2008 2 16) (to-string d.last-week)) "2008-02-09" )
11
+ ("navigates to next week" (let d (date 1972 11 13) (to-string d.next-week)) "1972-11-20" )
12
+ ("navigates to year start" (let d (date 1972 11 13) (to-string d.beginning-of-year)) "1972-01-01" )
13
+ ("navigates to year end" (let d (date 1972 11 13) (to-string d.end-of-year)) "1972-12-31" )
14
+ ("navigates to month start" (let d (date 1971 11 18) (to-string d.beginning-of-month)) "1971-11-01" )
15
+ ("navigates to month end" (let d (date 1971 11 18) (to-string d.end-of-month)) "1971-11-30" )
16
+ ("navigates to week start" (let d (date 2015 11 6) (to-string d.beginning-of-week)) "2015-11-02" )
17
+ ("navigates to week end" (let d (date 2015 11 6) (to-string d.end-of-week)) "2015-11-08" )
18
+
19
+ ("returns its year" (let d (date 1999 12 31) d.year) 1999)
20
+ ("returns its month" (let d (date 1999 12 31) d.month) 12 )
21
+ ("returns its day" (let d (date 1999 12 31) d.day) 31 )
22
+ ("returns its week-day" (let d (date 1999 12 31) d.week-day) 5 )
23
+ ("recognises not monday" (let d (date 2015 11 1) d.monday? ) nil )
24
+ ("recognises monday" (let d (date 2015 11 2) d.monday? ) t )
25
+ ("recognises tuesday" (let d (date 2015 11 3) d.tuesday? ) t )
26
+ ("recognises wednesday" (let d (date 2015 11 4) d.wednesday?) t )
27
+ ("recognises thursday" (let d (date 2015 11 5) d.thursday? ) t )
28
+ ("recognises friday" (let d (date 2015 11 6) d.friday? ) t )
29
+ ("recognises not friday" (let d (date 2015 11 7) d.friday? ) nil )
30
+ ("recognises saturday" (let d (date 2015 11 7) d.saturday? ) t )
31
+ ("recognises sunday" (let d (date 2015 11 8) d.sunday? ) t ))
@@ -0,0 +1,16 @@
1
+ (assign foo (hash))
2
+ (def foo.bar (a b) (* a b))
3
+ (def foo.zeb (a b) (* a (foo.bar a b)))
4
+
5
+ (examples-for def
6
+ ("can assign a function to a hash key"
7
+ (foo.bar 3 4)
8
+ 12)
9
+
10
+ ("sets hash keys"
11
+ (hash-keys foo)
12
+ (bar zeb))
13
+
14
+ ("hash defs are accessible wherever the hash is"
15
+ (foo.zeb 5 7)
16
+ 175))
@@ -4,6 +4,14 @@
4
4
  2.5))
5
5
 
6
6
  (examples-for eq?
7
+ ("is nil for two different dates"
8
+ (eq? (today) (+ (today) 1))
9
+ nil)
10
+
11
+ ("is true for two identical dates"
12
+ (eq? (date 2015 3 12) (+ (date 2015 3 1) 11))
13
+ t)
14
+
7
15
  ("true for two empty symbols"
8
16
  (eq? '|| '||)
9
17
  t)
@@ -19,6 +19,11 @@
19
19
  nil))
20
20
 
21
21
  (examples-for brace-list
22
+ ("with no args builds an empty hash"
23
+ (let thing {}
24
+ (list (type-of thing) (hash-keys thing)))
25
+ (hash nil))
26
+
22
27
  ("build a hash table from brace-list syntax"
23
28
  (let hsh { foo 1 bar 2 }
24
29
  (list 'foo hsh.foo 'bar hsh.bar))
@@ -20,6 +20,10 @@
20
20
  (parse "%this-and-that")
21
21
  ((percent-syntax || this-and-that)) )
22
22
 
23
+ ("parses a percent-prefix-mixed-with-dot-syntax symbol"
24
+ (parse "%this.and.that")
25
+ ((percent-syntax || (dot-syntax this and that))) )
26
+
23
27
  ("parses a dot-syntax symbol"
24
28
  (parse "this.that.zozo")
25
29
  ((dot-syntax this that zozo)) )
@@ -0,0 +1,19 @@
1
+ (examples-for pre-compile-with
2
+ ("does nothing with an empty hash"
3
+ (pre-compile-with (hash) '(let a 1 (p a)))
4
+ (let a 1 (p a)))
5
+
6
+ ("uses the given macros to expand the given expression"
7
+ (let lang { p (fn args `(print-stuff ,@args))
8
+ def (fn (name . body) `(define-it ,(to-string name) ,(len body) ,@body))
9
+ brace-list (fn (first second third) `(brace-things ,first (p ,second))) }
10
+ (pre-compile-with lang
11
+ '(let a 'b
12
+ (p { a b c }
13
+ (with (m n)
14
+ (def p q r s tt))))))
15
+ (let a 'b
16
+ (print-stuff (brace-things a
17
+ (print-stuff b))
18
+ (with (m n)
19
+ (define-it "p" 4 q r s tt))))))
@@ -25,6 +25,10 @@
25
25
  (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!"))
26
26
  "\"hello ~~!x.y.foo&bar and welcome to ~~%%(a b c d) and friends!\"")
27
27
 
28
+ ("perent-syntax"
29
+ (pp '(percent-syntax || (dot-syntax x y)))
30
+ "%x.y")
31
+
28
32
  ("brace list"
29
33
  (pp '(&x {a 1 b "two" c 'three d ,four e (sub invocation) f {sub brace list} }))
30
34
  "(&x {a 1 b \"two\" c 'three d ,four e (sub invocation) f {sub brace list}})"))
@@ -8,8 +8,12 @@ module Nydp
8
8
 
9
9
  MONTH_SIZES = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
10
10
  def build y, m, d
11
- s = MONTH_SIZES[m]
12
- ::Date.new(y, m, (d > s ? s : d))
11
+ if m < 1
12
+ build( y - 1, m + 12, d )
13
+ else
14
+ s = MONTH_SIZES[m]
15
+ ::Date.new(y, m, (d > s ? s : d))
16
+ end
13
17
  end
14
18
 
15
19
  def initialize ruby_date
@@ -24,14 +28,16 @@ module Nydp
24
28
  def + int ; r2n(ruby_date + int , nil) ; end
25
29
  def > other ; ruby_date > other.ruby_date ; end
26
30
  def < other ; ruby_date < other.ruby_date ; end
31
+ def == other ; ruby_date == other.ruby_date ; end
27
32
 
33
+ @@pass_through = %i{ monday? tuesday? wednesday? thursday? friday? saturday? sunday? }
28
34
  @@keys = Set.new %i{
29
35
  year month week_day day
30
36
  last_year next_year beginning_of_year end_of_year
31
37
  last_month next_month beginning_of_month end_of_month
32
38
  last_week next_week beginning_of_week end_of_week
33
39
  yesterday tomorrow
34
- }
40
+ } + @@pass_through
35
41
 
36
42
  def year y, m, d, w ; y ; end
37
43
  def month y, m, d, w ; m ; end
@@ -56,6 +62,12 @@ module Nydp
56
62
  def yesterday y, m, d, w ; ruby_date - 1 ; end
57
63
  def tomorrow y, m, d, w ; ruby_date + 1 ; end
58
64
 
65
+ @@pass_through.each do |n|
66
+ class_eval "def #{n} * ; ruby_date.#{n} ; end"
67
+ end
68
+
69
+ def dispatch key, y, m, d, w ; self.send(key, y, m, d, w) if @@keys.include?(key) ; end
70
+
59
71
  def [] key
60
72
  key = key.to_s.gsub(/-/, '_').to_sym
61
73
  y = ruby_date.year
@@ -63,8 +75,7 @@ module Nydp
63
75
  d = ruby_date.day
64
76
  w = ruby_date.wday
65
77
 
66
- adjusted = self.send(key, y, m, d, w) if @@keys.include?(key)
67
- r2n adjusted, nil
78
+ r2n(dispatch(key, y, m, d, w), nil)
68
79
  end
69
80
  end
70
81
  end
@@ -1,3 +1,3 @@
1
1
  module Nydp
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
3
3
  end
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
4
+ version: 0.1.5
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-11-05 00:00:00.000000000 Z
11
+ date: 2015-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -101,6 +101,8 @@ files:
101
101
  - lib/lisp/tests/collect-tests.nydp
102
102
  - lib/lisp/tests/cons-examples.nydp
103
103
  - lib/lisp/tests/curry-tests.nydp
104
+ - lib/lisp/tests/date-examples.nydp
105
+ - lib/lisp/tests/def-examples.nydp
104
106
  - lib/lisp/tests/detect-examples.nydp
105
107
  - lib/lisp/tests/dot-syntax-examples.nydp
106
108
  - lib/lisp/tests/dox-tests.nydp
@@ -115,6 +117,7 @@ files:
115
117
  - lib/lisp/tests/len-examples.nydp
116
118
  - lib/lisp/tests/list-tests.nydp
117
119
  - lib/lisp/tests/parser-tests.nydp
120
+ - lib/lisp/tests/pre-compile-examples.nydp
118
121
  - lib/lisp/tests/pretty-print-tests.nydp
119
122
  - lib/lisp/tests/quasiquote-examples.nydp
120
123
  - lib/lisp/tests/range-examples.nydp