interrotron 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -35,7 +35,9 @@ compiled.call(:my_param => 'bar')
35
35
  # Since interrotron is meant for business rules, it handles dates as a
36
36
  # native type as instances of ruby's DateTime class. You can use literals
37
37
  # for that like so:
38
- Interrotron.run('(> #dt{2010-09-04} start_date)', start_date: DateTime.parse('2012-12-12'))
38
+ Interrotron.run('(> #t{2010-09-04} start_date)', start_date: DateTime.parse('2012-12-12').to_time)
39
+ # => true
40
+ Interrotron.run('(> (now) (ago (hours 12)))')
39
41
  # => true
40
42
 
41
43
  # You can, of course, create arbitarily complex exprs
@@ -64,12 +66,11 @@ The following functions and variables are built in to Interrotron (and more are
64
66
  (floor expr) ; equiv to num.floor
65
67
  (ceil expr) ; equiv to num.ceil
66
68
  (round expr) ; equiv to num.round
67
- (to_i expr) ; int conversion
68
- (to_f expr) ; float conversion
69
+ (int expr) ; int conversion
70
+ (float expr) ; float conversion
69
71
  (rand) ; returns a random float between 0 and 1
70
72
  (upcase str) ; uppercases a string
71
73
  (downcase) ; lowercases a string
72
- (now) ; returns the current DateTime
73
74
  (array e1, e2, ...) ; creates an array
74
75
  (max arr) ; returns the largest element of an array
75
76
  (min arr) ; returns the smallest element of an array
@@ -78,6 +79,14 @@ The following functions and variables are built in to Interrotron (and more are
78
79
  (last arr) ; get arr tail
79
80
  (nth pos arr) ; get array at index
80
81
  (member? val arr) ; check if the array has a member with value 'val'
82
+ (now) ; returns the current DateTime
83
+ (seconds n); n, for completeness
84
+ (minutes n); n * secs_in_a_minute
85
+ (hours n); n * secs_in_a_hour
86
+ (months n) ; n * secs_in_a_month
87
+ (ago n) ; yields a time in seconds from now
88
+ (from-now n) ; yields a time in seconds from now
89
+ (time 'str') ; parses a string to a Time
81
90
  ```
82
91
 
83
92
  ## Contributing
data/Rakefile CHANGED
@@ -2,7 +2,8 @@
2
2
  require "bundler/gem_tasks"
3
3
  require "rspec/core/rake_task"
4
4
 
5
- Bundler::GemHelper.install_tasks
5
+ # This seems to deplicate tasks
6
+ #Bundler::GemHelper.install_tasks
6
7
 
7
8
  RSpec::Core::RakeTask.new('spec') do |t|
8
9
  t.rspec_opts = '--tag ~integration'
@@ -12,5 +13,4 @@ RSpec::Core::RakeTask.new('spec:integration') do |t|
12
13
  t.pattern = 'spec/integration/*_spec.rb'
13
14
  end
14
15
 
15
- task :default => :spec
16
-
16
+ task :default => :spec
data/bin/interrotron ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'interrotron'
4
+
5
+ puts Interrotron.run(ARGV[0]).inspect
data/interrotron.gemspec CHANGED
@@ -9,7 +9,8 @@ Gem::Specification.new do |gem|
9
9
  gem.homepage = ""
10
10
 
11
11
  gem.files = `git ls-files`.split($\)
12
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
12
+ gem.executables << 'interrotron'
13
+ #gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
14
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
15
  gem.name = "interrotron"
15
16
  gem.require_paths = ["lib"]
data/lib/interrotron.rb CHANGED
@@ -44,17 +44,17 @@ class Interrotron
44
44
  end
45
45
 
46
46
  TOKENS = [
47
- [:lpar, /\(/],
48
- [:rpar, /\)/],
49
- [:fn, /fn/],
50
- [:var, /[A-Za-z_><\+\>\<\!\=\*\/\%\-\?]+/],
51
- [:num, /(\-?[0-9]+(\.[0-9]+)?)/,
47
+ [:lpar, /\A\(/],
48
+ [:rpar, /\A\)/],
49
+ [:fn, /\Afn/],
50
+ [:var, /\A[A-Za-z_><\+\>\<\!\=\*\/\%\-\?]+/],
51
+ [:num, /\A(\-?[0-9]+(\.[0-9]+)?)/,
52
52
  {cast: proc {|v| v =~ /\./ ? v.to_f : v.to_i }}],
53
- [:datetime, /#dt\{([^\{]+)\}/,
54
- {capture: 1, cast: proc {|v| DateTime.parse(v) }}],
55
- [:spc, /\s+/, {discard: true}],
56
- [:str, /"([^"\\]*(\\.[^"\\]*)*)"/, {capture: 1}],
57
- [:str, /'([^'\\]*(\\.[^'\\]*)*)'/, {capture: 1}]
53
+ [:time, /\A#t\{([^\{]+)\}/,
54
+ {capture: 1, cast: proc {|v| DateTime.parse(v).to_time }}],
55
+ [:spc, /\A\s+/, {discard: true}],
56
+ [:str, /\A"([^"\\]*(\\.[^"\\]*)*)"/, {capture: 1}],
57
+ [:str, /\A'([^'\\]*(\\.[^'\\]*)*)'/, {capture: 1}]
58
58
  ]
59
59
 
60
60
  # Quote a ruby variable as a interrotron one
@@ -76,6 +76,7 @@ class Interrotron
76
76
  },
77
77
  'and' => Macro.new {|i,*args| args.all? {|a| i.iro_eval(a)} ? args.last : qvar('false') },
78
78
  'or' => Macro.new {|i,*args| args.detect {|a| i.iro_eval(a) } || qvar('false') },
79
+ 'apply' => proc {|fn,arr| fn.call(*arr) },
79
80
  'array' => proc {|*args| args},
80
81
  'identity' => proc {|a| a},
81
82
  'not' => proc {|a| !a},
@@ -104,13 +105,22 @@ class Interrotron
104
105
  'nth' => proc {|pos, arr| arr[pos]},
105
106
  'length' => proc {|arr| arr.length},
106
107
  'member?' => proc {|v,arr| arr.member? v},
107
- 'to_i' => proc {|a| a.to_i},
108
- 'to_f' => proc {|a| a.to_f},
109
- 'rand' => proc { rand },
108
+ 'int' => proc {|a| a.to_i},
109
+ 'float' => proc {|a| a.to_f},
110
+ 'time' => proc {|s| DateTime.parse(s).to_time},
111
+ 'rand' => proc {|n| rand n },
112
+ 'str' => proc {|*args| args.reduce("") {|m,a| m + a.to_s}},
113
+ 'strip' => proc {|s| s.strip},
110
114
  'upcase' => proc {|a| a.upcase},
111
115
  'downcase' => proc {|a| a.downcase},
112
- 'now' => proc { DateTime.now },
113
- 'str' => proc {|*args| args.reduce("") {|m,a| m + a.to_s}}
116
+ 'now' => proc { Time.now },
117
+ 'seconds' => proc {|n| n.to_i},
118
+ 'minutes' => proc {|n| n.to_i * 60},
119
+ 'hours' => proc {|n| n.to_i * 3600 },
120
+ 'days' => proc {|n| n.to_i * 86400},
121
+ 'months' => proc {|n| n.to_i * 2592000},
122
+ 'ago' => proc {|t| Time.now - t},
123
+ 'from-now' => proc {|t| Time.now + t}
114
124
  })
115
125
 
116
126
  def initialize(vars={},max_ops=nil)
@@ -131,7 +141,7 @@ class Interrotron
131
141
  matched_any = TOKENS.any? {|name,matcher,opts|
132
142
  opts ||= {}
133
143
  matches = matcher.match(str)
134
- if !matches || !matches.pre_match.empty?
144
+ if !matches
135
145
  false
136
146
  else
137
147
  str = str[matches[0].length..-1]
@@ -1,3 +1,3 @@
1
1
  class Interrotron
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -59,9 +59,22 @@ describe "running" do
59
59
  end
60
60
  end
61
61
 
62
- describe "date times" do
62
+ describe "times" do
63
63
  it "should parse and compare them properly" do
64
- run('(> #dt{2010-09-04} start_date)', start_date: DateTime.parse('2012-12-12'))
64
+ run('(> #t{2010-09-04} start_date)', start_date: DateTime.parse('2012-12-12').to_time)
65
+ end
66
+ it "should understand days, minutes, seconds, and hours, as integers" do
67
+ run("(+ (days 1) (minutes 1) (hours 1) (seconds 1))").should == 90061
68
+ end
69
+
70
+ it "should add the time using from-now" do
71
+ n = Time.now
72
+ Time.should_receive(:now).twice().and_return(n)
73
+ run("(from-now (minutes 1))").to_i.should == (Time.now + 60).to_i
74
+ end
75
+
76
+ it "should compare times using convenience multipliers correctly" do
77
+ run('(> (now) (ago (hours 12)))').should be_true
65
78
  end
66
79
  end
67
80
 
@@ -171,4 +184,28 @@ describe "running" do
171
184
  run("").should be_nil
172
185
  end
173
186
  end
187
+
188
+ describe "apply macro" do
189
+ it "should spat an array into another function" do
190
+ run("(apply + (array 1 2 3))").should == 6
191
+ end
192
+ end
193
+
194
+ describe "conversions" do
195
+ it "should convert ints" do
196
+ res = run("(int '2')")
197
+ res.should == 2
198
+ res.should be_a(Fixnum)
199
+ end
200
+
201
+ it "should convert floats" do
202
+ res = run("(float '2.5')")
203
+ res.should == 2.5
204
+ res.should be_a(Float)
205
+ end
206
+
207
+ it "should parse dates and times" do
208
+ run("(time '2012-05-01')").should == DateTime.parse("2012-05-01").to_time
209
+ end
210
+ end
174
211
  end
metadata CHANGED
@@ -1,31 +1,32 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: interrotron
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
5
- prerelease:
4
+ prerelease:
5
+ version: 0.0.5
6
6
  platform: ruby
7
7
  authors:
8
8
  - Andrew Cholakian
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-27 00:00:00.000000000 Z
12
+ date: 2012-05-27 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70187372115860 !ruby/object:Gem::Requirement
17
- none: false
16
+ version_requirements: &2056 !ruby/object:Gem::Requirement
18
17
  requirements:
19
18
  - - ~>
20
19
  - !ruby/object:Gem::Version
21
20
  version: '2.6'
22
- type: :development
21
+ none: false
22
+ requirement: *2056
23
23
  prerelease: false
24
- version_requirements: *70187372115860
24
+ type: :development
25
25
  description: A tiny, embeddable, lisp VM
26
26
  email:
27
27
  - andrew@andrewvc.com
28
- executables: []
28
+ executables:
29
+ - interrotron
29
30
  extensions: []
30
31
  extra_rdoc_files: []
31
32
  files:
@@ -35,33 +36,35 @@ files:
35
36
  - LICENSE
36
37
  - README.md
37
38
  - Rakefile
39
+ - bin/interrotron
38
40
  - interrotron.gemspec
39
41
  - lib/interrotron.rb
40
42
  - lib/interrotron/version.rb
41
43
  - spec/interrotron_spec.rb
42
44
  homepage: ''
43
45
  licenses: []
44
- post_install_message:
46
+ post_install_message:
45
47
  rdoc_options: []
46
48
  require_paths:
47
49
  - lib
48
50
  required_ruby_version: !ruby/object:Gem::Requirement
49
- none: false
50
51
  requirements:
51
52
  - - ! '>='
52
53
  - !ruby/object:Gem::Version
53
54
  version: '0'
54
- required_rubygems_version: !ruby/object:Gem::Requirement
55
55
  none: false
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
57
  requirements:
57
58
  - - ! '>='
58
59
  - !ruby/object:Gem::Version
59
60
  version: '0'
61
+ none: false
60
62
  requirements: []
61
- rubyforge_project:
62
- rubygems_version: 1.8.10
63
- signing_key:
63
+ rubyforge_project:
64
+ rubygems_version: 1.8.9
65
+ signing_key:
64
66
  specification_version: 3
65
67
  summary: A lisp VM meant to run with guarantees on execution for business rules
66
68
  test_files:
67
69
  - spec/interrotron_spec.rb
70
+ ...