crisp 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,16 @@
1
- ## 0.0.8 (2010-xx-xx)
1
+ ## 0.0.9 (2011-xx-xx)
2
2
 
3
3
  * ...
4
4
 
5
+ ## 0.0.8 (2011-01-06)
6
+
7
+ * local bindings with let
8
+ * cond provides a kind of switch/case statemnts, including default path
9
+ * load lets you load crisp source files at runtime
10
+ * loops can be performed with loop/recur
11
+ * internal fixes and refactorings
12
+ * more examples
13
+
5
14
  ## 0.0.6/0.0.7 (2010-12-17)
6
15
 
7
16
  * if else statements
data/Rakefile CHANGED
@@ -15,7 +15,7 @@ begin
15
15
  gem.homepage = "http://github.com/mgsnova/crisp"
16
16
  gem.authors = ['Markus Gerdes']
17
17
  gem.add_dependency 'treetop', '~> 1.4.9'
18
- gem.add_development_dependency 'rspec', '~> 2.3.0'
18
+ gem.add_development_dependency 'rspec', '~> 2.4.0'
19
19
  end
20
20
 
21
21
  Jeweler::GemcutterTasks.new
data/bin/crisp CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'lib/crisp'
3
+ require 'crisp'
4
4
 
5
5
  if ARGV.size == 0
6
6
  Crisp::Shell.new.run
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{crisp}
8
- s.version = "0.0.7"
8
+ s.version = "0.0.8"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Markus Gerdes"]
12
- s.date = %q{2010-12-17}
12
+ s.date = %q{2011-01-06}
13
13
  s.default_executable = %q{crisp}
14
14
  s.email = %q{github@mgsnova.de}
15
15
  s.executables = ["crisp"]
@@ -25,7 +25,9 @@ Gem::Specification.new do |s|
25
25
  "autotest/discover.rb",
26
26
  "bin/crisp",
27
27
  "crisp.gemspec",
28
+ "examples/factorial.crisp",
28
29
  "examples/fibonacci.crisp",
30
+ "examples/run.crisp",
29
31
  "lib/crisp.rb",
30
32
  "lib/crisp/chained_env.rb",
31
33
  "lib/crisp/crisp.treetop",
@@ -83,14 +85,14 @@ Gem::Specification.new do |s|
83
85
 
84
86
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
85
87
  s.add_runtime_dependency(%q<treetop>, ["~> 1.4.9"])
86
- s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
88
+ s.add_development_dependency(%q<rspec>, ["~> 2.4.0"])
87
89
  else
88
90
  s.add_dependency(%q<treetop>, ["~> 1.4.9"])
89
- s.add_dependency(%q<rspec>, ["~> 2.3.0"])
91
+ s.add_dependency(%q<rspec>, ["~> 2.4.0"])
90
92
  end
91
93
  else
92
94
  s.add_dependency(%q<treetop>, ["~> 1.4.9"])
93
- s.add_dependency(%q<rspec>, ["~> 2.3.0"])
95
+ s.add_dependency(%q<rspec>, ["~> 2.4.0"])
94
96
  end
95
97
  end
96
98
 
@@ -0,0 +1,6 @@
1
+ (def factorial
2
+ (fn [n]
3
+ (loop [cnt n acc 1]
4
+ (if (= 0 cnt)
5
+ acc
6
+ (recur (- cnt 1) (* acc cnt))))))
@@ -3,4 +3,3 @@
3
3
  (if (< n 2)
4
4
  n
5
5
  (+ (fib (- n 1)) (fib (- n 2))))))
6
- (println "fibonacci for 10 is" (fib 10))
@@ -0,0 +1,5 @@
1
+ (load "fibonacci")
2
+ (load "factorial")
3
+
4
+ (println "fibonacci for 10 is" (fib 10))
5
+ (println "factorial of 10 is" (factorial 10))
@@ -3,7 +3,7 @@ require "treetop"
3
3
  require "pp"
4
4
 
5
5
  module Crisp
6
- VERSION = '0.0.7'
6
+ VERSION = '0.0.8'
7
7
  end
8
8
 
9
9
  require 'crisp/errors'
@@ -29,5 +29,15 @@ module Crisp
29
29
  def []=(key, val)
