nydp 0.4.0 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +44 -0
  3. data/lib/lisp/core-010-precompile.nydp +13 -16
  4. data/lib/lisp/core-012-utils.nydp +21 -6
  5. data/lib/lisp/core-015-documentation.nydp +60 -19
  6. data/lib/lisp/core-017-builtin-dox.nydp +50 -39
  7. data/lib/lisp/core-020-utils.nydp +5 -5
  8. data/lib/lisp/core-030-syntax.nydp +103 -61
  9. data/lib/lisp/core-035-flow-control.nydp +18 -9
  10. data/lib/lisp/core-037-list-utils.nydp +36 -14
  11. data/lib/lisp/core-039-module.nydp +24 -0
  12. data/lib/lisp/core-040-utils.nydp +41 -23
  13. data/lib/lisp/core-041-string-utils.nydp +37 -9
  14. data/lib/lisp/core-042-date-utils.nydp +21 -1
  15. data/lib/lisp/core-043-list-utils.nydp +93 -67
  16. data/lib/lisp/core-045-dox-utils.nydp +5 -0
  17. data/lib/lisp/core-080-pretty-print.nydp +55 -17
  18. data/lib/lisp/core-090-hook.nydp +35 -1
  19. data/lib/lisp/core-100-utils.nydp +130 -28
  20. data/lib/lisp/core-110-hash-utils.nydp +61 -0
  21. data/lib/lisp/core-120-settings.nydp +46 -0
  22. data/lib/lisp/core-130-validations.nydp +51 -0
  23. data/lib/lisp/{core-060-benchmarking.nydp → core-900-benchmarking.nydp} +108 -5
  24. data/lib/lisp/tests/accum-examples.nydp +28 -1
  25. data/lib/lisp/tests/aif-examples.nydp +8 -3
  26. data/lib/lisp/tests/andify-examples.nydp +7 -0
  27. data/lib/lisp/tests/at-syntax-examples.nydp +17 -0
  28. data/lib/lisp/tests/best-examples.nydp +9 -0
  29. data/lib/lisp/tests/builtin-tests.nydp +19 -0
  30. data/lib/lisp/tests/case-examples.nydp +14 -0
  31. data/lib/lisp/tests/cdr-set-examples.nydp +6 -0
  32. data/lib/lisp/tests/date-examples.nydp +56 -1
  33. data/lib/lisp/tests/destructuring-examples.nydp +5 -5
  34. data/lib/lisp/tests/detect-examples.nydp +12 -0
  35. data/lib/lisp/tests/dp-examples.nydp +24 -0
  36. data/lib/lisp/tests/empty-examples.nydp +1 -1
  37. data/lib/lisp/tests/error-tests.nydp +4 -4
  38. data/lib/lisp/tests/filter-forms-examples.nydp +30 -0
  39. data/lib/lisp/tests/foundation-test.nydp +12 -0
  40. data/lib/lisp/tests/hash-examples.nydp +26 -2
  41. data/lib/lisp/tests/list-grep-examples.nydp +40 -0
  42. data/lib/lisp/tests/list-tests.nydp +58 -1
  43. data/lib/lisp/tests/map-hash-examples.nydp +11 -0
  44. data/lib/lisp/tests/mapreduce-examples.nydp +10 -0
  45. data/lib/lisp/tests/module-examples.nydp +10 -0
  46. data/lib/lisp/tests/multi-assign-examples.nydp +6 -0
  47. data/lib/lisp/tests/parser-tests.nydp +21 -0
  48. data/lib/lisp/tests/pretty-print-tests.nydp +16 -13
  49. data/lib/lisp/tests/set-difference-examples.nydp +8 -0
  50. data/lib/lisp/tests/set-intersection-examples.nydp +32 -0
  51. data/lib/lisp/tests/set-union-examples.nydp +24 -0
  52. data/lib/lisp/tests/settings-examples.nydp +40 -0
  53. data/lib/lisp/tests/sort-examples.nydp +8 -0
  54. data/lib/lisp/tests/string-tests.nydp +61 -1
  55. data/lib/lisp/tests/syntax-tests.nydp +5 -1
  56. data/lib/lisp/tests/to-integer-examples.nydp +16 -0
  57. data/lib/lisp/tests/validation-examples.nydp +15 -0
  58. data/lib/lisp/tests/zap-examples.nydp +12 -0
  59. data/lib/nydp.rb +13 -7
  60. data/lib/nydp/assignment.rb +10 -3
  61. data/lib/nydp/builtin.rb +1 -1
  62. data/lib/nydp/builtin/abs.rb +8 -0
  63. data/lib/nydp/builtin/cdr_set.rb +1 -6
  64. data/lib/nydp/builtin/date.rb +15 -1
  65. data/lib/nydp/builtin/error.rb +1 -1
  66. data/lib/nydp/builtin/handle_error.rb +1 -1
  67. data/lib/nydp/builtin/hash.rb +27 -45
  68. data/lib/nydp/builtin/inspect.rb +1 -1
  69. data/lib/nydp/builtin/plus.rb +10 -2
  70. data/lib/nydp/builtin/rand.rb +18 -0
  71. data/lib/nydp/builtin/random_string.rb +2 -2
  72. data/lib/nydp/builtin/ruby_wrap.rb +72 -0
  73. data/lib/nydp/builtin/set_intersection.rb +8 -0
  74. data/lib/nydp/builtin/set_union.rb +8 -0
  75. data/lib/nydp/builtin/string_match.rb +2 -2
  76. data/lib/nydp/builtin/string_pad_left.rb +7 -0
  77. data/lib/nydp/builtin/string_pad_right.rb +7 -0
  78. data/lib/nydp/builtin/string_replace.rb +1 -1
  79. data/lib/nydp/builtin/string_split.rb +1 -2
  80. data/lib/nydp/builtin/to_integer.rb +23 -0
  81. data/lib/nydp/builtin/to_string.rb +2 -9
  82. data/lib/nydp/builtin/type_of.rb +9 -6
  83. data/lib/nydp/closure.rb +0 -3
  84. data/lib/nydp/cond.rb +23 -1
  85. data/lib/nydp/context_symbol.rb +14 -6
  86. data/lib/nydp/core.rb +45 -33
  87. data/lib/nydp/core_ext.rb +54 -0
  88. data/lib/nydp/date.rb +37 -31
  89. data/lib/nydp/function_invocation.rb +34 -26
  90. data/lib/nydp/hash.rb +5 -6
  91. data/lib/nydp/helper.rb +41 -25
  92. data/lib/nydp/interpreted_function.rb +68 -40
  93. data/lib/nydp/literal.rb +1 -1
  94. data/lib/nydp/pair.rb +25 -9
  95. data/lib/nydp/parser.rb +8 -6
  96. data/lib/nydp/string_atom.rb +16 -22
  97. data/lib/nydp/symbol.rb +40 -27
  98. data/lib/nydp/symbol_lookup.rb +7 -7
  99. data/lib/nydp/tokeniser.rb +2 -2
  100. data/lib/nydp/truth.rb +17 -10
  101. data/lib/nydp/version.rb +1 -1
  102. data/lib/nydp/vm.rb +7 -2
  103. data/nydp.gemspec +2 -4
  104. data/spec/date_spec.rb +115 -22
  105. data/spec/embedded_spec.rb +12 -12
  106. data/spec/foreign_hash_spec.rb +14 -2
  107. data/spec/hash_non_hash_behaviour_spec.rb +7 -7
  108. data/spec/hash_spec.rb +24 -2
  109. data/spec/nydp_spec.rb +14 -2
  110. data/spec/parser_spec.rb +27 -16
  111. data/spec/rand_spec.rb +45 -0
  112. data/spec/spec_helper.rb +13 -1
  113. data/spec/symbol_spec.rb +31 -0
  114. data/spec/time_spec.rb +1 -1
  115. metadata +38 -37
  116. data/lib/nydp/builtin/car.rb +0 -7
  117. data/lib/nydp/builtin/cdr.rb +0 -7
  118. data/lib/nydp/builtin/cons.rb +0 -9
