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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/lib/lisp/core-010-precompile.nydp +5 -6
  3. data/lib/lisp/core-012-utils.nydp +2 -1
  4. data/lib/lisp/core-015-documentation.nydp +17 -11
  5. data/lib/lisp/core-020-utils.nydp +5 -5
  6. data/lib/lisp/core-030-syntax.nydp +29 -9
  7. data/lib/lisp/core-035-flow-control.nydp +15 -6
  8. data/lib/lisp/core-037-list-utils.nydp +22 -0
  9. data/lib/lisp/core-039-module.nydp +24 -0
  10. data/lib/lisp/core-040-utils.nydp +11 -12
  11. data/lib/lisp/core-041-string-utils.nydp +24 -0
  12. data/lib/lisp/core-042-date-utils.nydp +16 -0
  13. data/lib/lisp/core-043-list-utils.nydp +72 -50
  14. data/lib/lisp/core-080-pretty-print.nydp +50 -17
  15. data/lib/lisp/core-090-hook.nydp +13 -1
  16. data/lib/lisp/core-100-utils.nydp +82 -2
  17. data/lib/lisp/core-110-hash-utils.nydp +38 -0
  18. data/lib/lisp/core-120-settings.nydp +11 -2
  19. data/lib/lisp/core-900-benchmarking.nydp +17 -17
  20. data/lib/lisp/tests/accum-examples.nydp +28 -1
  21. data/lib/lisp/tests/at-syntax-examples.nydp +17 -0
  22. data/lib/lisp/tests/best-examples.nydp +9 -0
  23. data/lib/lisp/tests/builtin-tests.nydp +10 -0
  24. data/lib/lisp/tests/case-examples.nydp +14 -0
  25. data/lib/lisp/tests/date-examples.nydp +54 -1
  26. data/lib/lisp/tests/detect-examples.nydp +12 -0
  27. data/lib/lisp/tests/dp-examples.nydp +24 -0
  28. data/lib/lisp/tests/empty-examples.nydp +1 -1
  29. data/lib/lisp/tests/error-tests.nydp +4 -4
  30. data/lib/lisp/tests/hash-examples.nydp +17 -0
  31. data/lib/lisp/tests/list-grep-examples.nydp +40 -0
  32. data/lib/lisp/tests/list-tests.nydp +39 -0
  33. data/lib/lisp/tests/module-examples.nydp +10 -0
  34. data/lib/lisp/tests/parser-tests.nydp +16 -0
  35. data/lib/lisp/tests/pretty-print-tests.nydp +8 -2
  36. data/lib/lisp/tests/settings-examples.nydp +1 -1
  37. data/lib/lisp/tests/string-tests.nydp +48 -0
  38. data/lib/lisp/tests/syntax-tests.nydp +5 -1
  39. data/lib/nydp.rb +6 -3
  40. data/lib/nydp/assignment.rb +10 -3
  41. data/lib/nydp/builtin.rb +1 -1
  42. data/lib/nydp/builtin/abs.rb +8 -0
  43. data/lib/nydp/builtin/date.rb +9 -0
  44. data/lib/nydp/builtin/error.rb +1 -1
  45. data/lib/nydp/builtin/hash.rb +11 -1
  46. data/lib/nydp/builtin/ruby_wrap.rb +69 -0
  47. data/lib/nydp/builtin/string_pad_left.rb +7 -0
  48. data/lib/nydp/builtin/string_pad_right.rb +7 -0
  49. data/lib/nydp/builtin/type_of.rb +9 -6
  50. data/lib/nydp/closure.rb +0 -3
  51. data/lib/nydp/cond.rb +23 -1
  52. data/lib/nydp/context_symbol.rb +14 -6
  53. data/lib/nydp/core.rb +33 -29
  54. data/lib/nydp/core_ext.rb +5 -4
  55. data/lib/nydp/date.rb +17 -17
  56. data/lib/nydp/function_invocation.rb +33 -25
  57. data/lib/nydp/helper.rb +12 -2
  58. data/lib/nydp/interpreted_function.rb +68 -40
  59. data/lib/nydp/literal.rb +1 -1
  60. data/lib/nydp/pair.rb +13 -2
  61. data/lib/nydp/parser.rb +3 -0
  62. data/lib/nydp/symbol_lookup.rb +7 -7
  63. data/lib/nydp/version.rb +1 -1
  64. data/nydp.gemspec +2 -4
  65. data/spec/date_spec.rb +79 -0
  66. data/spec/parser_spec.rb +11 -0
  67. metadata +15 -36
  68. data/lib/nydp/builtin/car.rb +0 -7
  69. data/lib/nydp/builtin/cdr.rb +0 -7
  70. data/lib/nydp/builtin/cons.rb +0 -9