30
30
  @second[key] = val
31
31
  end
32
+
33
+ # returns global loop data of global/second env
34
+ def global_loop_data
35
+ @second.global_loop_data
36
+ end
37
+
38
+ # set global loop data to global/second env
39
+ def global_loop_data=(data)
40
+ @second.global_loop_data = data
41
+ end
32
42
  end
33
43
  end
@@ -37,7 +37,7 @@ grammar Crisp
37
37
  end
38
38
 
39
39
  rule symbol
40
- [a-z] [a-z0-9]* <Nodes::SymbolLiteral>
40
+ [a-zA-Z] [a-zA-Z0-9]* <Nodes::SymbolLiteral>
41
41
  end
42
42
 
43
43
  rule integer
@@ -2,6 +2,8 @@ module Crisp
2
2
  # The Crisp environment is basically a key/value store.
3
3
  # The value for each key is immutable, so you can only store one time for each key
4
4
  class Env
5
+ attr_accessor :global_loop_data
6
+
5
7
  # create a new internal hash
6
8
  def initialize
7
9
  @map = {}
@@ -9,4 +9,7 @@ module Crisp
9
9
  class EnvironmentError < StandardError
10
10
  end
11
11
 
12
+ class LoopError < StandardError
13
+ end
14
+
12
15
  end
@@ -54,10 +54,6 @@ module Crisp
54
54
  raise ArgumentError, "no argument list defined"
55
55
  end
56
56
 
57
- if args[1].class.name != "Crisp::Nodes::Operation"
58
- raise ArgumentError, "no function body defined"
59
- end
60
-
61
57
  fn_arg_list = args[0].raw_elements
62
58
  fn_operation = args[1]
63
59
 
@@ -72,7 +68,7 @@ module Crisp
72
68
 
73
69
  chained_env = ChainedEnv.new(local_env, env)
74
70
 
75
- fn_operation.eval(chained_env)
71
+ fn_operation.resolve_and_eval(chained_env)
76
72
  end
77
73
  end.bind('fn', current_env)
78
74
 
@@ -96,6 +92,127 @@ module Crisp
96
92
  res ? res.resolve_and_eval(env) : res
97
93
  end.bind('if', current_env)
98
94
 