@@ -18,7 +18,7 @@ module Nydp
18
18
  def nydp_type ; :literal ; end
19
19
  def inspect ; @expression.inspect ; end
20
20
  def to_s ; @expression.to_s ; end
21
- def to_ruby ; n2r @expression ; end
21
+ def to_ruby ; n2r @expression ; end
22
22
 
23
23
  def coerce _
24
24
  [_, expression]
@@ -16,17 +16,37 @@ 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
23
24
  def size ; 1 + (cdr.is_a?(Nydp::Pair) ? cdr.size : 0) ; end
24
25
  def inspect ; "(#{inspect_rest})" ; end
26
+ def & other ; self.class.from_list((Set.new(self) & other).to_a) ; end
27
+ def | other ; self.class.from_list((Set.new(self) | other).to_a) ; end
28
+ def - other ; self.class.from_list((Set.new(self) - other).to_a) ; end
29
+ def proper? ; Nydp::NIL.is?(cdr) || (cdr.is_a?(Nydp::Pair) && cdr.proper?) ; end
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
25
40
 
26
41
  # returns Array of elements after calling #n2r on each element
27
- def to_ruby list=[]
28
- list << n2r(car)
29
- cdr.is_a?(Nydp::Pair) ? cdr.to_ruby(list) : list
42
+ def to_ruby list=[], pair=self
43
+ list << n2r(pair.car)
44
+ while(pair.cdr.is_a?(Nydp::Pair))
45
+ pair = pair.cdr
46
+ list << n2r(pair.car)
47
+ end
48
+
49
+ list
30
50
  end