@@ -32,13 +32,13 @@ module Nydp::Builtin
32
32
  handle_error e, arg_0, arg_1, arg_2
33
33
  end
34
34
 
35
+ # called from 'apply (among others)
35
36
  def invoke vm, args
36
37
  builtin_invoke vm, args
37
38
  rescue StandardError => e
38
39
  handle_error e, *(args.to_a)
39
40
  end
40
41
 
41
-
42
42
  def handle_error e, *args
43
43
  case e
44
44
  when Nydp::Error
@@ -0,0 +1,8 @@
1
+ class Nydp::Builtin::Abs
2
+ include Nydp::Builtin::Base, Singleton
3
+
4
+ def invoke_2 vm, a0 ; vm.push_arg(a0.abs) ; end
5
+ def builtin_invoke vm, args ; invoke_2 vm, args.car ; end
6
+
7
+ def name ; "mod" ; end
8
+ end
@@ -1,6 +1,15 @@
1
1
  class Nydp::Builtin::Date
2
2
  include Nydp::Helper, Nydp::Builtin::Base, Singleton
3
3
 
4
+ def builtin_invoke vm, args
5
+ case args.size
6
+ when 0 ; builtin_invoke_1 vm
7
+ when 1 ; builtin_invoke_2 vm, args.car
8
+ when 2 ; builtin_invoke_3 vm, args.car, args.cdr.car
9
+ when 3 ; builtin_invoke_4 vm, args.car, args.cdr.car, args.cdr.cdr.car
10
+ end
11
+ end
12
+
4
13
  def builtin_invoke_1 vm
5
14
  vm.push_arg(Nydp::Date.new Date.today)
6
15
  end
@@ -4,6 +4,6 @@ class Nydp::Builtin::Error
4
4
  # override #invoke on nydp/builtin/base because
5
5
  # we don't want to inherit error handling
6
6
  def builtin_invoke vm, args
7
- raise Nydp::Error.new(args.to_a.map(&:inspect).join("\n"), vm.last_error)
7
+ raise Nydp::Error.new(args.to_a.map(&:to_s).join("\n"), vm.last_error)
8
8
  end
9
9
  end
@@ -2,8 +2,18 @@ require "nydp/hash"
2
2
 
3
3
  class Nydp::Builtin::Hash
4
4
  include Nydp::Helper, Nydp::Builtin::Base, Singleton
5
+
5
6
  def builtin_invoke vm, args
6
- vm.push_arg(Nydp::Hash.new)
7
+ vm.push_arg(build_hash Nydp::Hash.new, args)
8
+ end
9
+
10
+ def build_hash h, args
11
+ return h if Nydp::NIL.is? args
12
+ k = args.car
13
+ rest = args.cdr
14
+ v = rest.car
15
+ h[k] = v
16
+ build_hash h, rest.cdr
7
17
  end
8
18
  end
9
19
 