95
+ # cond
96
+ # cond works like a switch/case statement, evaluating the first expression where the condition matches
97
+ #
98
+ # (cond
99
+ # false (println "should not be printed")
100
+ # true (println "should be printed"))
101
+ Function.new do
102
+ if args.size.odd?
103
+ raise ArgumentError, "argument list has to contain even list of arguments"
104
+ end
105
+
106
+ result = nil
107
+
108
+ args.each_with_index do |arg, idx|
109
+ next if idx.odd?
110
+ if (arg.class.name == 'Crisp::Nodes::SymbolLiteral' and arg.text_value == 'else') or
111
+ (![nil, false].include?(arg.resolve_and_eval(env)))
112
+ result = args[idx + 1].resolve_and_eval(env)
113
+ break
114
+ end
115
+ end
116
+
117
+ result
118
+ end.bind("cond", current_env)
119
+
120
+ # let
121
+ # create local binding only valid within let and evaluate expressions
122
+ #
123
+ # (let [x 1 y 2] (+ x y))
124
+ # => 3
125
+ Function.new do
126
+ if args[0].class.name != "Crisp::Nodes::ArrayLiteral"
127
+ raise ArgumentError, "no argument list defined"
128
+ end
129
+
130
+ if args[0].raw_elements.size.odd?
131
+ raise ArgumentError, "argument list has to contain even list of arguments"
132
+ end
133
+
134
+ local_env = Env.new
135
+ chained_env = ChainedEnv.new(local_env, env)
136
+ binding_array = args[0].raw_elements
137
+
138
+ binding_array.each_with_index do |key, idx|
139
+ next if idx.odd?
140
+ local_env[key.text_value] = binding_array[idx+1].resolve_and_eval(chained_env)
141
+ end
142
+
143
+ args[1..-1].map do |op|
144
+ op.resolve_and_eval(chained_env)
145
+ end.last
146
+ end.bind('let', current_env)
147
+
148
+ # loop
149
+ # create loop with a local binding, perform a loopjump using recur
150
+ #
151
+ # (loop [cnt 5 acc 1]
152
+ # (if (= 0 cnt)
153
+ # acc
154
+ # (recur (- cnt 1) (* acc cnt))))
155
+ # => 120
156
+ Function.new do
157
+ if env.global_loop_data
158
+ raise LoopError, "nested loops are not allowed"
159
+ end
160
+
161
+ if args[0].class.name != "Crisp::Nodes::ArrayLiteral"
162
+ raise ArgumentError, "no argument list defined"
163
+ end
164
+
165
+ if args[0].raw_elements.size.odd?
166
+ raise ArgumentError, "argument list has to contain even list of arguments"
167
+ end
168
+
169
+ local_env = Env.new
170
+ chained_env = ChainedEnv.new(local_env, env)
171
+ binding_array = args[0].raw_elements
172
+ argument_name_array = []
173
+
174
+ binding_array.each_with_index do |key, idx|
175
+ next if idx.odd?
176
+ local_env[key.text_value] = binding_array[idx+1].resolve_and_eval(chained_env)
177
+ argument_name_array << key.text_value
178
+ end
179
+
180
+ env.global_loop_data = {
181
+ :operations => args[1..-1],
182
+ :argument_names => argument_name_array
183
+ }
184
+
185
+ result = args[1..-1].map do |op|
186
+ op.resolve_and_eval(chained_env)
187
+ end.last
188
+
189
+ env.global_loop_data = nil
190
+
191
+ result
192
+ end.bind('loop', current_env)
193
+
194
+ # recur
195
+ # only used inside a loop. recur will trigger a new run of the loop
196
+ # see 'loop' for an example
197
+ Function.new do
198
+ if !env.global_loop_data
199
+ raise LoopError, "recur called outside loop"
200
+ end
201
+
202
+ validate_args_count(env.global_loop_data[:argument_names].size, args.size)
203
+
204
+ local_env = Env.new
205
+ chained_env = ChainedEnv.new(local_env, env)
206
+
207
+ env.global_loop_data[:argument_names].each_with_index do |key, idx|
208
+ local_env[key] = args[idx].resolve_and_eval(env)
209
+ end
210
+
211
+ env.global_loop_data[:operations].map do |op|
212
+ op.resolve_and_eval(chained_env)
213
+ end.last
214
+ end.bind('recur', current_env)
215
+
99
216
  # .
100
217
  # perform a native call on an object with optional arguments
101
218
  #
@@ -103,12 +220,42 @@ module Crisp
103
220
  # => "ABC"
104
221
  Function.new do
105
222
  meth = args[0].text_value.to_sym
106
- target = args[1].resolve_and_eval(env)
223
+ target = if args[1].class.name == "Crisp::Nodes::SymbolLiteral" and !env.has_key?(args[1].text_value)
224
+ Object.const_get(args[1].text_value)
225
+ else
226
+ args[1].resolve_and_eval(env)
227
+ end
107
228
  values = args[2..-1].map { |arg| arg.resolve_and_eval(env) }
108
229
 
109
230
  NativeCallInvoker.new(target, meth, values).invoke!
110
231
  end.bind('.', current_env)
111
232
 
233
+ # load
234
+ # include content of another crisp source file
235
+ #
236
+ # (load "business_logic")
237
+ # => true
238
+ Function.new do
239
+ args_evaled.collect(&:to_s).each do |filename|
240
+ pwd = `pwd`.strip
241
+ file = if filename[0..1] == '/'
242
+ File.join(pwd, filename)
243
+ else
244
+ filename
245
+ end.sub(".crisp$", '') + '.crisp'
246
+
247
+ if !File.exists?(file)
248
+ raise Crisp::ArgumentError, "file #{file} not found"
249
+ end
250
+
251
+ filecontent = File.read(file)
252
+ ast = Crisp::Parser.new.parse(filecontent)
253
+ Crisp::Runtime.new(env).run(ast)
254
+ end
255
+
256
+ true
257
+ end.bind('load', current_env)
258
+
112
259
  end
113
260
  end
114
261
  end
@@ -4,13 +4,9 @@ module Crisp
4
4
  class Block < Base
5
5
  # eval each element of the block and return the last result
