nydp 0.4.2 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +44 -0
  3. data/lib/lisp/core-010-precompile.nydp +13 -16
  4. data/lib/lisp/core-012-utils.nydp +3 -2
  5. data/lib/lisp/core-015-documentation.nydp +54 -23
  6. data/lib/lisp/core-017-builtin-dox.nydp +14 -12
  7. data/lib/lisp/core-020-utils.nydp +5 -5
  8. data/lib/lisp/core-030-syntax.nydp +166 -72
  9. data/lib/lisp/core-035-flow-control.nydp +38 -11
  10. data/lib/lisp/core-037-list-utils.nydp +12 -0
  11. data/lib/lisp/core-039-module.nydp +24 -0
  12. data/lib/lisp/core-040-utils.nydp +32 -12
  13. data/lib/lisp/core-041-string-utils.nydp +25 -1
  14. data/lib/lisp/core-042-date-utils.nydp +21 -1
  15. data/lib/lisp/core-043-list-utils.nydp +96 -64
  16. data/lib/lisp/core-070-prefix-list.nydp +1 -1
  17. data/lib/lisp/core-080-pretty-print.nydp +57 -17
  18. data/lib/lisp/core-090-hook.nydp +35 -1
  19. data/lib/lisp/core-100-utils.nydp +82 -2
  20. data/lib/lisp/core-110-hash-utils.nydp +56 -2
  21. data/lib/lisp/core-120-settings.nydp +16 -5
  22. data/lib/lisp/core-130-validations.nydp +51 -0
  23. data/lib/lisp/core-900-benchmarking.nydp +78 -20
  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/date-examples.nydp +54 -1
  32. data/lib/lisp/tests/destructuring-examples.nydp +46 -14
  33. data/lib/lisp/tests/detect-examples.nydp +12 -0
  34. data/lib/lisp/tests/dp-examples.nydp +24 -0
  35. data/lib/lisp/tests/each-tests.nydp +5 -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/explain-mac-examples.nydp +1 -1
  39. data/lib/lisp/tests/filter-forms-examples.nydp +15 -0
  40. data/lib/lisp/tests/hash-examples.nydp +25 -1
  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/module-examples.nydp +10 -0
  45. data/lib/lisp/tests/multi-assign-examples.nydp +6 -0
  46. data/lib/lisp/tests/parser-tests.nydp +25 -0
  47. data/lib/lisp/tests/pretty-print-tests.nydp +17 -14
  48. data/lib/lisp/tests/set-difference-examples.nydp +8 -0
  49. data/lib/lisp/tests/settings-examples.nydp +17 -1
  50. data/lib/lisp/tests/string-tests.nydp +70 -1
  51. data/lib/lisp/tests/syntax-tests.nydp +5 -1
  52. data/lib/lisp/tests/to-integer-examples.nydp +16 -0
  53. data/lib/lisp/tests/validation-examples.nydp +15 -0
  54. data/lib/nydp.rb +10 -3
  55. data/lib/nydp/assignment.rb +10 -3
  56. data/lib/nydp/builtin.rb +1 -1
  57. data/lib/nydp/builtin/abs.rb +8 -0
  58. data/lib/nydp/builtin/date.rb +15 -1
  59. data/lib/nydp/builtin/error.rb +1 -1
  60. data/lib/nydp/builtin/hash.rb +24 -1
  61. data/lib/nydp/builtin/inspect.rb +1 -1
  62. data/lib/nydp/builtin/plus.rb +10 -2
  63. data/lib/nydp/builtin/random_string.rb +2 -2
  64. data/lib/nydp/builtin/{car.rb → regexp.rb} +2 -2
  65. data/lib/nydp/builtin/ruby_wrap.rb +72 -0
  66. data/lib/nydp/builtin/string_match.rb +2 -2
  67. data/lib/nydp/builtin/string_pad_left.rb +7 -0
  68. data/lib/nydp/builtin/string_pad_right.rb +7 -0
  69. data/lib/nydp/builtin/string_replace.rb +3 -3
  70. data/lib/nydp/builtin/string_split.rb +4 -3
  71. data/lib/nydp/builtin/to_integer.rb +23 -0
  72. data/lib/nydp/builtin/to_string.rb +2 -9
  73. data/lib/nydp/builtin/type_of.rb +9 -6
  74. data/lib/nydp/closure.rb +0 -3
  75. data/lib/nydp/cond.rb +23 -1
  76. data/lib/nydp/context_symbol.rb +14 -6
  77. data/lib/nydp/core.rb +36 -28
  78. data/lib/nydp/core_ext.rb +21 -5
  79. data/lib/nydp/date.rb +26 -18
  80. data/lib/nydp/function_invocation.rb +34 -26
  81. data/lib/nydp/helper.rb +35 -3
  82. data/lib/nydp/interpreted_function.rb +68 -40
  83. data/lib/nydp/literal.rb +1 -1
  84. data/lib/nydp/pair.rb +22 -5
  85. data/lib/nydp/parser.rb +11 -7
  86. data/lib/nydp/string_atom.rb +3 -4
  87. data/lib/nydp/symbol_lookup.rb +7 -7
  88. data/lib/nydp/tokeniser.rb +2 -2
  89. data/lib/nydp/truth.rb +10 -10
  90. data/lib/nydp/version.rb +1 -1
  91. data/lib/nydp/vm.rb +7 -0
  92. data/nydp.gemspec +2 -4
  93. data/spec/date_spec.rb +93 -0
  94. data/spec/embedded_spec.rb +12 -12
  95. data/spec/foreign_hash_spec.rb +14 -2
  96. data/spec/hash_non_hash_behaviour_spec.rb +7 -7
  97. data/spec/hash_spec.rb +24 -2
  98. data/spec/nydp_spec.rb +14 -2
  99. data/spec/pair_spec.rb +3 -1
  100. data/spec/parser_spec.rb +31 -20
  101. data/spec/rand_spec.rb +3 -3
  102. data/spec/spec_helper.rb +10 -1
  103. metadata +24 -37
  104. data/lib/nydp/builtin/cdr.rb +0 -7
  105. data/lib/nydp/builtin/cons.rb +0 -9