31
51
 
32
52
  # returns Array of elements as they are
@@ -47,7 +67,7 @@ class Nydp::Pair
47
67
  if n >= list.size
48
68
  last
49
69
  else
50
- new list[n], from_list(list, last, n+1)
70
+ Nydp::Pair.new list[n], from_list(list, last, n+1)
51
71
  end
52
72
  end
53
73
 
@@ -55,10 +75,6 @@ class Nydp::Pair
55
75
  (NIL != other) && (other.respond_to? :car) && (self.car == other.car) && (self.cdr == other.cdr)
56
76
  end
57
77
 
58
- def proper?
59
- Nydp::NIL.is?(cdr) || (cdr.is_a?(Nydp::Pair) && cdr.proper?)
60
- end
61
-
62
78
  def each &block
63
79
  yield car
64
80
  cdr.each(&block) unless Nydp::NIL.is?(cdr)
@@ -34,8 +34,7 @@ module Nydp
34
34
  when /^(.*),@$/
35
35
  prefix_list $1, Pair.from_list([sym(:"unquote-splicing"), list])
36
36
  else
37
- pfx = Nydp::StringAtom.new prefix
38
- Pair.from_list([sym(:"prefix-list"), pfx, list])
37
+ Pair.from_list([sym(:"prefix-list"), prefix, list])
39
38
  end
40
39
  end
41
40
 
@@ -45,15 +44,16 @@ module Nydp
45
44
 
46
45
  SYMBOL_OPERATORS =
47
46
  [
48
- [ /%/, "percent-syntax" ],
49
47
  [ /\!/, "bang-syntax" ],
50
48
  [ /::/, "colon-colon-syntax"],
51
49
  [ /:/, "colon-syntax" ],
52
50
  [ /&/, "ampersand-syntax" ],
51
+ [ /%/, "percent-syntax" ],
53
52
  [ /\./, "dot-syntax" ],
54
53
  [ /\$/, "dollar-syntax" ],
55
54
  [ /->/, "arrow-syntax" ],
56
55
  [ /[=][>]/, "rocket-syntax" ],
56
+ [ /@/, "at-syntax" ],
57
57
  ]
58
58
 
59
59
  def parse_symbol txt
@@ -73,6 +73,8 @@ module Nydp
73
73
  Pair.from_list [sym(:unquote), parse_symbol($1)]
74
74
  when /^\.$/
75
75
  sym txt
76
+ when /^@$/
77
+ sym txt
76
78
  else
77
79
  SYMBOL_OPERATORS.each do |rgx, name|
78
80
  syms = txt.split(rgx, -1)
@@ -108,7 +110,7 @@ module Nydp
108
110
  when :symbol
109
111
  parse_symbol token.last