6
6
  def eval(env)
7
- last_result = nil
8
-
9
- elements.each do |op|
10
- last_result = op.resolve_and_eval(env)
11
- end
12
-
13
- last_result
7
+ elements.map do |op|
8
+ op.resolve_and_eval(env)
9
+ end.last
14
10
  end
15
11
 
16
12
  # a block resolves to itself
@@ -5,9 +5,9 @@ module Crisp
5
5
  # get the function binded to the given function name and eval it (including arguments)
6
6
  def eval(env)
7
7
  if self.func_identifier.class.name == "Crisp::Nodes::Operation"
8
- self.func_identifier.eval(env).eval(env, self.element_list.elements.collect(&:element))
8
+ self.func_identifier.eval(env).eval(env, raw_element_list)
9
9
  else
10
- env[self.func_identifier.text_value].eval(env, self.element_list.elements.collect(&:element))
10
+ env[self.func_identifier.text_value].eval(env, raw_element_list)
11
11
  end
12
12
  end
13
13
 
@@ -15,6 +15,12 @@ module Crisp
15
15
  def resolve(env)
16
16
  self
17
17
  end
18
+
19
+ private
20
+
21
+ def raw_element_list
22
+ self.element_list.elements.collect(&:element)
23
+ end
18
24
  end
19
25
  end
20
26
  end
@@ -6,9 +6,9 @@ module Crisp
6
6
  # Run code by calling run with the output of the parser as argurment.
7
7
  class Runtime
8
8
  # create a new env and load all functions when creating a new runtime
9
- def initialize
10
- @env = Env.new
11
- Functions.load(@env)
9
+ def initialize(env = nil)
10
+ @env = env || Env.new
11
+ Functions.load(@env) if !env
12
12
  end
13
13
 
14
14
  # run the parsed code (abstract syntax tree)
@@ -82,7 +82,7 @@ describe "arithemtic functions" do
82
82
  evaluate("(< 1 2)").should == true
83
83
  end
84
84
 
