expressive 0.0.2 → 0.0.3

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.
data/Gemfile.lock CHANGED
@@ -1,15 +1,19 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- expressive (0.0.2)
4
+ expressive (0.0.3)
5
5
  awesome_print (~> 1.0.2)
6
6
  polyglot (~> 0.3.3)
7
+ rest-client (~> 1.6.7)
7
8
  treetop (~> 1.4.10)
8
9
 
9
10
  GEM
10
11
  remote: http://rubygems.org/
11
12
  specs:
13
+ addressable (2.3.2)
12
14
  awesome_print (1.0.2)
15
+ coderay (1.0.7)
16
+ crack (0.3.1)
13
17
  diff-lcs (1.1.3)
14
18
  ffi (1.1.5)
15
19
  guard (1.3.2)
@@ -22,7 +26,13 @@ GEM
22
26
  rb-fchange (~> 0.0.5)
23
27
  rb-fsevent (~> 0.9.1)
24
28
  rb-inotify (~> 0.8.8)
29
+ method_source (0.8)
30
+ mime-types (1.19)
25
31
  polyglot (0.3.3)
32
+ pry (0.9.10)
33
+ coderay (~> 1.0.5)
34
+ method_source (~> 0.8)
35
+ slop (~> 3.3.1)
26
36
  rb-fchange (0.0.5)
27
37
  ffi
28
38
  rb-fsevent (0.9.1)
@@ -30,6 +40,8 @@ GEM
30
40
  ffi (>= 0.5.0)
31
41
  rdoc (3.12)
32
42
  json (~> 1.4)
43
+ rest-client (1.6.7)
44
+ mime-types (>= 1.16)
33
45
  rspec (2.11.0)
34
46
  rspec-core (~> 2.11.0)
35
47
  rspec-expectations (~> 2.11.0)
@@ -39,10 +51,14 @@ GEM
39
51
  diff-lcs (~> 1.1.3)
40
52
  rspec-mocks (2.11.2)
41
53
  ruby_gntp (0.3.4)
54
+ slop (3.3.2)
42
55
  thor (0.16.0)
43
- treetop (1.4.10)
56
+ treetop (1.4.11)
44
57
  polyglot
45
58
  polyglot (>= 0.3.1)
59
+ webmock (1.8.11)
60
+ addressable (>= 2.2.7)
61
+ crack (>= 0.1.7)
46
62
 
47
63
  PLATFORMS
48
64
  ruby
@@ -52,6 +68,8 @@ DEPENDENCIES
52
68
  expressive!
53
69
  guard (~> 1.3.2)
54
70
  guard-rspec (~> 1.2.1)
71
+ pry (~> 0.9.10)
55
72
  rdoc (~> 3.12)
56
73
  rspec (~> 2.11.0)
57
74
  ruby_gntp (~> 0.3.4)
75
+ webmock (~> 1.8.11)
data/Guardfile CHANGED
@@ -1,30 +1,9 @@
1
1
  # A sample Guardfile
2
2
  # More info at https://github.com/guard/guard#readme
3
3
 
4
- guard 'bundler' do
5
- watch('Gemfile')
6
- # Uncomment next line if Gemfile contain `gemspec' command
7
- # watch(/^.+\.gemspec/)
8
- end
9
-
10
- guard 'rspec', :cli => "--color --format nested --fail-fast", :version => 2 do
4
+ guard 'rspec', :cli => "--color --format nested --fail-fast", :version => 2, :notification => false do
11
5
  watch(%r{^spec/.+_spec\.rb$})
12
6
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
13
- watch('spec/spec_helper.rb') { "spec" }
14
-
15
- # Rails example
16
- watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
17
- watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
18
- watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
19
- watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
20
- watch('config/routes.rb') { "spec/routing" }
21
- watch('app/controllers/application_controller.rb') { "spec/controllers" }
22
-
23
- # Capybara request specs
24
- watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
25
-
26
- # Turnip features and steps
27
- watch(%r{^spec/acceptance/(.+)\.feature$})
28
- watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
7
+ watch('spec/spec_helper.rb') { "rspec" }
29
8
  end
