nydp 0.4.3 → 0.4.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 +4 -4
- data/lib/lisp/core-010-precompile.nydp +5 -6
- data/lib/lisp/core-012-utils.nydp +2 -1
- data/lib/lisp/core-015-documentation.nydp +17 -11
- data/lib/lisp/core-020-utils.nydp +5 -5
- data/lib/lisp/core-030-syntax.nydp +29 -9
- data/lib/lisp/core-035-flow-control.nydp +15 -6
- data/lib/lisp/core-037-list-utils.nydp +22 -0
- data/lib/lisp/core-039-module.nydp +24 -0
- data/lib/lisp/core-040-utils.nydp +11 -12
- data/lib/lisp/core-041-string-utils.nydp +24 -0
- data/lib/lisp/core-042-date-utils.nydp +16 -0
- data/lib/lisp/core-043-list-utils.nydp +72 -50
- data/lib/lisp/core-080-pretty-print.nydp +50 -17
- data/lib/lisp/core-090-hook.nydp +13 -1
- data/lib/lisp/core-100-utils.nydp +82 -2
- data/lib/lisp/core-110-hash-utils.nydp +38 -0
- data/lib/lisp/core-120-settings.nydp +11 -2
- data/lib/lisp/core-900-benchmarking.nydp +17 -17
- data/lib/lisp/tests/accum-examples.nydp +28 -1
- 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 +10 -0
- data/lib/lisp/tests/case-examples.nydp +14 -0
- data/lib/lisp/tests/date-examples.nydp +54 -1
- 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/hash-examples.nydp +17 -0
- data/lib/lisp/tests/list-grep-examples.nydp +40 -0
- data/lib/lisp/tests/list-tests.nydp +39 -0
- data/lib/lisp/tests/module-examples.nydp +10 -0
- data/lib/lisp/tests/parser-tests.nydp +16 -0
- data/lib/lisp/tests/pretty-print-tests.nydp +8 -2
- data/lib/lisp/tests/settings-examples.nydp +1 -1
- data/lib/lisp/tests/string-tests.nydp +48 -0
- data/lib/lisp/tests/syntax-tests.nydp +5 -1
- data/lib/nydp.rb +6 -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 +9 -0
- data/lib/nydp/builtin/error.rb +1 -1
- data/lib/nydp/builtin/hash.rb +11 -1
- data/lib/nydp/builtin/ruby_wrap.rb +69 -0
- data/lib/nydp/builtin/string_pad_left.rb +7 -0
- data/lib/nydp/builtin/string_pad_right.rb +7 -0
- 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 +33 -29
- data/lib/nydp/core_ext.rb +5 -4
- data/lib/nydp/date.rb +17 -17
- data/lib/nydp/function_invocation.rb +33 -25
- data/lib/nydp/helper.rb +12 -2
- data/lib/nydp/interpreted_function.rb +68 -40
- data/lib/nydp/literal.rb +1 -1
- data/lib/nydp/pair.rb +13 -2
- data/lib/nydp/parser.rb +3 -0
- data/lib/nydp/symbol_lookup.rb +7 -7
- data/lib/nydp/version.rb +1 -1
- data/nydp.gemspec +2 -4
- data/spec/date_spec.rb +79 -0
- data/spec/parser_spec.rb +11 -0
- metadata +15 -36
- data/lib/nydp/builtin/car.rb +0 -7
- data/lib/nydp/builtin/cdr.rb +0 -7
- data/lib/nydp/builtin/cons.rb +0 -9
@@ -13,9 +13,8 @@ module Nydp
|
|
13
13
|
|
14
14
|
class Base
|
15
15
|
include Helper
|
16
|
-
def initialize
|
17
|
-
@
|
18
|
-
@sig = sig
|
16
|
+
def initialize expr, source, sig=nil
|
17
|
+
@expr, @source, @sig = expr, source, sig
|
19
18
|
end
|
20
19
|
|
21
20
|
def handle e, f, invoker, *args
|
@@ -35,9 +34,14 @@ module Nydp
|
|
35
34
|
end
|
36
35
|
end
|
37
36
|
|
38
|
-
|
39
|
-
def
|
40
|
-
|
37
|
+
# TODO: speed up compilation by writing custom #lexical_reach for sig-based subclasses (when you know which elements of #expr are lexical symbols)
|
38
|
+
def lexical_reach n
|
39
|
+
@expr.map { |x| x.lexical_reach n}.max
|
40
|
+
end
|
41
|
+
|
42
|
+
def inspect ; @expr.map { |x| x.inspect }.join ' ' ; end
|
43
|
+
def source ; @source ; end
|
44
|
+
def to_s ; source.to_s ; end
|
41
45
|
end
|
42
46
|
|
43
47
|
class Invocation_1 < Invocation::Base
|
@@ -87,8 +91,8 @@ module Nydp
|
|
87
91
|
end
|
88
92
|
|
89
93
|
class Invocation_N < Invocation::Base
|
90
|
-
def initialize arg_count,
|
91
|
-
super
|
94
|
+
def initialize arg_count, expr, source
|
95
|
+
super expr, source
|
92
96
|
@arg_count = arg_count
|
93
97
|
end
|
94
98
|
|
@@ -107,7 +111,7 @@ module Nydp
|
|
107
111
|
class Invocation_LEX < Invocation::Base
|
108
112
|
SIGS << self.name
|
109
113
|
def initialize expr, src
|
110
|
-
super src
|
114
|
+
super expr, src
|
111
115
|
@sym = expr.car
|
112
116
|
end
|
113
117
|
|
@@ -122,7 +126,7 @@ module Nydp
|
|
122
126
|
class Invocation_SYM < Invocation::Base
|
123
127
|
SIGS << self.name
|
124
128
|
def initialize expr, src
|
125
|
-
super src
|
129
|
+
super expr, src
|
126
130
|
@sym = expr.car
|
127
131
|
end
|
128
132
|
|
@@ -137,7 +141,7 @@ module Nydp
|
|
137
141
|
class Invocation_LEX_LEX < Invocation::Base
|
138
142
|
SIGS << self.name
|
139
143
|
def initialize expr, src
|
140
|
-
super src
|
144
|
+
super expr, src
|
141
145
|
@lex0 = expr.car
|
142
146
|
@lex1 = expr.cdr.car
|
143
147
|
end
|
@@ -155,7 +159,7 @@ module Nydp
|
|
155
159
|
class Invocation_SYM_LEX < Invocation::Base
|
156
160
|
SIGS << self.name
|
157
161
|
def initialize expr, src
|
158
|
-
super src
|
162
|
+
super expr, src
|
159
163
|
@sym = expr.car
|
160
164
|
@lex = expr.cdr.car
|
161
165
|
end
|
@@ -172,7 +176,7 @@ module Nydp
|
|
172
176
|
class Invocation_SYM_LIT < Invocation::Base
|
173
177
|
SIGS << self.name
|
174
178
|
def initialize expr, src
|
175
|
-
super src
|
179
|
+
super expr, src
|
176
180
|
@sym = expr.car
|
177
181
|
@lit = expr.cdr.car.expression
|
178
182
|
end
|
@@ -188,7 +192,7 @@ module Nydp
|
|
188
192
|
class Invocation_LEX_LEX_LEX < Invocation::Base
|
189
193
|
SIGS << self.name
|
190
194
|
def initialize expr, src
|
191
|
-
super src
|
195
|
+
super expr, src
|
192
196
|
@lex_0 = expr.car
|
193
197
|
@lex_1 = expr.cdr.car
|
194
198
|
@lex_2 = expr.cdr.cdr.car
|
@@ -208,7 +212,7 @@ module Nydp
|
|
208
212
|
class Invocation_SYM_LEX_LEX < Invocation::Base
|
209
213
|
SIGS << self.name
|
210
214
|
def initialize expr, src
|
211
|
-
super src
|
215
|
+
super expr, src
|
212
216
|
@sym = expr.car
|
213
217
|
@lex_0 = expr.cdr.car
|
214
218
|
@lex_1 = expr.cdr.cdr.car
|
@@ -227,7 +231,7 @@ module Nydp
|
|
227
231
|
class Invocation_SYM_LEX_LEX_LEX < Invocation::Base
|
228
232
|
SIGS << self.name
|
229
233
|
def initialize expr, src
|
230
|
-
super src
|
234
|
+
super expr, src
|
231
235
|
@sym = expr.car
|
232
236
|
@lex_0 = expr.cdr.car
|
233
237
|
@lex_1 = expr.cdr.cdr.car
|
@@ -248,7 +252,7 @@ module Nydp
|
|
248
252
|
class Invocation_SYM_LEX_LIT_LEX < Invocation::Base
|
249
253
|
SIGS << self.name
|
250
254
|
def initialize expr, src
|
251
|
-
super src
|
255
|
+
super expr, src
|
252
256
|
@sym = expr.car
|
253
257
|
@lex_0 = expr.cdr.car
|
254
258
|
@lit_1 = expr.cdr.cdr.car.expression
|
@@ -268,7 +272,7 @@ module Nydp
|
|
268
272
|
class Invocation_SYM_LIT_LEX < Invocation::Base
|
269
273
|
SIGS << self.name
|
270
274
|
def initialize expr, src
|
271
|
-
super src
|
275
|
+
super expr, src
|
272
276
|
@sym = expr.car
|
273
277
|
@lit_0 = expr.cdr.car.expression
|
274
278
|
@lex_1 = expr.cdr.cdr.car
|
@@ -288,6 +292,10 @@ module Nydp
|
|
288
292
|
extend Helper
|
289
293
|
attr_accessor :function_instruction, :argument_instructions
|
290
294
|
|
295
|
+
def lexical_reach n
|
296
|
+
function_instruction.car.lexical_reach(n)
|
297
|
+
end
|
298
|
+
|
291
299
|
def self.build expression, bindings
|
292
300
|
compiled = Compiler.compile_each(expression, bindings)
|
293
301
|
invocation_sig = compiled.map { |x| sig x }.join("_")
|
@@ -303,15 +311,15 @@ module Nydp
|
|
303
311
|
|
304
312
|
invocation = cons case expression.size
|
305
313
|
when 1
|
306
|
-
Invocation::Invocation_1.new(expression)
|
314
|
+
Invocation::Invocation_1.new(compiled, expression)
|
307
315
|
when 2
|
308
|
-
Invocation::Invocation_2.new(expression)
|
316
|
+
Invocation::Invocation_2.new(compiled, expression)
|
309
317
|
when 3
|
310
|
-
Invocation::Invocation_3.new(expression)
|
318
|
+
Invocation::Invocation_3.new(compiled, expression)
|
311
319
|
when 4
|
312
|
-
Invocation::Invocation_4.new(expression)
|
320
|
+
Invocation::Invocation_4.new(compiled, expression)
|
313
321
|
else
|
314
|
-
Invocation::Invocation_N.new(expression.size, expression)
|
322
|
+
Invocation::Invocation_N.new(expression.size, compiled, expression)
|
315
323
|
end
|
316
324
|
new invocation, compiled, expression, cname
|
317
325
|
end
|
@@ -327,7 +335,7 @@ module Nydp
|
|
327
335
|
vm.push_ctx_instructions argument_instructions
|
328
336
|
end
|
329
337
|
|
330
|
-
def inspect ; @
|
331
|
-
def to_s ; @source.to_s
|
338
|
+
def inspect ; @function_instruction.inspect ; end
|
339
|
+
def to_s ; @source.to_s ; end
|
332
340
|
end
|
333
341
|
end
|
data/lib/nydp/helper.rb
CHANGED
@@ -1,7 +1,17 @@
|
|
1
1
|
module Nydp
|
2
2
|
module AutoWrap
|
3
|
-
|
4
|
-
|
3
|
+
# include this and be sure to either override #_nydp_ok? or #_nydp_whitelist
|
4
|
+
# #_nydp_whitelist should return a list of methods which are safe for nydp to invoke
|
5
|
+
def _nydp_wrapper ; self ; end
|
6
|
+
def _nydp_ok? method ; _nydp_whitelist.include? method ; end
|
7
|
+
def _nydp_safe_send method, *args ; send method, *args if _nydp_ok? method ; end
|
8
|
+
def _nydp_get key ; _nydp_safe_send(key.to_s.as_method_name) ; end
|
9
|
+
def to_ruby ; self ; end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Struct < ::Struct
|
13
|
+
include AutoWrap
|
14
|
+
def _nydp_whitelist ; members ; end
|
5
15
|
end
|
6
16
|
|
7
17
|
module Converter
|
@@ -5,8 +5,8 @@ require 'nydp/closure'
|
|
5
5
|
module Nydp
|
6
6
|
class PopArg
|
7
7
|
def self.execute vm ; vm.args.pop ; end
|
8
|
-
def self.to_s ; ""
|
9
|
-
def self.inspect ; "#pop_arg"
|
8
|
+
def self.to_s ; "" ; end
|
9
|
+
def self.inspect ; "#pop_arg" ; end
|
10
10
|
end
|
11
11
|
|
12
12
|
class InterpretedFunction
|
@@ -16,42 +16,22 @@ module Nydp
|
|
16
16
|
|
17
17
|
attr_accessor :arg_names, :body, :context_builder
|
18
18
|
|
19
|
-
def
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
def invoke_2 vm, parent_context, arg
|
24
|
-
vm.push_instructions self.body, set_args_1(parent_context, arg)
|
25
|
-
end
|
26
|
-
|
27
|
-
def invoke_3 vm, parent_context, arg_0, arg_1
|
28
|
-
vm.push_instructions self.body, set_args_2(parent_context, arg_0, arg_1)
|
29
|
-
end
|
30
|
-
|
31
|
-
def invoke_4 vm, parent_context, arg_0, arg_1, arg_2
|
32
|
-
vm.push_instructions self.body, set_args_3(parent_context, arg_0, arg_1, arg_2)
|
33
|
-
end
|
34
|
-
|
35
|
-
def invoke vm, parent_context, arg_values
|
36
|
-
vm.push_instructions self.body, set_args(parent_context, arg_values)
|
37
|
-
end
|
38
|
-
|
39
|
-
def setup_context context, names, values
|
40
|
-
if pair? names
|
41
|
-
context.set names.car, values.car
|
42
|
-
setup_context context, names.cdr, values.cdr
|
43
|
-
elsif NIL != names
|
44
|
-
context.set names, values
|
45
|
-
end
|
19
|
+
def lexical_reach n
|
20
|
+
body.map { |b| b.lexical_reach(n - 1) }.max
|
46
21
|
end
|
47
22
|
|
48
23
|
def self.build arg_list, body, bindings
|
49
24
|
my_params = { }
|
50
25
|
index_parameters arg_list, my_params
|
51
|
-
|
26
|
+
body = compile_body body, cons(my_params, bindings), []
|
27
|
+
reach = body.map { |b| b.lexical_reach(-1) }.max
|
28
|
+
|
29
|
+
ifn_klass = reach >= 0 ? InterpretedFunctionWithClosure : InterpretedFunctionWithoutClosure
|
30
|
+
ifn = ifn_klass.new
|
52
31
|
ifn.arg_names = arg_list
|
32
|
+
ifn.body = body
|
33
|
+
|
53
34
|
ifn.extend Nydp::LexicalContextBuilder.select arg_list
|
54
|
-
ifn.body = compile_body body, cons(my_params, bindings), []
|
55
35
|
ifn
|
56
36
|
end
|
57
37
|
|
@@ -62,6 +42,11 @@ module Nydp
|
|
62
42
|
if Nydp::NIL.is? rest
|
63
43
|
return Pair.from_list(instructions)
|
64
44
|
else
|
45
|
+
# PopArg is necessary because each expression pushes an arg onto the arg stack.
|
46
|
+
# we only need to keep the arg pushed by the last expression in a function
|
47
|
+
# so we need the following line in order to remove unwanted args from the stack.
|
48
|
+
# Each expression at some executes vm.push_arg(thing)
|
49
|
+
# TODO find a more intelligent way to do this, eg change the meaning of vm or of push_arg in the expression vm.push_arg(thing)
|
65
50
|
instructions << PopArg
|
66
51
|
compile_body rest, bindings, instructions
|
67
52
|
end
|
@@ -76,19 +61,62 @@ module Nydp
|
|
76
61
|
end
|
77
62
|
end
|
78
63
|
|
79
|
-
def execute vm
|
80
|
-
# TODO do not create a new Closure if this function does not refer to it
|
81
|
-
# - including top-level function definitions
|
82
|
-
# - and any other function that does not refer to any lexically-bound outer variable
|
83
|
-
# - for example (fn (x) (* x x)) in (map λx(* x x) things) does not need a closure, because
|
84
|
-
# the function does not refer to any lexical variable outside itself.
|
85
|
-
vm.push_arg Closure.new(self, vm.current_context)
|
86
|
-
end
|
87
|
-
|
88
64
|
def nydp_type ; "fn" ; end
|
89
65
|
def inspect ; to_s ; end
|
90
66
|
def to_s
|
91
67
|
"(fn #{arg_names.inspect} #{body.map { |b| b.inspect}.join(' ')})"
|
92
68
|
end
|
93
69
|
end
|
70
|
+
|
71
|
+
class InterpretedFunctionWithClosure < InterpretedFunction
|
72
|
+
def invoke_1 vm, ctx
|
73
|
+
vm.push_instructions self.body, set_args_0(ctx)
|
74
|
+
end
|
75
|
+
|
76
|
+
def invoke_2 vm, ctx, arg
|
77
|
+
vm.push_instructions self.body, set_args_1(ctx, arg)
|
78
|
+
end
|
79
|
+
|
80
|
+
def invoke_3 vm, ctx, arg_0, arg_1
|
81
|
+
vm.push_instructions self.body, set_args_2(ctx, arg_0, arg_1)
|
82
|
+
end
|
83
|
+
|
84
|
+
def invoke_4 vm, ctx, arg_0, arg_1, arg_2
|
85
|
+
vm.push_instructions self.body, set_args_3(ctx, arg_0, arg_1, arg_2)
|
86
|
+
end
|
87
|
+
|
88
|
+
def invoke vm, ctx, arg_values
|
89
|
+
vm.push_instructions self.body, set_args(ctx, arg_values)
|
90
|
+
end
|
91
|
+
|
92
|
+
def execute vm
|
93
|
+
vm.push_arg Closure.new(self, vm.current_context)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class InterpretedFunctionWithoutClosure < InterpretedFunction
|
98
|
+
def invoke_1 vm
|
99
|
+
vm.push_instructions self.body, set_args_0(vm.current_context)
|
100
|
+
end
|
101
|
+
|
102
|
+
def invoke_2 vm, arg
|
103
|
+
vm.push_instructions self.body, set_args_1(vm.current_context, arg)
|
104
|
+
end
|
105
|
+
|
106
|
+
def invoke_3 vm, arg_0, arg_1
|
107
|
+
vm.push_instructions self.body, set_args_2(vm.current_context, arg_0, arg_1)
|
108
|
+
end
|
109
|
+
|
110
|
+
def invoke_4 vm, arg_0, arg_1, arg_2
|
111
|
+
vm.push_instructions self.body, set_args_3(vm.current_context, arg_0, arg_1, arg_2)
|
112
|
+
end
|
113
|
+
|
114
|
+
def invoke vm, arg_values
|
115
|
+
vm.push_instructions self.body, set_args(vm.current_context, arg_values)
|
116
|
+
end
|
117
|
+
|
118
|
+
def execute vm
|
119
|
+
vm.push_arg self
|
120
|
+
end
|
121
|
+
end
|
94
122
|
end
|
data/lib/nydp/literal.rb
CHANGED
data/lib/nydp/pair.rb
CHANGED
@@ -16,7 +16,8 @@ class Nydp::Pair
|
|
16
16
|
def cddr ; cdr.cdr ; end
|
17
17
|
def car= thing ; @car = thing ; @_hash = nil ; end
|
18
18
|
def cdr= thing ; @cdr = thing ; @_hash = nil ; end
|
19
|
-
def hash ; @_hash ||= (car.hash + cdr.hash) ; end
|
19
|
+
# def hash ; @_hash ||= (car.hash + cdr.hash) ; end
|
20
|
+
def hash ; (car.hash + cdr.hash) ; end # can't cache hash of symbol, breaks when unmarshalling
|
20
21
|
def eql? other ; self == other ; end
|
21
22
|
def copy ; cons(car, cdr.copy) ; end
|
22
23
|
def + other ; copy.append other ; end
|
@@ -27,6 +28,16 @@ class Nydp::Pair
|
|
27
28
|
def - other ; self.class.from_list((Set.new(self) - other).to_a) ; end
|
28
29
|
def proper? ; Nydp::NIL.is?(cdr) || (cdr.is_a?(Nydp::Pair) && cdr.proper?) ; end
|
29
30
|
|
31
|
+
def index_of x
|
32
|
+
if x == car
|
33
|
+
0
|
34
|
+
elsif pair?(cdr)
|
35
|
+
1 + cdr.index_of(x)
|
36
|
+
else
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
30
41
|
# returns Array of elements after calling #n2r on each element
|
31
42
|
def to_ruby list=[]
|
32
43
|
list << n2r(car)
|
@@ -51,7 +62,7 @@ class Nydp::Pair
|
|
51
62
|
if n >= list.size
|
52
63
|
last
|
53
64
|
else
|
54
|
-
new list[n], from_list(list, last, n+1)
|
65
|
+
Nydp::Pair.new list[n], from_list(list, last, n+1)
|
55
66
|
end
|
56
67
|
end
|
57
68
|
|
data/lib/nydp/parser.rb
CHANGED
@@ -54,6 +54,7 @@ module Nydp
|
|
54
54
|
[ /\$/, "dollar-syntax" ],
|
55
55
|
[ /->/, "arrow-syntax" ],
|
56
56
|
[ /[=][>]/, "rocket-syntax" ],
|
57
|
+
[ /@/, "at-syntax" ],
|
57
58
|
]
|
58
59
|
|
59
60
|
def parse_symbol txt
|
@@ -73,6 +74,8 @@ module Nydp
|
|
73
74
|
Pair.from_list [sym(:unquote), parse_symbol($1)]
|
74
75
|
when /^\.$/
|
75
76
|
sym txt
|
77
|
+
when /^@$/
|
78
|
+
sym txt
|
76
79
|
else
|
77
80
|
SYMBOL_OPERATORS.each do |rgx, name|
|
78
81
|
syms = txt.split(rgx, -1)
|
data/lib/nydp/symbol_lookup.rb
CHANGED
@@ -11,17 +11,17 @@ module Nydp
|
|
11
11
|
bindings
|
12
12
|
end
|
13
13
|
|
14
|
-
def self.build name,
|
15
|
-
|
16
|
-
depth
|
17
|
-
while NIL !=
|
18
|
-
here =
|
14
|
+
def self.build name, original_bindings
|
15
|
+
effective_bindings = skip_empty original_bindings
|
16
|
+
depth = 0
|
17
|
+
while NIL != effective_bindings
|
18
|
+
here = effective_bindings.car
|
19
19
|
if here.key? name
|
20
20
|
binding_index = here[name]
|
21
|
-
return ContextSymbol.build(depth, name, binding_index)
|
21
|
+
return ContextSymbol.build(depth, name, binding_index, original_bindings.index_of(here))
|
22
22
|
else
|
23
23
|
depth += 1
|
24
|
-
|
24
|
+
effective_bindings = skip_empty effective_bindings.cdr
|
25
25
|
end
|
26
26
|
end
|
27
27
|
name
|
data/lib/nydp/version.rb
CHANGED
data/nydp.gemspec
CHANGED
@@ -18,8 +18,6 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_development_dependency "
|
22
|
-
spec.add_development_dependency
|
23
|
-
spec.add_development_dependency 'rspec', '~> 3.1'
|
24
|
-
spec.add_development_dependency 'rspec_numbering_formatter'
|
21
|
+
spec.add_development_dependency "rake", "~> 12"
|
22
|
+
spec.add_development_dependency 'rspec' #, '~> 3.1'
|
25
23
|
end
|
data/spec/date_spec.rb
CHANGED
@@ -138,6 +138,40 @@ describe Nydp::Date do
|
|
138
138
|
expect(nd._nydp_get(:"end-of-month").to_s). to eq "2015-06-30"
|
139
139
|
end
|
140
140
|
|
141
|
+
it "calculates end-of-month all year around" do
|
142
|
+
expect(Nydp.r2n(Date.parse("2015-01-08"))._nydp_get(:"end-of-month").to_s).to eq "2015-01-31"
|
143
|
+
expect(Nydp.r2n(Date.parse("2015-02-08"))._nydp_get(:"end-of-month").to_s).to eq "2015-02-28"
|
144
|
+
expect(Nydp.r2n(Date.parse("2016-02-08"))._nydp_get(:"end-of-month").to_s).to eq "2016-02-29"
|
145
|
+
expect(Nydp.r2n(Date.parse("2015-03-08"))._nydp_get(:"end-of-month").to_s).to eq "2015-03-31"
|
146
|
+
expect(Nydp.r2n(Date.parse("2015-04-08"))._nydp_get(:"end-of-month").to_s).to eq "2015-04-30"
|
147
|
+
expect(Nydp.r2n(Date.parse("2015-05-08"))._nydp_get(:"end-of-month").to_s).to eq "2015-05-31"
|
148
|
+
expect(Nydp.r2n(Date.parse("2015-06-08"))._nydp_get(:"end-of-month").to_s).to eq "2015-06-30"
|
149
|
+
expect(Nydp.r2n(Date.parse("2015-07-08"))._nydp_get(:"end-of-month").to_s).to eq "2015-07-31"
|
150
|
+
expect(Nydp.r2n(Date.parse("2015-08-08"))._nydp_get(:"end-of-month").to_s).to eq "2015-08-31"
|
151
|
+
expect(Nydp.r2n(Date.parse("2015-09-08"))._nydp_get(:"end-of-month").to_s).to eq "2015-09-30"
|
152
|
+
expect(Nydp.r2n(Date.parse("2015-10-08"))._nydp_get(:"end-of-month").to_s).to eq "2015-10-31"
|
153
|
+
expect(Nydp.r2n(Date.parse("2015-11-08"))._nydp_get(:"end-of-month").to_s).to eq "2015-11-30"
|
154
|
+
expect(Nydp.r2n(Date.parse("2015-12-08"))._nydp_get(:"end-of-month").to_s).to eq "2015-12-31"
|
155
|
+
end
|
156
|
+
|
157
|
+
it "manages leap years" do
|
158
|
+
rd = Date.parse "2020-02-08"
|
159
|
+
nd = Nydp.r2n rd
|
160
|
+
|
161
|
+
expect(nd._nydp_get(:"last-month").to_s). to eq "2020-01-08"
|
162
|
+
expect(nd._nydp_get(:"next-month").to_s). to eq "2020-03-08"
|
163
|
+
expect(nd._nydp_get(:"beginning-of-month").to_s). to eq "2020-02-01"
|
164
|
+
expect(nd._nydp_get(:"end-of-month").to_s). to eq "2020-02-29"
|
165
|
+
|
166
|
+
rd = Date.parse "2020-02-28"
|
167
|
+
nd = Nydp.r2n rd
|
168
|
+
expect(nd._nydp_get(:"tomorrow").to_s). to eq "2020-02-29"
|
169
|
+
|
170
|
+
rd = Date.parse "2020-03-01"
|
171
|
+
nd = Nydp.r2n rd
|
172
|
+
expect(nd._nydp_get(:"yesterday").to_s). to eq "2020-02-29"
|
173
|
+
end
|
174
|
+
|
141
175
|
it "returns relative dates by week" do
|
142
176
|
rd = Date.parse "2015-03-12"
|
143
177
|
nd = Nydp.r2n rd
|
@@ -161,4 +195,49 @@ describe Nydp::Date do
|
|
161
195
|
allow(::Date).to receive_messages(today: Date.parse("2016-06-21"))
|
162
196
|
expect(nd._nydp_get(:age)).to eq({ years: -78, months: -5 })
|
163
197
|
end
|
198
|
+
|
199
|
+
describe "#change" do
|
200
|
+
let(:nd) { Nydp::Date.new(Date.parse("1965-06-08")) }
|
201
|
+
|
202
|
+
it "advances by weeks" do
|
203
|
+
expect((nd.change 1, :week).to_s).to eq "1965-06-15"
|
204
|
+
expect((nd.change -1, :week).to_s).to eq "1965-06-01"
|
205
|
+
expect((nd.change -2, :week).to_s).to eq "1965-05-25"
|
206
|
+
expect((nd.change 2, :week).to_s).to eq "1965-06-22"
|
207
|
+
end
|
208
|
+
|
209
|
+
it "advances by days" do
|
210
|
+
expect((nd.change 1, :day).to_s).to eq "1965-06-09"
|
211
|
+
expect((nd.change -1, :day).to_s).to eq "1965-06-07"
|
212
|
+
expect((nd.change -2, :day).to_s).to eq "1965-06-06"
|
213
|
+
expect((nd.change 2, :day).to_s).to eq "1965-06-10"
|
214
|
+
end
|
215
|
+
|
216
|
+
it "advances by months" do
|
217
|
+
expect((nd.change 1, :month).to_s).to eq "1965-07-08"
|
218
|
+
expect((nd.change -1, :month).to_s).to eq "1965-05-08"
|
219
|
+
expect((nd.change -2, :month).to_s).to eq "1965-04-08"
|
220
|
+
expect((nd.change 2, :month).to_s).to eq "1965-08-08"
|
221
|
+
end
|
222
|
+
|
223
|
+
it "advances by years" do
|
224
|
+
expect((nd.change 1, :year).to_s).to eq "1966-06-08"
|
225
|
+
expect((nd.change -1, :year).to_s).to eq "1964-06-08"
|
226
|
+
expect((nd.change -2, :year).to_s).to eq "1963-06-08"
|
227
|
+
expect((nd.change 2, :year).to_s).to eq "1967-06-08"
|
228
|
+
end
|
229
|
+
|
230
|
+
it "handles leap years and small months" do
|
231
|
+
d = Nydp::Date.new(Date.parse("2019-12-31"))
|
232
|
+
|
233
|
+
expect(d.change( 2, :month).to_s).to eq "2020-02-29"
|
234
|
+
expect(d.change(12, :month).to_s).to eq "2020-12-31"
|
235
|
+
expect(d.change(14, :month).to_s).to eq "2021-02-28"
|
236
|
+
expect(d.change( 6, :month).to_s).to eq "2020-06-30"
|
237
|
+
expect(d.change( 7, :month).to_s).to eq "2020-07-31"
|
238
|
+
|
239
|
+
d = Nydp::Date.new(Date.parse("2020-02-29"))
|
240
|
+
expect(d.change(12, :month).to_s).to eq "2021-02-28"
|
241
|
+
end
|
242
|
+
end
|
164
243
|
end
|