@@ -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
data/lib/nydp/closure.rb CHANGED
@@ -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
data/lib/nydp/cond.rb CHANGED
@@ -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
data/lib/nydp/core.rb CHANGED
@@ -25,9 +25,11 @@ 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
+ Symbol.mk(:log , ns).assign(Nydp::Builtin::RubyWrap::Log.instance )
32
+
31
33
  Symbol.mk(:+, ns).assign(Nydp::Builtin::Plus.instance)
32
34
  Symbol.mk(:-, ns).assign(Nydp::Builtin::Minus.instance)
33
35
  Symbol.mk(:*, ns).assign(Nydp::Builtin::Times.instance)
@@ -47,34 +49,40 @@ module Nydp
47
49
  Symbol.mk(:nil, ns).assign Nydp::NIL
48
50
  Symbol.mk(:rand, ns).assign Nydp::Builtin::Rand.instance
49
51
  Symbol.mk(:sort, ns).assign Nydp::Builtin::Sort.instance
52
+ Symbol.mk(:abs, ns).assign Nydp::Builtin::Abs.instance
50
53
  Symbol.mk(:sqrt, ns).assign Nydp::Builtin::Sqrt.instance
51
54
  Symbol.mk(:t, ns).assign Nydp::T
52
55
  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(:"vm-info", ns).assign Nydp::Builtin::VmInfo.instance
75
- Symbol.mk(:"pre-compile" , ns).assign Nydp::Builtin::PreCompile.instance
76
- Symbol.mk(:"script-run" , ns).assign Nydp::Builtin::ScriptRun.instance
77
- Symbol.mk(:"**" , ns).assign Nydp::Builtin::MathPower.instance
56
+ Symbol.mk(:ensuring , ns).assign(Nydp::Builtin::Ensuring.instance)
57
+ Symbol.mk(:inspect , ns).assign(Nydp::Builtin::Inspect.instance)
58
+ Symbol.mk(:comment , ns).assign(Nydp::Builtin::Comment.instance)
59
+ Symbol.mk("handle-error" , ns).assign(Nydp::Builtin::HandleError.instance)
60
+ Symbol.mk("parse-in-string" , ns).assign(Nydp::Builtin::ParseInString.instance)
61
+ Symbol.mk("random-string" , ns).assign(Nydp::Builtin::RandomString.instance)
62
+ Symbol.mk("regexp" , ns).assign(Nydp::Builtin::Regexp.instance)
63
+ Symbol.mk("to-string" , ns).assign(Nydp::Builtin::ToString.instance)
64
+ Symbol.mk("to-integer" , ns).assign(Nydp::Builtin::ToInteger.instance)
65
+ Symbol.mk("string-length" , ns).assign(Nydp::Builtin::StringLength.instance)
66
+ Symbol.mk("string-replace" , ns).assign(Nydp::Builtin::StringReplace.instance)
67
+ Symbol.mk("string-match" , ns).assign(Nydp::Builtin::StringMatch.instance)
68
+ Symbol.mk("string-split" , ns).assign(Nydp::Builtin::StringSplit.instance)
69
+ Symbol.mk("string/pad-left" , ns).assign(Nydp::Builtin::StringPadLeft.instance)
70
+ Symbol.mk("string/pad-right" , ns).assign(Nydp::Builtin::StringPadRight.instance)
71
+ Symbol.mk("time" , ns).assign(Nydp::Builtin::Time.instance)
72
+ Symbol.mk("thread-locals" , ns).assign(Nydp::Builtin::ThreadLocals.instance)
73
+ Symbol.mk("type-of" , ns).assign(Nydp::Builtin::TypeOf.instance)
74
+ Symbol.mk(:"eq?" , ns).assign(Nydp::Builtin::IsEqual.instance)
75
+ Symbol.mk(:"cdr-set" , ns).assign(Nydp::Builtin::CdrSet.instance)
76
+ Symbol.mk(:"hash-get" , ns).assign(Nydp::Builtin::HashGet.instance)
77
+ Symbol.mk(:"hash-set" , ns).assign(Nydp::Builtin::HashSet.instance)
78
+ Symbol.mk(:"hash-keys" , ns).assign(Nydp::Builtin::HashKeys.instance)
79
+ Symbol.mk(:"hash-key?" , ns).assign(Nydp::Builtin::HashKeyPresent.instance)
80
+ Symbol.mk(:"hash-merge" , ns).assign(Nydp::Builtin::HashMerge.instance)
81
+ Symbol.mk(:"hash-slice" , ns).assign(Nydp::Builtin::HashSlice.instance)
82
+ Symbol.mk(:"vm-info" , ns).assign Nydp::Builtin::VmInfo.instance
83
+ Symbol.mk(:"pre-compile" , ns).assign Nydp::Builtin::PreCompile.instance
84
+ Symbol.mk(:"script-run" , ns).assign Nydp::Builtin::ScriptRun.instance
85
+ Symbol.mk(:"**" , ns).assign Nydp::Builtin::MathPower.instance
78
86
  Symbol.mk(:"⌊" , ns).assign Nydp::Builtin::MathFloor.instance