30
9
 
data/expressive.gemspec CHANGED
@@ -22,8 +22,11 @@ Gem::Specification.new do |gem|
22
22
  gem.add_development_dependency "bundler", "~> 1.1.4"
23
23
  gem.add_development_dependency "guard", "~> 1.3.2"
24
24
  gem.add_development_dependency "guard-rspec", "~> 1.2.1"
25
+ gem.add_development_dependency "webmock", "~> 1.8.11"
26
+ gem.add_development_dependency "pry", "~> 0.9.10"
25
27
 
26
28
  gem.add_dependency "polyglot", "~> 0.3.3"
27
29
  gem.add_dependency "treetop", "~> 1.4.10"
28
30
  gem.add_dependency "awesome_print", "~> 1.0.2"
31
+ gem.add_dependency "rest-client", "~> 1.6.7"
29
32
  end
@@ -1,3 +1,3 @@
1
1
  module Expressive
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/expressive.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'polyglot'
2
2
  require 'treetop'
3
3
  require 'awesome_print'
4
+ require 'rest_client'
4
5
  require File.join(File.dirname(__FILE__), 'scope')
5
6
 
6
7
  Treetop.load File.join(File.dirname(__FILE__), 'expressive_grammar.treetop')
@@ -15,30 +16,39 @@ module Expressive
15
16
  @parser ||= ::ExpressiveParser.new
16
17
  @parser.parse(expressions)
17
18
  end
18
- end
19
19
 
20
+ def self.all_symbols
21
+ %w(+ - * / = set sum post >= > < <= and or if)
22
+ end
23
+ end
20
24
 
21
- module Boolean
25
+ module Boolean
22
26
  def eval(scope)
23
- 'true' == text_value
27
+ 'true' == text_value
24
28
  end
25
29
  end
26
30
 
27
- module IntegerValue
28
- def eval(scope)
31
+ module IntegerValue
32
+ def eval(scope)
29
33
  text_value.to_i
30
34
  end
31
35
  end
32
36
 
33
- module FloatValue
34
- def eval(scope)
35
- text_value.to_f
37
+ module FloatValue
38
+ def eval(scope)
39
+ text_value.to_f
40
+ end
41
+ end
42
+
43
+ module StringValue
44
+ def eval(scope)
45
+ text_value.gsub('"', '')
36
46
  end
37
47
  end
38
48
 
39
49
  class Program < Treetop::Runtime::SyntaxNode
40
50
  def eval(scope)