110
112
  when :comment
111
- Pair.from_list [sym(:comment), Nydp::StringAtom.new(token.last)]
113
+ Pair.from_list [sym(:comment), token.last]
112
114
  else
113
115
  token.last
114
116
  end
@@ -129,11 +131,11 @@ module Nydp
129
131
  fragments = [sym(:"string-pieces")]
130
132
  string_token = token_stream.next_string_fragment(open_delimiter, close_delimiter, INTERPOLATION_SIGN, INTERPOLATION_ESCAPES)
131
133
  raise "unterminated string" if string_token.nil?
132
- fragments << Nydp::StringAtom.new(string_token.string, string_token)
134
+ fragments << string_token.string
133
135
  while !(string_token.is_a? StringFragmentCloseToken)
134
136
  fragments << expression(token_stream)
135
137
  string_token = token_stream.next_string_fragment('', close_delimiter, INTERPOLATION_SIGN, INTERPOLATION_ESCAPES)
136
- fragments << Nydp::StringAtom.new(string_token.string, string_token)
138
+ fragments << string_token.string
137
139
  end
138
140
 
139
141
  if fragments.size == 2
@@ -1,32 +1,26 @@
1
1
  module Nydp
2
2
  class StringAtom
3
- attr_accessor :string, :token
4
- def initialize string, token=nil
5
- @string, @token = string, token
6
- end
3
+ attr_accessor :string
7
4
 
8
- def nydp_type ; :string ; end
9
- def to_s ; string ; end
10
- def to_ruby ; string ; end
11
- def to_sym ; string.to_sym ; end
12
- def eql? other ; self == other ; end
13
- def inspect ; string.inspect ; end
14
- def hash ; string.hash ; end
15
- def length ; string.length ; end
16
- def > other ; self.string > other.string ; end
17
- def < other ; self.string < other.string ; end
18
- def * other ; StringAtom.new(string * other) ; end
5
+ def initialize string ; @string = string ; end
19
6
 
20
- def <=> other
21
- self < other ? -1 : (self == other ? 0 : 1)
22
- end
7
+ def nydp_type ; :string ; end
8
+ def to_s ; string ; end
9
+ def to_ruby ; string ; end
10
+ def to_sym ; string.to_sym ; end
11
+ def to_date ; ::Date.parse(@string) ; end
12
+ def eql? other ; self == other ; end
13
+ def inspect ; string.inspect ; end
14
+ def hash ; string.hash ; end
15
+ def length ; string.length ; end
16
+ def > other ; self.string > other.string ; end
17
+ def < other ; self.string < other.string ; end
18
+ def * other ; StringAtom.new(string * other) ; end
19
+ def <=> other ; self < other ? -1 : (self == other ? 0 : 1) ; end
20
+ def + other ; StringAtom.new "#{@string}#{other}" ; end
23
21
 
24
22
  def == other
25
23
  other.is_a?(Nydp::StringAtom) && (other.to_s == self.to_s)
26
24
  end
27
-
28
- def + other
29
- StringAtom.new "#{@string}#{other}"
30
- end
31
25
  end
32
26
  end
@@ -1,19 +1,22 @@
1
1
  class Nydp::Symbol
2
2
  class Unbound < StandardError ; end
3
-
4
3
  EMPTY = :""
5
4
  attr_accessor :name
6
- attr_reader :hash
5
+
6
+ def self.new name
7
+ special(name.to_s.to_sym) || super
8
+ end
7
9
 
8
10
  def initialize name
9
11
  name = name.to_s
10
12
  @name = name.to_sym
11
- @inspection = "|#{name}|" if untidy(name)
12
- @hash = name.hash
13
+ @inspection = "|#{name.gsub(/\|/, '\|')}|" if untidy(name)
13
14
  end
14
15
 
16
+ def hash ; name.hash ; end # can't cache this, it seems to break when unmarshalling
17
+
15
18
  def untidy str