79
87
  Symbol.mk(:"math-floor" , ns).assign Nydp::Builtin::MathFloor.instance
80
88
  Symbol.mk(:"⌈" , ns).assign Nydp::Builtin::MathCeiling.instance
data/lib/nydp/core_ext.rb CHANGED
@@ -1,8 +1,18 @@
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
7
+ end
8
+
9
+ class Method
10
+ include Nydp::Converter
11
+ def invoke_1 vm ; vm.push_arg call._nydp_wrapper ; end
12
+ def invoke_2 vm, a0 ; vm.push_arg call(n2r(a0))._nydp_wrapper ; end
13
+ def invoke_3 vm, a0, a1 ; vm.push_arg call(n2r(a0), n2r(a1))._nydp_wrapper ; end
14
+ def invoke_4 vm, a0, a1, a2 ; vm.push_arg call(n2r(a0), n2r(a1), n2r(a2))._nydp_wrapper ; end
15
+ def invoke vm, args ; vm.push_arg call(*(args.map { |a| n2r a}))._nydp_wrapper ; end
6
16
  end
7
17
 
8
18
  class NilClass
@@ -29,8 +39,14 @@ class ::Array
29
39
  def _nydp_wrapper ; Nydp::Pair.from_list map &:_nydp_wrapper ; end
30
40
  end
31
41
 
42
+ class ::Object
43
+ def to_ruby ; self ; end
44
+ end
45
+
32
46
  class ::String
33
- def _nydp_wrapper ; Nydp::StringAtom.new self ; end
47
+ # def _nydp_wrapper ; Nydp::StringAtom.new self ; end
48
+ def as_method_name ; self.gsub(/-/, '_').to_sym ; end
49
+ def nydp_type ; :string ; end
34
50
  end
35
51
 
36
52
  class ::Hash
data/lib/nydp/date.rb CHANGED
@@ -18,19 +18,20 @@ module Nydp
18
18
 
19
19
  def initialize ruby_date ; @ruby_date = ruby_date ; end
20
20
 
21
+ def to_date ; ruby_date ; end
21
22
  def to_s ; ruby_date.to_s ; end
22
23
  def to_ruby ; ruby_date ; end
23
24
  def inspect ; ruby_date.inspect ; end
24
25
  def nydp_type ; :date ; end
25
- def + int ; r2n(ruby_date + int) ; end
26
26
  def > other ; is_date?(other) && ruby_date > other.ruby_date ; end
27
27
  def < other ; is_date?(other) && ruby_date < other.ruby_date ; end
28
28
  def == other ; is_date?(other) && ruby_date == other.ruby_date ; end
29
29
  def <=> other ; is_date?(other) && ruby_date <=> other.ruby_date ; end
30
30
  def eql? d ; self == d ; end
31
31
  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
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
34
+ def + int ; int.is_a?(Integer) ? r2n(ruby_date + int) : r2n(change(*int.to_ruby)) ; end
34
35
 
35
36
  @@pass_through = %i{ monday? tuesday? wednesday? thursday? friday? saturday? sunday? }