41
- elements.map {|e|
51
+ elements.map {|e|
42
52
  e.eval(scope)
43
53
  }.last
44
54
  end
@@ -83,7 +93,7 @@ class Function
83
93
  end
84
94
 
85
95
  def call(scope, statements)
86
- parameters = statements.map {|c| c.eval(scope)}
96
+ parameters = statements.map {|c| c.eval(scope)}
87
97
  @block.call(*parameters)
88
98
  end
89
99
  end
@@ -17,13 +17,17 @@ grammar Expressive
17
17
  end
18
18
 
19
19
  rule value
20
- (boolean / number)
20
+ (string / boolean / number)
21
21
  end
22
22
 
23
23
  rule word
24
24
  [a-zA-Z]+
25
25
  end
26
26
 
27
+ rule string
28
+ '"' ([^"\\] / "\\" . )* '"' <StringValue>
29
+ end
30
+
27
31
  rule number
28
32
  ( float / integer )
29
33
  end
data/lib/scope.rb CHANGED
@@ -25,14 +25,13 @@ class Scope
25
25
  @symbols
26
26
  end
27
27
 
28
- def define(name, &block)
29
- self[name] = Function.new(&block)
28
+ def define(name, &block)
29
+ self[name] = Function.new(&block)
30
30
  end
31
31
 
32
- def syntax(name, &block)
33
- self[name] = Syntax.new(&block)
32
+ def syntax(name, &block)
33
+ self[name] = Syntax.new(&block)
34
34
  end
35
-
36
35
  end
37
36
 
38
37
  class TopLevel < Scope
@@ -43,11 +42,33 @@ class TopLevel < Scope
43
42
  scope[cells.first.text_value] = cells[1].eval(scope)
44
43
  end
45
44
 
45
+ syntax('post') do |scope, cells|
46
+ uri = cells.shift.text_value.gsub('"', '')
47
+ payload = {}
48
+ cells.each do |key|
49
+ payload[key.text_value] = scope[key.text_value]
50
+ end
51
+ begin
52
+ response = RestClient.post uri, payload
53
+ scope = scope.merge(response) if response.is_a?(Hash)
54
+ rescue RestClient::Exception => e
55
+ scope['_errors'] = e.message
56
+ end
57
+ scope
58
+ end
59
+
46
60
  define('+') {|a,b| a.to_f + b.to_f }
47
61
  define('-') {|a,b| a.to_f - b.to_f }
48
62
  define('*') {|a,b| a.to_f * b.to_f }
49
63
  define('/') {|a,b| a.to_f / b.to_f }
50
64
  define('=') {|a,b| a == b }
51
- define('sum') {|*args| args.flatten.map(&:to_f).reduce(:+) }
65
+ define('>') {|a,b| a.to_f > b.to_f }
66
+ define('<') {|a,b| a.to_f < b.to_f }
67
+ define('>=') {|a,b| a.to_f >= b.to_f }
68
+ define('<=') {|a,b| a.to_f <= b.to_f }
69
+ define('and') {|a,b| !!a && !!b }
70
+ define('or') {|a,b| !!a || !!b }
71
+ define('sum') { |*args| args.flatten.map(&:to_f).reduce(:+) }
72
+ define('if') { |*args| args.compact!; args[0] ? args[1] : args[2] }
52
73
  end
53
74
  end
@@ -4,7 +4,11 @@ describe "Expressive" do
4
4
  before(:each) do
5
5
  @scope = TopLevel.new
6
6
  end
7
-
7
+
8
+ describe "all_symbols" do
9
+ it { Expressive.all_symbols.should =~ %w(+ - * / = set sum post >= > < <= and or if) }
10
+ end
11
+
8
12
  describe "understands booleans" do
9
13
  it { Expressive.run("true").should eql true }
10
14
  it { Expressive.run("false").should eql false }
@@ -12,7 +16,14 @@ describe "Expressive" do
12
16
 
13
17
  describe "understands numbers" do
14
18
  it { Expressive.run("5").should eql 5 }
15
- it { Expressive.run("5.5").should eql 5.5 }
19
+ it { Expressive.run("5.5").should eql 5.5 }
20
+ end
21
+
22
+ describe "understands string literals" do
23
+ it { Expressive.run('"hello world "').should eql "hello world " }
24
+ it { Expressive.run('"hello world 2012"').should eql "hello world 2012" }
25
+ it { Expressive.run('"hello world 2.5"').should eql "hello world 2.5" }
26
+ it { Expressive.run('"hello world false"').should eql "hello world false" }
16
27
  end
17
28
 
18
29
  it "understands variables" do
@@ -20,16 +31,113 @@ describe "Expressive" do
20
31
  Expressive.run("hello", @scope).should eql "World"
21
32
  end
22
33
 
23
- describe "understands arithmetic" do
34
+ describe "under stands arithmetic" do
24
35
  it { Expressive.run("(+ 4 2)").should eql 6.0 }
25
36
  it { Expressive.run("(- 4 2)").should eql 2.0 }
26
37
  it { Expressive.run("(* 4 2)").should eql 8.0 }
27
38
  it { Expressive.run("(/ 4 2)").should eql 2.0 }
28
- it { Expressive.run("(sum 1 2 3)").should eql 6.0}
39
+ it { Expressive.run("(sum 1 2 3)").should eql 6.0 }
40
+ end
41
+
42
+ describe "understands comparisson" do
43
+ it { Expressive.run("(= 4 2)").should eql false }
44
+ it { Expressive.run("(= 4 4)").should eql true }
45
+ it { Expressive.run("(> 4 2)").should eql true }
46
+ it { Expressive.run("(> 2 4)").should eql false }
47
+ it { Expressive.run("(< 4 2)").should eql false }
48
+ it { Expressive.run("(< 2 4)").should eql true }
49
+ it { Expressive.run("(>= 4 4)").should eql true }
50
+ it { Expressive.run("(<= 4 4)").should eql true }
29
51
  end
30
52
 
31
53
  describe "understands compound statements" do
32
54
  it { Expressive.run("(= (+ 4 2) 6)").should eql true }
55
+ it { Expressive.run("(if (and (< 3 9) (> 2 1)), true, false)").should eql true }
56
+ it { Expressive.run("(if (and (< 10 9) (> 2 1)), true, false)").should eql false }
57
+ end
58
+
59
+ describe "understands conditional statements" do
60
+ it { Expressive.run('(if (> 5 4) "greater" "not so greater")').should eql "greater" }
61
+
62
+ context "it understands the need for commas (if you like that kind of thing" do
63
+ it { Expressive.run('(if (< 5 4), "greater", "not so greater")').should eql "not so greater" }
64
+ end
65
+
66
+ context "nil values" do
67
+ it { Expressive.run('(if (> nil_value 4) "greater" "not so greater")', @scope).should eql "not so greater" }
68
+ it { Expressive.run('(if (> 4 nil_value) "greater" "not so greater")', @scope).should eql "greater" }
69
+ it { Expressive.run('(if (> 4 nil_value) "greater" "not so greater")', @scope).should eql "greater" }
70
+ it { Expressive.run('(if (<= nil_value 4) "greater" "not so greater")', @scope).should eql "greater" }
71
+ it { Expressive.run('(if (>= 4 nil_value) "greater" "not so greater")', @scope).should eql "greater" }
72
+ end
73
+ end
74
+
75
+ describe "understands logical statements" do
76
+ it { Expressive.run('(and true true)').should eql true }
77
+ it { Expressive.run('(and true false)').should eql false }
78
+ it { Expressive.run('(or true true)').should eql true }
79
+ it { Expressive.run('(or true false)').should eql true }
80
+ it { Expressive.run('(or false false)').should eql false }
81
+
82
+ context "nil values" do
83
+ it { Expressive.run('(and true nil_value)', @scope).should eql false }
84
+ it { Expressive.run('(and nil_value true)', @scope).should eql false }
85
+ it { Expressive.run('(or nil_value true)', @scope).should eql true }
86
+ it { Expressive.run('(or nil_value false)', @scope).should eql false }
87
+ end
88
+ end
89
+
90
+ describe "understands web-hook statements" do
91
+ context "with a valid response" do
92
+ it "should post to the given uri" do
93
+ request = stub_request(:post, "www.example.com")
94
+ Expressive.run('(post "http://www.example.com")')
95
+ assert_requested(request)
96
+ end
97
+
98
+ it "should post the cope parameters if given" do
99
+ @scope['ohai'] = "world"
100
+ request = stub_request(:post, "www.example.com").with(body: {'ohai' => 'world'})
101
+ Expressive.run('(post "http://www.example.com" ohai)', @scope)
102
+ assert_requested(request)
103
+ end
104
+
105
+ it "should update the scope based on the response" do
106
+ @scope['ohai'] = "world"
107
+ request = stub_request(:post, "www.example.com").with(body: {'ohai' => 'world'}).to_return(body: {'goodbye' => 'srsly'})
108
+ Expressive.run('(post "http://www.example.com" ohai)', @scope)
109
+ @scope['goodbye'].should eql 'srsly'
110
+ end
111
+ end
112
+
113
+ context "when the response is invalid" do
114
+ context "sets error custom message" do
115
+ it "should add an entry in the errors element of the scope" do
116
+ message = 'Something went Pete Tong'
117
+ exception = RestClient::Exception.new
118
+ exception.message = message
119
+ stub_request(:post, 'www.example.com').to_raise(exception)
120
+ Expressive.run('(post "http://www.example.com")', @scope)
121
+ @scope['_errors'].should eql message
122
+ end
123
+ end
124
+
125
+ context "bad uri" do
126
+ it "should add an entry in the errors element of the scope" do
127
+ stub_request(:post, "badexample.com").to_raise(RestClient::ResourceNotFound.new)
128
+ Expressive.run('(post "badexample.com")', @scope)
129
+ @scope['_errors'].should eql 'Resource Not Found'
130
+ end
131
+ end
132
+
133
+ context "timeout" do
134
+ it "should add an entry in the errors element of the scope" do
135
+ stub_request(:post, 'www.example.com').to_timeout
136
+ Expressive.run('(post "http://www.example.com")', @scope)
137
+ @scope['_errors'].should eql 'Request Timeout'
138
+ end
139
+ end
140
+ end
33
141
  end
34
142
 
35
143
  context "looking up an id based on a value" do
data/spec/spec_helper.rb CHANGED
@@ -8,7 +8,10 @@ rescue Bundler::BundlerError => e
8
8
  exit e.status_code
9
9
  end
10
10
  require 'rspec'
11
+ require 'webmock/rspec'
12
+ require 'pry'
11
13
 
12
14
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
13
15
  $LOAD_PATH.unshift(File.dirname(__FILE__))
16
+
14
17
  require 'expressive'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: expressive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-10 00:00:00.000000000 Z
12
+ date: 2012-10-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ruby_gntp
@@ -107,6 +107,38 @@ dependencies:
107
107
  - - ~>
108
108
  - !ruby/object:Gem::Version
109
109
  version: 1.2.1
110
+ - !ruby/object:Gem::Dependency
111
+ name: webmock
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 1.8.11
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: 1.8.11
126
+ - !ruby/object:Gem::Dependency
127
+ name: pry
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ~>
132
+ - !ruby/object:Gem::Version
133
+ version: 0.9.10
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ~>
140
+ - !ruby/object:Gem::Version
141
+ version: 0.9.10
110
142
  - !ruby/object:Gem::Dependency
111
143
  name: polyglot
112
144
  requirement: !ruby/object:Gem::Requirement
@@ -155,6 +187,22 @@ dependencies:
155
187
  - - ~>
156
188
  - !ruby/object:Gem::Version
157
189
  version: 1.0.2
190
+ - !ruby/object:Gem::Dependency
191
+ name: rest-client
192
+ requirement: !ruby/object:Gem::Requirement
193
+ none: false
194
+ requirements:
195
+ - - ~>
196
+ - !ruby/object:Gem::Version
197
+ version: 1.6.7
198
+ type: :runtime
199
+ prerelease: false
200
+ version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
202
+ requirements:
203
+ - - ~>
204
+ - !ruby/object:Gem::Version
205
+ version: 1.6.7
158
206
  description: Scheme-like language for manipulating CaseBlocks cases
159
207
  email:
160
208
  - ijonas@emergeadapt.com
@@ -193,7 +241,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
193
241
  version: '0'
194
242
  segments:
195
243
  - 0
196
- hash: -3233629507963509909
244
+ hash: -977329044772272752
197
245
  required_rubygems_version: !ruby/object:Gem::Requirement
198
246
  none: false
199
247
  requirements:
@@ -202,7 +250,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
202
250
  version: '0'
203
251
  segments:
204
252
  - 0
205
- hash: -3233629507963509909
253
+ hash: -977329044772272752
206
254
  requirements: []
207
255
  rubyforge_project:
208
256
  rubygems_version: 1.8.23