85
- it "should calc fibonacci numbers" do
85
+ it "calculates fibonacci numbers" do
86
86
  evaluate("
87
87
  (def fib (
88
88
  fn [n]
@@ -3,17 +3,17 @@ require 'spec_helper'
3
3
  describe "the language" do
4
4
  include Crisp::SpecHelper
5
5
 
6
- it "does not bother whitspaces characters in expressions" do
6
+ it "does not bother whitspace characters in expressions" do
7
7
  evaluate(" \r\t\n (\r+\t 1\n2 \t(\n - 9\r\t \n 2)\r)\r\t ").should == 10
8
8
  end
9
9
 
10
- it "creates syntax error on invalid expressions" do
10
+ it "raises a syntax error on invalid expressions" do
11
11
  lambda do
12
12
  evaluate("(()")
13
13
  end.should raise_error(Crisp::SyntaxError, "syntax error at : 0")
14
14
  end
15
15
 
16
- it "bind arrays to symbols" do
16
+ it "binds arrays to symbols" do
17
17
  evaluate("(def bla [1 2 3])").size.should == 3
18
18
  evaluate("(def bla [1 2 3])")[1].should == 2
19
19
  evaluate("(def foo 5)(def bla [1 2 foo])")[2].should == 5
@@ -80,4 +80,140 @@ describe "the core language features" do
80
80
  it "resolves symbols in if statements" do
81
81
  evaluate("(def foo 2)(if true foo)").should == 2
82
82
  end
83
+
84
+ it "uses local binding with let" do
85
+ evaluate("(let [x 1] x)").should == 1
86
+ end
87
+
88
+ it "uses more complex local bindings with let" do
89
+ evaluate("(let [x 2 y x] (* x y))").should == 4
90
+ end
91
+
92
+ it "evaluates several expressions within local binding" do
93
+ evaluate("(let [x 2 y 3] (* x y) (+ x y))").should == 5
94
+ end
95
+
96
+ it "binds symbols to global binding within local binding" do
97
+ evaluate("(let [x 1 y 2] (def foo (+ x y))) foo").should == 3
98
+ end
99
+
100
+ it "overrides global binding within local binding" do
101
+ evaluate("(def x 1)(let [x 2] x)").should == 2
102
+ end
103
+
104
+ it "ensures that local binding is only valid within let" do
105
+ evaluate("(def x 1)(let [x 2] x) x").should == 1
106
+ end
107
+
108
+ it "can handle emtpy local binding" do
109
+ evaluate("(let [] 2)").should == 2
110
+ end
111
+
112
+ it "raises an error when calling let without correct argument" do
113
+ lambda do
114
+ evaluate("(let 2 2)")
115
+ end.should raise_error(Crisp::ArgumentError, "no argument list defined")
116
+ end
117
+
118
+ it "raises an error when calling let with odd binding list" do
119
+ lambda do
120
+ evaluate("(let [x 1 y] 2)")
121
+ end.should raise_error(Crisp::ArgumentError, "argument list has to contain even list of arguments")
122
+ end
123
+
124
+ it "raises an error if file to be load not there" do
125
+ lambda do
126
+ evaluate('(load "not_there")')
127
+ end.should raise_error(Crisp::ArgumentError, /file (.*) not found/)
128
+
129
+ lambda do
130
+ evaluate('(load "/not_there")')
131
+ end.should raise_error(Crisp::ArgumentError, "file /not_there.crisp not found")
132
+ end
133
+
134
+ it "loads other crisp files" do
135
+ File.open("/tmp/crisp_test_file.crisp", 'w') do |f|
136
+ f << "(def foo 123)"
137
+ end
138
+
139
+ evaluate('(load "/tmp/crisp_test_file")(+ 1 foo)').should == 124
140
+ end
141
+
142
+ it "uses the current environment when loading other crisp source files" do
143
+ File.open("/tmp/crisp_test_file.crisp", 'w') do |f|
144
+ f << "(def bla 123)"
145
+ end
146
+
147
+ lambda do
148
+ evaluate('(def bla 321)(load "/tmp/crisp_test_file")')
149
+ end.should raise_error(Crisp::EnvironmentError, "bla already binded")
150
+ end
151
+
152
+ it "raises an error if calling cond with wrong number of arguments" do
153
+ lambda do
154
+ evaluate("(cond false 1 true)")
155
+ end.should raise_error(Crisp::ArgumentError, "argument list has to contain even list of arguments")
156
+ end
157
+
158
+ it "has cond statement" do
159
+ evaluate("(cond)").should == nil
160
+ evaluate("(cond false 1 false 2)").should == nil
161
+ evaluate("(cond true 3)").should == 3
162
+ evaluate("(cond true 3 false 2)").should == 3
163
+ evaluate("(cond false 3 true 2)").should == 2
164
+ evaluate("(cond (= 1 1) (+ 1 1))").should == 2
165
+ evaluate("(cond true 3 true 2 true 1)").should == 3
166
+ end
167
+
168
+ it "does not eval expressions for unmatched condition" do
169
+ evaluate("(cond false (def foo 1) true 2)(def foo 2) foo").should == 2
170
+ end
171
+
172
+ it "has a default condition in cond" do
173
+ evaluate("(cond false 1 true 2 else 3)").should == 2
174
+ evaluate("(cond true 1 true 2 else 3)").should == 1
175
+ evaluate("(cond false 1 else 2 true 3)").should == 2
176
+ end
177
+
178
+ it "raises an error when calling loop without correct argument" do
179
+ lambda do
180
+ evaluate("(loop 2 2)")
181
+ end.should raise_error(Crisp::ArgumentError, "no argument list defined")
182
+ end
183
+
184
+ it "raises an error when calling loop with odd binding list" do
185
+ lambda do
186
+ evaluate("(loop [x 1 y] 2)")
187
+ end.should raise_error(Crisp::ArgumentError, "argument list has to contain even list of arguments")
188
+ end
189
+
190
+ it "raises an error when calling recur outside a loop" do
191
+ lambda do
192
+ evaluate("(recur 1)")
193
+ end.should raise_error(Crisp::LoopError, "recur called outside loop")
194
+ end
195
+
196
+ it "raises an error when calling recur with wrong number of arguments" do
197
+ lambda do
198
+ evaluate("(loop [x 1] (recur 1 2))")
199
+ end.should raise_error(Crisp::ArgumentError, "wrong number of arguments for 'recur' (2 for 1)")
200
+ end
201
+
202
+ it "calculates factorials using loop recur" do
203
+ evaluate("
204
+ (def factorial
205
+ (fn [n]
206
+ (loop [cnt n acc 1]
207
+ (if (= 0 cnt)
208
+ acc
209
+ (recur (- cnt 1) (* acc cnt))))))
210
+ (factorial 5)
211
+ ").should == 120
212
+ end
213
+
214
+ it "raises an error when nesting loops" do
215
+ lambda do
216
+ evaluate("(loop [x 1] (loop [a 1 b 2] (+ a b)))")
217
+ end.should raise_error(Crisp::LoopError, "nested loops are not allowed")
218
+ end
83
219
  end
@@ -15,10 +15,11 @@ describe "the languages functions" do
15
15
  end.should raise_error(Crisp::ArgumentError, "no argument list defined")
16
16
  end
17
17
 
18
- it "does not create a function when not providing a proper function body" do
19
- lambda do
20
- evaluate("(fn [] [])")
21
- end.should raise_error(Crisp::ArgumentError, "no function body defined")
18
+ it "does return primitive values as result" do
19
+ evaluate("((fn [] 1))").should == 1
20
+ evaluate('((fn [] "abc"))').should == 'abc'
21
+ evaluate('((fn [] [1 2 3]))').should == [1, 2, 3]
22
+ evaluate("((fn [x] x) 2)").should == 2
22
23
  end
23
24
 
24
25
  it "creates functions" do
@@ -3,21 +3,27 @@ require 'spec_helper'
3
3
  describe "NativeCallInvoker functionality" do
4
4
  include Crisp::SpecHelper
5
5
 
6
- it "should execute String#reverse probably" do
6
+ it "executes ruby native String#reverse" do
7
7
  evaluate('(. reverse "foobar")').should == 'raboof'
8
8
  end
9
9
 
10
- it "should execute Array#first probably" do
10
+ it "executes ruby native Array#first" do
11
11
  evaluate('(. first [1 2 3])').should == 1
12
12
  end
13
13
 
14
- it "should execute Array#first(n) probably" do
14
+ it "executes ruby native Array#first(n)" do
15
15
  evaluate('(. first [1 2 3] 2)').should == [1,2]
16
16
  end
17
17
 
18
- it "should raise a named exception on invalid method" do
18
+ it "raises a named exception on invalid method" do
19
19
  lambda do
20
20
  evaluate('(. foo "bar")')
21
21
  end.should raise_error(NoMethodError, %q{undefined method `foo' for "bar":String})
22
22
  end
23
+
24
+ it "executes calls on Ruby classes" do
25
+ evaluate("(. new String)").should == ''
26
+ evaluate('(. new String "123")').should == '123'
27
+ evaluate("(. new Array 5 2)").should == [2, 2, 2, 2, 2]
28
+ end
23
29
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe "string functionality" do
4
4
  include Crisp::SpecHelper
5
5
 
6
- it "should concat strings" do
6
+ it "concats strings" do
7
7
  evaluate('(+ "foo" "bar")').should == 'foobar'
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crisp
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 7
10
- version: 0.0.7
9
+ - 8
10
+ version: 0.0.8
11
11
  platform: ruby
12
12
  authors:
13
13
  - Markus Gerdes
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-12-17 00:00:00 +01:00
18
+ date: 2011-01-06 00:00:00 +01:00
19
19
  default_executable: crisp
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -42,12 +42,12 @@ dependencies:
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- hash: 3
45
+ hash: 31
46
46
  segments:
47
47
  - 2
48
- - 3
48
+ - 4
49
49
  - 0
50
- version: 2.3.0
50
+ version: 2.4.0
51
51
  type: :development
52
52
  version_requirements: *id002
53
53
  description:
@@ -67,7 +67,9 @@ files:
67
67
  - autotest/discover.rb
68
68
  - bin/crisp
69
69
  - crisp.gemspec
70
+ - examples/factorial.crisp
70
71
  - examples/fibonacci.crisp
72
+ - examples/run.crisp
71
73
  - lib/crisp.rb
72
74
  - lib/crisp/chained_env.rb
73
75
  - lib/crisp/crisp.treetop