36
37
  @@keys = Set.new %i{
@@ -38,7 +39,7 @@ module Nydp
38
39
  last_year next_year beginning_of_year end_of_year
39
40
  last_month next_month beginning_of_month end_of_month
40
41
  last_week next_week beginning_of_week end_of_week
41
- yesterday tomorrow
42
+ yesterday tomorrow age
42
43
  } + @@pass_through
43
44
 
44
45
  def year y, m, d, w ; y ; end
@@ -46,15 +47,15 @@ module Nydp
46
47
  def day y, m, d, w ; d ; end
47
48
  def week_day y, m, d, w ; w ; end
48
49
 
49
- def last_year y, m, d, w ; build(y - 1, m, d) ; end
50
+ def last_year y, m, d, w ; ruby_date.prev_year ; end
50
51
  def next_year y, m, d, w ; ruby_date.next_year ; end
51
52
  def beginning_of_year y, m, d, w ; build(y, 1, 1) ; end
52
53
  def end_of_year y, m, d, w ; build(y, 12, 31) ; end
53
54
 
54
- def last_month y, m, d, w ; build(y, m - 1, d) ; end
55
+ def last_month y, m, d, w ; ruby_date.prev_month ; end
55
56
  def next_month y, m, d, w ; ruby_date.next_month ; end
56
57
  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
58
+ def end_of_month y, m, d, w ; beginning_of_month(*splat(ruby_date.next_month)) - 1 ; end
58
59
 
59
60
  def last_week y, m, d, w ; ruby_date - 7 ; end
60
61
  def next_week y, m, d, w ; ruby_date + 7 ; end
@@ -64,21 +65,28 @@ module Nydp
64
65
  def yesterday y, m, d, w ; ruby_date - 1 ; end
65
66
  def tomorrow y, m, d, w ; ruby_date + 1 ; end
66
67
 
68
+ def age y,m,d,w # args not used
69
+ interval = (::Date.today - ruby_date) / 365.0
70
+ age_in_years = interval.to_i
71
+ extra_months = (12 * (interval - age_in_years)).to_i
72
+ { years: age_in_years, months: extra_months }
73
+ end
74
+
67
75
  @@pass_through.each do |n|
68
76
  class_eval "def #{n} * ; ruby_date.#{n} ; end"
69
77
  end
70
78
 
71
- def _nydp_keys ; @@keys.to_a ; end
72
- def dispatch key, y, m, d, w ; self.send(key, y, m, d, w) if _nydp_keys.include?(key) ; end
73
-
74
- def _nydp_get key
75
- key = key.to_s.gsub(/-/, '_').to_sym
76
- y = ruby_date.year
77
- m = ruby_date.month
78
- d = ruby_date.day
79
- w = ruby_date.wday
80
-
81
- r2n(dispatch(key, y, m, d, w))
79
+ def _nydp_keys ; @@keys.to_a ; end
80
+ def dispatch key, y, m, d, w ; self.send(key, y, m, d, w) if _nydp_keys.include?(key) ; end
81
+ def splat date ; [date.year, date.month, date.day, date.wday] ; end
82
+ def lookup key, date ; r2n(dispatch(key.to_s.gsub(/-/, '_').to_sym, *splat(date))) ; end
83
+ def _nydp_get key ; lookup key, ruby_date ; end
84
+ def change amount, attr
85
+ if attr == :day ; (ruby_date + amount)
86
+ elsif attr == :week ; (ruby_date + (7 * amount))
87
+ elsif attr == :month ; (ruby_date >> amount)
88
+ elsif attr == :year ; (ruby_date >> (12 * amount))
89
+ end
82
90
  end
83
91
  end
84
92
  end
@@ -13,9 +13,8 @@ module Nydp
13
13
 
14
14
  class Base
15
15
  include Helper
16
- def initialize source_expression, sig=nil
17
- @source_expression = source_expression
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
@@ -24,7 +23,7 @@ module Nydp
24
23
  raise
25
24
  else
26
25
  if e.is_a?(NoMethodError) && !f.respond_to?(invoker)
27
- raise InvocationFailed.new("#{f.inspect} is not a function: args were #{args.inspect}")
26
+ raise InvocationFailed.new("#{f.inspect} is not a function: args were #{args.inspect} in #{source.inspect}")
28
27
  else
29
28
  msg = args.map { |a| " #{a.inspect}"}.join("\n")
30
29
  msg = "failed to execute invocation #{f.inspect}\n#{msg}"
@@ -35,9 +34,14 @@ module Nydp
35
34
  end
36
35
  end
37
36
 
38
- def inspect ; source.inspect ; end
39
- def source ; @source_expression ; end
40
- def to_s ; source.to_s ; end
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, source_expression
91
- super source_expression
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 ; @source.inspect ; end
331
- def to_s ; @source.to_s ; end
338
+ def inspect ; @function_instruction.inspect ; end
339
+ def to_s ; @source.to_s ; end
332
340
  end
333
341
  end