nydp 0.1.4 → 0.1.5

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