16
- (str == "") || (str == nil) || (str =~ /\s/)
19
+ (str == "") || (str == nil) || (str =~ /[\s\|,\(\)"]/)
17
20
  end
18
21
 
19
22
  def value context=nil
@@ -21,41 +24,51 @@ class Nydp::Symbol
21
24
  @value
22
25
  end
23
26
 
24
- def self.mk name, ns
25
- name = name.to_sym
27
+ def self.special name
26
28
  return Nydp::NIL if name == :nil
27
29
  return Nydp::T if name == :t
28
- sym = ns[name]
29
- unless sym
30
- sym = new(name)
31
- ns[name] = sym
32
- end
33
- sym
30
+ nil
34
31
  end
35
32
 
33
+ def self.mk name, ns
34
+ name = name.to_s.to_sym
35
+ ns[name] ||= new(name)
36
+ end
36
37
 
37
38
  def self.find name, ns ; ns[name.to_sym] ; end
38
39
 
39
- def nydp_type ; :symbol ; end
40
- def inspect ; @inspection || name.to_s ; end
41
- def to_s ; name.to_s ; end
42
- def to_sym ; name ; end
43
- def to_ruby ; to_sym ; end
44
- def eql? other ; self == other ; end
45
- def is? nm ; self.name == nm.to_sym ; end
46
- def > other ; self.name > other.name ; end
47
- def < other ; self.name < other.name ; end
48
- def <=> other ; self.name <=> other.name ; end
40
+ def nydp_type ; :symbol ; end
41
+ def inspect ; @inspection || name.to_s ; end
42
+ def to_s ; name.to_s ; end
43
+ def to_sym ; name ; end
44
+ def to_ruby ; to_sym ; end
45
+ def is? nm ; self.name == nm.to_sym ; end
46
+ def > other ; self.name > other.name ; end
47
+ def < other ; self.name < other.name ; end
48
+ def <=> other ; self.name <=> other.name ; end
49
+ def assign value, _=nil ; @value = value ; end
50
+ def execute vm ; vm.push_arg self.value ; end
49
51
 
50
52
  def == other
51
53
  other.is_a?(Nydp::Symbol) && (self.name == other.name)
52
54
  end
53
55
 
54
- def execute vm
55
- vm.push_arg self.value
56
+ alias eql? ==
57
+ end
58
+
59
+ class Nydp::FrozenSymbol < Nydp::Symbol
60
+ @@frozen = { }
61
+
62
+ def self.mk name
63
+ name = name.to_s.to_sym
64
+ @@frozen[name] ||= new(name)
65
+ end
66
+
67
+ def value _=nil
68
+ raise Unbound.new("frozen symbol: #{self.inspect}")
56
69
  end
57
70
 
58
- def assign value, _=nil
59
- @value = value
71
+ def assign v, _=nil
72
+ raise "can't assign to frozen: #{self.inspect}"
60
73
  end
61
74
  end
@@ -11,17 +11,17 @@ module Nydp
11
11
  bindings
12
12
  end
13
13
 
14
- def self.build name, bindings
15
- bindings = skip_empty bindings
16
- depth = 0
17
- while NIL != bindings
18
- here = bindings.car
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
- bindings = skip_empty bindings.cdr
24
+ effective_bindings = skip_empty effective_bindings.cdr
25
25
  end
26
26
  end
27
27
  name
@@ -3,7 +3,7 @@ require "strscan"
3
3
  module Nydp
4
4
  class Tokeniser
5
5
  BACKSLASH = /\\/.freeze
6
- COMMENT = /;.*$/.freeze
6
+ COMMENT = /;;?.*$/.freeze
7
7
  QUOTE = /"/.freeze
8
8
  PIPE = /\|/.freeze
9
9
  LIST_PFX = /[^\s()]*\(/.freeze
@@ -89,7 +89,7 @@ module Nydp
89
89
  @finished = true
90
90
  return nil
91
91
  elsif comment = s.scan(COMMENT)
92
- tok = [:comment, comment[1..-1].strip]
92
+ tok = [:comment, comment.gsub(/^;;?\s*/, '').strip]
93
93
  elsif open_str = s.scan(QUOTE)
94
94
  tok = [:string_open_delim, open_str]
95
95
  elsif open_sym = s.scan(PIPE)
@@ -3,22 +3,24 @@ require 'singleton'
3
3
  module Nydp
4
4
  class Truth
5
5
  include Singleton
6
- def init_with *; Nydp::T ; end
7
- def to_s ; 't' ; end
8
- def inspect ; 't[nydp::Truth]' ; end
9
- def assign *_ ; self ; end
10
- def nydp_type ; :truth ; end
11
- def to_ruby ; true ; end
6
+ def init_with *; Nydp::T ; end
7
+ def to_s ; 't' ; end
8
+ def inspect ; 't' ; end
9
+ def assign *_ ; self ; end
10
+ def nydp_type ; :truth ; end
11
+ def to_ruby ; true ; end
12
+ def _nydp_get a ; Nydp::T ; end
13
+ def _nydp_set a, v ; Nydp::T ; end
12
14
  end
13
15
 
14
16
  class Nil
15
- include Singleton
17
+ include Singleton, Enumerable
16
18
  def init_with * ; Nydp::NIL ; end
17
19
  def car ; self ; end
18
20
  def cdr ; self ; end
19
21
  def size ; 0 ; end
20
- def is? other ; self == other ; end
21
- def isnt? other ; self != other ; end
22
+ def is? other ; self.equal? other ; end
23
+ def isnt? other ; !self.equal? other ; end
22
24
  def to_s ; "" ; end
23
25
  def + other ; other ; end
24
26
  def copy ; self ; end
@@ -26,7 +28,12 @@ module Nydp
26
28
  def inspect ; "nil" ; end
27
29
  def nydp_type ; :nil ; end
28
30
  def to_ruby ; nil ; end
29
- def execute vm ; vm.push_arg self ; end
31
+ def execute vm ; vm.push_arg self ; end
32
+ def _nydp_get a ; Nydp::NIL ; end
33
+ def _nydp_set a, v ; Nydp::NIL ; end
34
+ def each ; ; end # nil behaves like an empty list
35
+ def & other ; self ; end
36
+ def | other ; other ; end
30
37
  end
31
38
 
32
39
  NIL = Nil.instance
@@ -1,3 +1,3 @@
1
1
  module Nydp
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.6"
3
3
  end
@@ -15,8 +15,6 @@ module Nydp
15
15
  @ns = ns
16
16
  end
17
17
 
18
- def r2n obj ; super obj, @ns ; end
19
-
20
18
  def push_instructions ii, ctx
21
19
  if @current_instructions && NIL != @current_instructions
22
20
  @instructions.push @current_instructions
@@ -118,6 +116,13 @@ module Nydp
118
116
  end
119
117
  msg << "\n"
120
118
  msg << "\n"
119
+ msg << "\nargs stack"
120
+ msg << "\n================="
121
+ args.each_with_index do |args, ix|
122
+ msg << "\args##{ix} :\n#{args}"
123
+ end
124
+ msg << "\n"
125
+ msg << "\n"
121
126
  msg
122
127
  end
123
128
  end
@@ -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 "bundler", "~> 1.3"
22
- spec.add_development_dependency "rake", "~> 10.0"
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
@@ -7,7 +7,7 @@ describe Nydp::Date do
7
7
 
8
8
  it "converts ruby Date to Nydp::Date" do
9
9
  rd = Date.parse "2015-06-08"
10
- nd = Nydp.r2n rd, ns
10
+ nd = Nydp.r2n rd
11
11
 
12
12
  expect(nd). to be_a Nydp::Date
13
13
  expect(nd.to_s). to eq "2015-06-08"
@@ -33,16 +33,16 @@ describe Nydp::Date do
33
33
 
34
34
  it "returns date components" do
35
35
  rd = Date.parse "2015-06-08"
36
- nd = Nydp.r2n rd, ns
36
+ nd = Nydp.r2n rd
37
37
 
38
- expect(nd[:year]). to eq 2015
39
- expect(nd[:month]).to eq 6
40
- expect(nd[:day]). to eq 8
38
+ expect(nd._nydp_get(:year) ).to eq 2015
39
+ expect(nd._nydp_get(:month)).to eq 6
40
+ expect(nd._nydp_get(:day) ).to eq 8
41
41
  end
42
42
 
43
43
  describe "date maths" do
44
- let(:d0) { Nydp.r2n Date.today, ns }
45
- let(:d1) { Nydp.r2n (Date.today + 6), ns }
44
+ let(:d0) { Nydp.r2n Date.today }
45
+ let(:d1) { Nydp.r2n (Date.today + 6) }
46
46
 
47
47
  it "works with builtin minus" do
48
48
  minus = Nydp::Builtin::Minus.instance
@@ -120,31 +120,124 @@ describe Nydp::Date do
120
120
 
121
121
  it "returns relative dates by year" do
122
122
  rd = Date.parse "2015-06-08"
123
- nd = Nydp.r2n rd, ns
123
+ nd = Nydp.r2n rd
124
124
 
125
- expect(nd[:"last-year"].to_s). to eq "2014-06-08"
126
- expect(nd[:"next-year"].to_s). to eq "2016-06-08"
127
- expect(nd[:"beginning-of-year"].to_s). to eq "2015-01-01"
128
- expect(nd[:"end-of-year"].to_s). to eq "2015-12-31"
125
+ expect(nd._nydp_get(:"last-year").to_s). to eq "2014-06-08"
126
+ expect(nd._nydp_get(:"next-year").to_s). to eq "2016-06-08"
127
+ expect(nd._nydp_get(:"beginning-of-year").to_s). to eq "2015-01-01"
128
+ expect(nd._nydp_get(:"end-of-year").to_s). to eq "2015-12-31"
129
129
  end
130
130
 
131
131
  it "returns relative dates by month" do
132
132
  rd = Date.parse "2015-06-08"
133
- nd = Nydp.r2n rd, ns
133
+ nd = Nydp.r2n rd
134
134
 
135
- expect(nd[:"last-month"].to_s). to eq "2015-05-08"
136
- expect(nd[:"next-month"].to_s). to eq "2015-07-08"
137
- expect(nd[:"beginning-of-month"].to_s). to eq "2015-06-01"
138
- expect(nd[:"end-of-month"].to_s). to eq "2015-06-30"
135
+ expect(nd._nydp_get(:"last-month").to_s). to eq "2015-05-08"
136
+ expect(nd._nydp_get(:"next-month").to_s). to eq "2015-07-08"
137
+ expect(nd._nydp_get(:"beginning-of-month").to_s). to eq "2015-06-01"
138
+ expect(nd._nydp_get(:"end-of-month").to_s). to eq "2015-06-30"
139
+ end
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"
139
173
  end
140
174
 
141
175
  it "returns relative dates by week" do
142
176
  rd = Date.parse "2015-03-12"
143
- nd = Nydp.r2n rd, ns
177
+ nd = Nydp.r2n rd
178
+
179
+ expect(nd._nydp_get(:"last-week").to_s). to eq "2015-03-05"
180
+ expect(nd._nydp_get(:"next-week").to_s). to eq "2015-03-19"
181
+ expect(nd._nydp_get(:"beginning-of-week").to_s). to eq "2015-03-09"
182
+ expect(nd._nydp_get(:"end-of-week").to_s). to eq "2015-03-15"
183
+ end
184
+
185
+ it "returns age relative to today" do
186
+ rd = Date.parse "2014-03-12"
187
+ nd = Nydp.r2n rd
188
+ allow(::Date).to receive_messages(today: Date.parse("2016-06-21"))
189
+ expect(nd._nydp_get(:age)).to eq({ years: 2, months: 3 })
190
+ end
191
+
192
+ it "returns a negative age relative to today for a date in the future" do
193
+ rd = Date.parse "2094-11-18"
194
+ nd = Nydp.r2n rd
195
+ allow(::Date).to receive_messages(today: Date.parse("2016-06-21"))
196
+ expect(nd._nydp_get(:age)).to eq({ years: -78, months: -5 })
197
+ end
144
198
 
145
- expect(nd[:"last-week"].to_s). to eq "2015-03-05"
146
- expect(nd[:"next-week"].to_s). to eq "2015-03-19"
147
- expect(nd[:"beginning-of-week"].to_s). to eq "2015-03-09"
148
- expect(nd[:"end-of-week"].to_s). to eq "2015-03-15"
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
149
242
  end
150
243
  end