@@ -0,0 +1,69 @@
1
+ class Nydp::Builtin::RubyWrap
2
+ @@builtins = { }
3
+
4
+ def self.builtins
5
+ @@builtins
6
+ end
7
+
8
+ class Coder < Struct.new(:name, :size, :code, :helpers)
9
+ def msize ; size + 1 ; end
10
+
11
+ def arg_mapper
12
+ case size
13
+ when 0 ; ""
14
+ when 1 ; ", a0"
15
+ when 2 ; ", a0, a1"
16
+ when 3 ; ", a0, a1, a2"
17
+ when 4 ; ", a0, a1, a2, a3"
18
+ else ; raise "maximum 4 arguments!"
19
+ end
20
+ end
21
+
22
+ def to_ruby
23
+ generic_code = code.
24
+ gsub(/a0/, "args.car").
25
+ gsub(/a1/, "args.cdr.car").
26
+ gsub(/a2/, "args.cdr.cdr.car").
27
+ gsub(/a3/, "args.cdr.cdr.cdr.car")
28
+ <<CODE
29
+ class #{name}
30
+ include Nydp::Builtin::Base, Singleton#{helpers}
31
+
32
+ def builtin_invoke_#{msize} vm#{ arg_mapper }
33
+ vm.push_arg(#{code})
34
+ end
35
+
36
+ def builtin_invoke vm, args
37
+ vm.push_arg(#{generic_code})
38
+ end
39
+ end
40
+ CODE
41
+ end
42
+ end
43
+
44
+ def self.const_missing const
45
+ coder = @@builtins[const]
46
+ coder ? class_eval(coder.to_ruby) : super
47
+ const_get const
48
+ end
49
+
50
+ class WrapperBuilder
51
+ def initialize default_helpers
52
+ @default_helpers = default_helpers.to_s.strip != "" ? ", #{default_helpers}" : ""
53
+ end
54
+
55
+ def build name, args, code, helpers=""
56
+ extra_helpers = helpers.to_s.strip != "" ? ", #{helpers}" : ""
57
+ Nydp::Builtin::RubyWrap.builtins[name.to_sym] = Coder.new(name.to_sym, args, code, "#{@default_helpers}#{extra_helpers}")
58
+ end
59
+ end
60
+
61
+ def self.builder includes
62
+ WrapperBuilder.new(includes)
63
+ end
64
+
65
+ core_builder = builder ""
66
+ core_builder.build(:Cons, 2, %{ Nydp::Pair.new(a0, a1) })
67
+ core_builder.build(:Car , 1, %{ a0.car })
68
+ core_builder.build(:Cdr , 1, %{ a0.cdr })
69
+ end
@@ -0,0 +1,7 @@
1
+ class Nydp::Builtin::StringPadLeft
2
+ include Nydp::Builtin::Base, Singleton
3
+
4
+ def builtin_invoke_4 vm, str, len, padding
5
+ vm.push_arg Nydp::StringAtom.new str.to_s.rjust len, padding.to_s
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ class Nydp::Builtin::StringPadRight
2
+ include Nydp::Builtin::Base, Singleton
3
+
4
+ def builtin_invoke_4 vm, str, len, padding
5
+ vm.push_arg Nydp::StringAtom.new str.to_s.ljust len, padding.to_s
6
+ end
7
+ end
@@ -1,18 +1,21 @@
1
1
  class Nydp::Builtin::TypeOf
2
2
  include Nydp::Builtin::Base, Singleton
3
3
 
4
- def builtin_invoke vm, args
5
- arg = args.car
6
- typename = if arg.respond_to?(:nydp_type)
7
- arg.nydp_type.to_sym
8
- elsif arg.is_a? Numeric
4
+ def builtin_invoke_1 vm, a0
5
+ typename = if a0.respond_to?(:nydp_type)
6
+ a0.nydp_type.to_sym
7
+ elsif a0.is_a? Numeric
9
8
  :number
10
9
  else
11
- "ruby/#{arg.class.name}".to_sym
10
+ "ruby/#{a0.class.name}".to_sym
12
11
  end
13
12
 
14
13
  type = Nydp::Symbol.mk(typename, vm.ns)
15
14
 
16
15
  vm.push_arg(type || Nydp::NIL)
17
16
  end
17
+
18
+ def builtin_invoke vm, args
19
+ builtin_invoke_1 vm, args.car
20
+ end
18
21
  end
@@ -4,9 +4,6 @@ module Nydp
4
4
 
5
5
  def initialize ifn, context
6
6
  @ifn, @context = ifn, context
7
- # TODO don't create a closure where it's not needed (zero_arg functions), use parent context instead
8
- # TODO see SymbolLookup for how to ensure variable references stay on track
9
- # TODO see InterpretedFunction for where to not instantiate new LexicalContext
10
7
  end
11
8
 
12
9
  def invoke_1 vm
@@ -6,6 +6,10 @@ module Nydp
6
6
  @when_true, @when_false = when_true, when_false
7
7
  end
8
8
 
9
+ def lexical_reach n
10
+ [@when_true.lexical_reach(n), @when_false.lexical_reach(n)].max
11
+ end
12
+
9
13
  def execute vm
10
14
  (Nydp::NIL.is?(vm.args.pop) ? @when_false : @when_true).execute vm
11
15
  end
@@ -13,6 +17,7 @@ module Nydp
13
17
  def inspect
14
18
  "when_true:#{@when_true.inspect}:when_false:#{@when_false.inspect}"
15
19
  end
20
+
16
21
  def to_s
17
22
  "#{@when_true.to_s} #{@when_false.to_s}"
18
23
  end
@@ -27,6 +32,10 @@ module Nydp
27
32
  @condition, @conditional = cond, cons(ExecuteConditionalInstruction.new(when_true, when_false))
28
33
  end
29
34
 
35
+ def lexical_reach n
36
+ [@condition.lexical_reach(n), @conditional.car.lexical_reach(n)].max
37
+ end
38
+
30
39
  def execute vm
31
40
  vm.push_ctx_instructions conditional
32
41
  condition.execute vm
@@ -35,6 +44,7 @@ module Nydp
35
44
  def inspect
36
45
  "cond:#{condition.inspect}:#{conditional.inspect}"
37
46
  end
47
+
38
48
  def to_s
39
49
  "(cond #{condition.to_s} #{conditional.to_s})"
40
50
  end
@@ -57,7 +67,7 @@ module Nydp
57
67
  new(cond, when_true, when_false)
58
68
  end
59
69
  else
60
- raise "can't compile Cond: #{expr.inspect}"
70
+ raise "can't compile Cond: #{expressions.inspect}"
61
71
  end
62
72
  end
63
73
  end
@@ -70,6 +80,10 @@ module Nydp
70
80
  @condition, @when_true, @when_false = cond, when_true, when_false
71
81
  end
72
82
 
83
+ def lexical_reach n
84
+ [@condition.lexical_reach(n), @when_true.lexical_reach(n), @when_false.lexical_reach(n)].max
85
+ end
86
+
73
87
  def inspect ; "cond:#{@condition.inspect}:#{@when_true.inspect}:#{@when_false.inspect}" ; end
74
88
  def to_s ; "(cond #{@condition.to_s} #{@when_true.to_s} #{@when_false.to_s})" ; end
75
89
  end
@@ -80,6 +94,14 @@ module Nydp
80
94
  vm.push_ctx_instructions (truth ? @when_true : @when_false)
81
95
  end
82
96
 
97
+ def lexical_reach n
98
+ cr = @condition.lexical_reach(n)
99
+ ct = @when_true.car.lexical_reach(n)
100
+ cf = @when_false.car.lexical_reach(n)
101
+
102
+ [cr, ct, cf].max
103
+ end
104
+
83
105
  def self.build cond, when_true, when_false
84
106
  tsig = sig(when_true)
85
107
  fsig = sig(when_false)
@@ -25,12 +25,18 @@ module Nydp
25
25
  end
26
26
 
27
27
  code = <<-KLASS
28
- def initialize name
29
- @name = name
28
+ def initialize name, lexical_depth
29
+ @name, @lexical_depth = name, lexical_depth
30
+ end
31
+
32
+ def lexical_reach n
33
+ @lexical_depth + n
30
34
  end
31
35
 
32
36
  def value ctx
33
37
  ctx#{getctx}.#{at_index} || Nydp::NIL
38
+ rescue
39
+ raise "failed looking up \#{@name.inspect} (\#{@name.class.name})"
34
40
  end
35
41
 
36
42
  def assign value, ctx
@@ -45,16 +51,18 @@ module Nydp
45
51
 
46
52
  def depth ; #{depth} ; end
47
53
  def inspect ; to_s ; end
48
- def to_s ; "[#{depth}##{binding_index}]\#{@name}" ; end
54
+ def to_s ; "[#{depth}##{binding_index}#\#{@lexical_depth}]\#{@name}" ; end
49
55
  KLASS
50
56
 
51
57
  const_set name, Class.new(Nydp::ContextSymbol) {
52
- eval code
58
+ eval code, binding, name.to_s, 0
53
59
  }
54
60
  end
55
61
 
56
- def self.build depth, name, binding_index
57
- const_get(:"ContextSymbol_#{depth}_#{binding_index}").new(name)
62
+ def self.build effective_depth, name, binding_index, lexical_depth
63
+ const_get(:"ContextSymbol_#{effective_depth}_#{binding_index}").new(name, lexical_depth)
64
+ rescue
65
+ raise "building ContextSymbol #{[effective_depth, name, binding_index, lexical_depth].inspect}"
58
66
  end
59
67
  end
60
68
  end
@@ -25,9 +25,10 @@ module Nydp
25
25
  end
26
26
 
27
27
  def setup ns
28
- Symbol.mk(:cons, ns).assign(Nydp::Builtin::Cons.instance)
29
- Symbol.mk(:car, ns).assign(Nydp::Builtin::Car.instance)
30
- Symbol.mk(:cdr, ns).assign(Nydp::Builtin::Cdr.instance)
28
+ Symbol.mk(:cons , ns).assign(Nydp::Builtin::RubyWrap::Cons.instance)
29
+ Symbol.mk(:car , ns).assign(Nydp::Builtin::RubyWrap::Car.instance)
30
+ Symbol.mk(:cdr , ns).assign(Nydp::Builtin::RubyWrap::Cdr.instance)
31
+
31
32
  Symbol.mk(:+, ns).assign(Nydp::Builtin::Plus.instance)
32
33
  Symbol.mk(:-, ns).assign(Nydp::Builtin::Minus.instance)
33
34
  Symbol.mk(:*, ns).assign(Nydp::Builtin::Times.instance)
@@ -47,35 +48,38 @@ module Nydp
47
48
  Symbol.mk(:nil, ns).assign Nydp::NIL
48
49
  Symbol.mk(:rand, ns).assign Nydp::Builtin::Rand.instance
49
50
  Symbol.mk(:sort, ns).assign Nydp::Builtin::Sort.instance
51
+ Symbol.mk(:abs, ns).assign Nydp::Builtin::Abs.instance
50
52
  Symbol.mk(:sqrt, ns).assign Nydp::Builtin::Sqrt.instance
51
53
  Symbol.mk(:t, ns).assign Nydp::T
52
54
  Symbol.mk(:sym, ns).assign Nydp::Builtin::Sym.instance
53
- Symbol.mk(:ensuring, ns).assign(Nydp::Builtin::Ensuring.instance)
54
- Symbol.mk(:inspect, ns).assign(Nydp::Builtin::Inspect.instance)
55
- Symbol.mk(:comment, ns).assign(Nydp::Builtin::Comment.instance)
56
- Symbol.mk("handle-error" , ns).assign(Nydp::Builtin::HandleError.instance)
57
- Symbol.mk("parse-in-string", ns).assign(Nydp::Builtin::ParseInString.instance)
58
- Symbol.mk("random-string" , ns).assign(Nydp::Builtin::RandomString.instance)
59
- Symbol.mk("to-string" , ns).assign(Nydp::Builtin::ToString.instance)
60
- Symbol.mk("string-length" , ns).assign(Nydp::Builtin::StringLength.instance)
61
- Symbol.mk("string-replace" , ns).assign(Nydp::Builtin::StringReplace.instance)
62
- Symbol.mk("string-match" , ns).assign(Nydp::Builtin::StringMatch.instance)
63
- Symbol.mk("string-split" , ns).assign(Nydp::Builtin::StringSplit.instance)
64
- Symbol.mk("time" , ns).assign(Nydp::Builtin::Time.instance)
65
- Symbol.mk("thread-locals" , ns).assign(Nydp::Builtin::ThreadLocals.instance)
66
- Symbol.mk("type-of", ns).assign(Nydp::Builtin::TypeOf.instance)
67
- Symbol.mk(:"eq?", ns).assign(Nydp::Builtin::IsEqual.instance)
68
- Symbol.mk(:"cdr-set", ns).assign(Nydp::Builtin::CdrSet.instance)
69
- Symbol.mk(:"hash-get", ns).assign(Nydp::Builtin::HashGet.instance)
70
- Symbol.mk(:"hash-set", ns).assign(Nydp::Builtin::HashSet.instance)
71
- Symbol.mk(:"hash-keys", ns).assign(Nydp::Builtin::HashKeys.instance)
72
- Symbol.mk(:"hash-key?", ns).assign(Nydp::Builtin::HashKeyPresent.instance)
73
- Symbol.mk(:"hash-merge", ns).assign(Nydp::Builtin::HashMerge.instance)
74
- Symbol.mk(:"hash-slice", ns).assign(Nydp::Builtin::HashSlice.instance)
75
- Symbol.mk(:"vm-info", ns).assign Nydp::Builtin::VmInfo.instance
76
- Symbol.mk(:"pre-compile" , ns).assign Nydp::Builtin::PreCompile.instance
77
- Symbol.mk(:"script-run" , ns).assign Nydp::Builtin::ScriptRun.instance
78
- Symbol.mk(:"**" , ns).assign Nydp::Builtin::MathPower.instance
55
+ Symbol.mk(:ensuring , ns).assign(Nydp::Builtin::Ensuring.instance)
56
+ Symbol.mk(:inspect , ns).assign(Nydp::Builtin::Inspect.instance)
57
+ Symbol.mk(:comment , ns).assign(Nydp::Builtin::Comment.instance)
58
+ Symbol.mk("handle-error" , ns).assign(Nydp::Builtin::HandleError.instance)
59
+ Symbol.mk("parse-in-string" , ns).assign(Nydp::Builtin::ParseInString.instance)
60
+ Symbol.mk("random-string" , ns).assign(Nydp::Builtin::RandomString.instance)
61
+ Symbol.mk("to-string" , ns).assign(Nydp::Builtin::ToString.instance)
62
+ Symbol.mk("string-length" , ns).assign(Nydp::Builtin::StringLength.instance)
63
+ Symbol.mk("string-replace" , ns).assign(Nydp::Builtin::StringReplace.instance)
64
+ Symbol.mk("string-match" , ns).assign(Nydp::Builtin::StringMatch.instance)
65
+ Symbol.mk("string-split" , ns).assign(Nydp::Builtin::StringSplit.instance)
66
+ Symbol.mk("string/pad-left" , ns).assign(Nydp::Builtin::StringPadLeft.instance)
67
+ Symbol.mk("string/pad-right" , ns).assign(Nydp::Builtin::StringPadRight.instance)
68
+ Symbol.mk("time" , ns).assign(Nydp::Builtin::Time.instance)
69
+ Symbol.mk("thread-locals" , ns).assign(Nydp::Builtin::ThreadLocals.instance)
70
+ Symbol.mk("type-of" , ns).assign(Nydp::Builtin::TypeOf.instance)
71
+ Symbol.mk(:"eq?" , ns).assign(Nydp::Builtin::IsEqual.instance)
72
+ Symbol.mk(:"cdr-set" , ns).assign(Nydp::Builtin::CdrSet.instance)
73
+ Symbol.mk(:"hash-get" , ns).assign(Nydp::Builtin::HashGet.instance)
74
+ Symbol.mk(:"hash-set" , ns).assign(Nydp::Builtin::HashSet.instance)
75
+ Symbol.mk(:"hash-keys" , ns).assign(Nydp::Builtin::HashKeys.instance)
76
+ Symbol.mk(:"hash-key?" , ns).assign(Nydp::Builtin::HashKeyPresent.instance)
77
+ Symbol.mk(:"hash-merge" , ns).assign(Nydp::Builtin::HashMerge.instance)
78
+ Symbol.mk(:"hash-slice" , ns).assign(Nydp::Builtin::HashSlice.instance)
79
+ Symbol.mk(:"vm-info" , ns).assign Nydp::Builtin::VmInfo.instance
80
+ Symbol.mk(:"pre-compile" , ns).assign Nydp::Builtin::PreCompile.instance
81
+ Symbol.mk(:"script-run" , ns).assign Nydp::Builtin::ScriptRun.instance
82
+ Symbol.mk(:"**" , ns).assign Nydp::Builtin::MathPower.instance
79
83
  Symbol.mk(:"⌊" , ns).assign Nydp::Builtin::MathFloor.instance
80
84
  Symbol.mk(:"math-floor" , ns).assign Nydp::Builtin::MathFloor.instance
81
85
  Symbol.mk(:"⌈" , ns).assign Nydp::Builtin::MathCeiling.instance
@@ -1,8 +1,9 @@
1
1
  class Object
2
- def _nydp_get a ; raise "_nydp_get : not gettable: #{a.inspect} on #{self.class.name}" ; end
3
- def _nydp_set a, v ; raise "_nydp_get : not settable: #{a.inspect} on #{self.class.name}" ; end
4
- def _nydp_keys ; [] ; end
5
- def _nydp_wrapper ; self ; end
2
+ def _nydp_get a ; raise "_nydp_get : not gettable: #{a.inspect} on #{self.class.name}" ; end
3
+ def _nydp_set a, v ; raise "_nydp_get : not settable: #{a.inspect} on #{self.class.name}" ; end
4
+ def _nydp_keys ; [] ; end
5
+ def _nydp_wrapper ; self ; end
6
+ def lexical_reach n ; n ; end
6
7
  end
7
8
 
8
9
  class NilClass
@@ -22,15 +22,15 @@ module Nydp
22
22
  def to_ruby ; ruby_date ; end
23
23
  def inspect ; ruby_date.inspect ; end
24
24
  def nydp_type ; :date ; end
25
- def + int ; r2n(ruby_date + int) ; end
26
25
  def > other ; is_date?(other) && ruby_date > other.ruby_date ; end
27
26
  def < other ; is_date?(other) && ruby_date < other.ruby_date ; end
28
27
  def == other ; is_date?(other) && ruby_date == other.ruby_date ; end
29
28
  def <=> other ; is_date?(other) && ruby_date <=> other.ruby_date ; end
30
29
  def eql? d ; self == d ; end
31
30
  def hash ; ruby_date.hash ; end
32
- def is_date? other ; other.is_a? Nydp::Date ; end
33
- def - other ; r2n(ruby_date - (is_date?(other) ? other.ruby_date : other)) ; end
31
+ def is_date? other ; other.is_a? Nydp::Date ; end
32
+ def - other ; r2n(ruby_date - (is_date?(other) ? other.ruby_date : other)) ; end
33
+ def + int ; int.is_a?(Fixnum) ? r2n(ruby_date + int) : r2n(change(*int.to_ruby)) ; end
34
34
 
35
35
  @@pass_through = %i{ monday? tuesday? wednesday? thursday? friday? saturday? sunday? }
36
36
  @@keys = Set.new %i{
@@ -46,15 +46,15 @@ module Nydp
46
46
  def day y, m, d, w ; d ; end
47
47
  def week_day y, m, d, w ; w ; end
48
48
 
49
- def last_year y, m, d, w ; build(y - 1, m, d) ; end
49
+ def last_year y, m, d, w ; ruby_date.prev_year ; end
50
50
  def next_year y, m, d, w ; ruby_date.next_year ; end
51
51
  def beginning_of_year y, m, d, w ; build(y, 1, 1) ; end
52
52
  def end_of_year y, m, d, w ; build(y, 12, 31) ; end
53
53
 
54
- def last_month y, m, d, w ; build(y, m - 1, d) ; end
54
+ def last_month y, m, d, w ; ruby_date.prev_month ; end
55
55
  def next_month y, m, d, w ; ruby_date.next_month ; end
56
56
  def beginning_of_month y, m, d, w ; build(y, m, 1) ; end
57
- def end_of_month y, m, d, w ; build(y, m, 31) ; end
57
+ def end_of_month y, m, d, w ; beginning_of_month(*splat(ruby_date.next_month)) - 1 ; end
58
58
 
59
59
  def last_week y, m, d, w ; ruby_date - 7 ; end
60
60
  def next_week y, m, d, w ; ruby_date + 7 ; end
@@ -75,17 +75,17 @@ module Nydp
75
75
  class_eval "def #{n} * ; ruby_date.#{n} ; end"
76
76
  end
77
77
 
78
- def _nydp_keys ; @@keys.to_a ; end
79
- def dispatch key, y, m, d, w ; self.send(key, y, m, d, w) if _nydp_keys.include?(key) ; end
80
-
81
- def _nydp_get key
82
- key = key.to_s.gsub(/-/, '_').to_sym
83
- y = ruby_date.year
84
- m = ruby_date.month
85
- d = ruby_date.day
86
- w = ruby_date.wday
87
-
88
- r2n(dispatch(key, y, m, d, w))
78
+ def _nydp_keys ; @@keys.to_a ; end
79
+ def dispatch key, y, m, d, w ; self.send(key, y, m, d, w) if _nydp_keys.include?(key) ; end
80
+ def splat date ; [date.year, date.month, date.day, date.wday] ; end
81
+ def lookup key, date ; r2n(dispatch(key.to_s.gsub(/-/, '_').to_sym, *splat(date))) ; end
82
+ def _nydp_get key ; lookup key, ruby_date ; end
83
+ def change amount, attr
84
+ if attr == :day ; (ruby_date + amount)
85
+ elsif attr == :week ; (ruby_date + (7 * amount))
86
+ elsif attr == :month ; (ruby_date >> amount)
87
+ elsif attr == :year ; (ruby_date >> (12 * amount))
88
+ end
89
89
  end
90
90
  end
91
91
  end