kapusta 0.2.1 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee9b062de9860ef3b9f3cfcbac8503e69c1549f0f09af35b41e5eb13303c1ddb
4
- data.tar.gz: daa87e0b3b65dfc82f21ff47e88b41652d05f087e46320ca1c3f49bac2457b71
3
+ metadata.gz: 1a5fcd922c54b5fa491785e6087c4fc2f8e6de1a8d94deab10fca3f775518b9b
4
+ data.tar.gz: d95f4bce9e6673104c44fc0ff281a705e796797490285cc50ef509b6b9fe5e97
5
5
  SHA512:
6
- metadata.gz: 564c441ea9395cd4f28daaa631de6022e39125eede47032bf32bbc2a45f18979b7376f264b5302459b78403ef039ef8aca93e6f469cc0666b033f6e6717894a2
7
- data.tar.gz: 38479cb8d38b81df15697a56c1a14e63d4dda7a0dd793db4e121e06126395339d9c7676a4bb14411a6b43398b64196f877ce3126990eb07d24f2a0c769a577e2
6
+ metadata.gz: cb5ba4420166be83a152c22bf56a12563efdb8cc64e54f230f6d299051761c5abc2329ae42dfc5e6127a721f66250b9804d6ec86a9b053dc36282599b2f8c986
7
+ data.tar.gz: 334d34e9e47bdecf6a4aa35cc6e905770efb6913fa6c2e9f90b0f3b1a95915b9044c8e3f36c81778a865f91a6d43f675318bf1ae892e19292cb4a2d2de179685
data/README.md CHANGED
@@ -67,8 +67,8 @@ def ack(m, n)
67
67
  ack(m - 1, ack(m, n - 1))
68
68
  end
69
69
  end
70
- p(ack(2, 3))
71
- p(ack(3, 3))
70
+ p ack(2, 3)
71
+ p ack(3, 3)
72
72
  ```
73
73
 
74
74
  ## Comparison with Fennel
data/examples/anagram.kap CHANGED
@@ -1,8 +1,8 @@
1
1
  (fn normalize-word [word]
2
- (let [lower (word.downcase)
3
- chars (lower.chars)
4
- sorted (chars.sort)]
5
- (sorted.join)))
2
+ (-> word
3
+ (: :downcase)
4
+ (: :chars)
5
+ (: :sort)))
6
6
 
7
7
  (fn anagram? [a b]
8
8
  (= (normalize-word a)
@@ -4,7 +4,7 @@
4
4
  (if (= op "C") (do (-?> (scores.pop) (: :abs)) nil)
5
5
  (= op "D") (scores.push (* 2 (. scores -1)))
6
6
  (= op "+") (scores.push (+ (. scores -1) (. scores -2)))
7
- (scores.push (Integer op))))
7
+ (scores.push (: op :to-i))))
8
8
  scores.sum))
9
9
 
10
10
  (print (cal-points ["5" "2" "C" "D" "+"]))
@@ -1,7 +1,7 @@
1
1
  (fn require-score [s]
2
2
  (if (= s "oops")
3
3
  (raise (ArgumentError.new "not a number"))
4
- (Integer s)))
4
+ (: s :to-i)))
5
5
 
6
6
  (fn parse-score [s]
7
7
  (try (require-score s)
data/examples/pcall.kap CHANGED
@@ -1,6 +1,9 @@
1
- (let [[ok value] (pcall Integer "12")
2
- [bad-ok error] (pcall Integer "oops")
3
- [handled-ok handled] (xpcall Integer (fn [e] (e.message)) "oops")]
1
+ (fn parse-int [s]
2
+ (: Kernel :Integer s))
3
+
4
+ (let [[ok value] (pcall parse-int "12")
5
+ [bad-ok error] (pcall parse-int "oops")
6
+ [handled-ok handled] (xpcall parse-int (fn [e] (e.message)) "oops")]
4
7
  (print ok)
5
8
  (print value)
6
9
  (print bad-ok)
@@ -7,7 +7,7 @@
7
7
  (when (div? n 5) (add-drop "Plang"))
8
8
  (when (div? n 7) (add-drop "Plong"))
9
9
  (if (empty? drops)
10
- (tostring n)
10
+ (: n :to-s)
11
11
  (drops.join)))
12
12
 
13
13
  (print (raindrops 15))
@@ -0,0 +1,7 @@
1
+ (fn single-number [nums]
2
+ (accumulate [acc 0 _ n (ipairs nums)]
3
+ (: acc :^ n)))
4
+
5
+ (print (single-number [2 2 1]))
6
+ (print (single-number [4 1 2 1 2]))
7
+ (print (single-number [1]))
data/kapusta.gemspec CHANGED
@@ -7,13 +7,13 @@ Gem::Specification.new do |spec|
7
7
  spec.version = Kapusta::VERSION
8
8
  spec.authors = ['Evgenii Morozov']
9
9
  spec.homepage = 'https://github.com/evmorov/kapusta'
10
+ spec.license = 'MIT'
10
11
 
11
12
  spec.summary = 'A Lisp for the Ruby runtime'
12
13
  spec.description = 'Kapusta is a Lisp for the Ruby runtime.'
13
14
  spec.required_ruby_version = '>= 3.1'
14
15
 
15
16
  spec.metadata['rubygems_mfa_required'] = 'true'
16
- spec.metadata['homepage_uri'] = spec.homepage
17
17
  spec.metadata['source_code_uri'] = spec.homepage
18
18
  spec.metadata['bug_tracker_uri'] = "#{spec.homepage}/issues"
19
19
 
@@ -213,11 +213,11 @@ module Kapusta
213
213
 
214
214
  def emit_let(args, env, current_scope)
215
215
  binding_code, body_code = emit_let_parts(args, env, current_scope, result: true)
216
- <<~RUBY.chomp
217
- (-> do
218
- #{indent(join_code(binding_code, body_code))}
219
- end).call
220
- RUBY
216
+ [
217
+ '(-> do',
218
+ indent(join_code(binding_code, body_code)),
219
+ 'end).call'
220
+ ].join("\n")
221
221
  end
222
222
 
223
223
  def emit_let_statement(args, env, current_scope)
@@ -242,7 +242,7 @@ module Kapusta
242
242
  body_code, = emit_sequence(body, child_env, current_scope,
243
243
  allow_method_definitions: false,
244
244
  result:)
245
- [binding_codes.join("\n"), body_code]
245
+ [binding_codes.reject(&:empty?).join("\n"), body_code]
246
246
  end
247
247
 
248
248
  def join_code(*chunks)
@@ -258,7 +258,7 @@ module Kapusta
258
258
  ["#{ruby_name} = #{value_code}\nnil", env]
259
259
  else
260
260
  bind_code, env = emit_pattern_bind(target, value_code, env)
261
- ["#{bind_code}\nnil", env]
261
+ [join_code(bind_code, 'nil'), env]
262
262
  end
263
263
  end
264
264
 
@@ -113,12 +113,9 @@ module Kapusta
113
113
  [[binding_pats[0], index_var], [binding_pats[1], value_var]], body_env
114
114
  )
115
115
  body_code = yield(body_env)
116
- return <<~RUBY.chomp
117
- #{emit_expr(iter_expr.items[1], env, current_scope)}.each_with_index do |#{value_var}, #{index_var}|
118
- #{bind_code}
119
- #{body_code}
120
- end
121
- RUBY
116
+ header = "#{emit_expr(iter_expr.items[1], env, current_scope)}" \
117
+ ".each_with_index do |#{value_var}, #{index_var}|"
118
+ return iteration_block(header, bind_code, body_code)
122
119
  when 'pairs'
123
120
  key_var = temp('key')
124
121
  value_var = temp('value')
@@ -126,12 +123,8 @@ module Kapusta
126
123
  bind_code, body_env = emit_iteration_bindings([[binding_pats[0], key_var], [binding_pats[1], value_var]],
127
124
  body_env)
128
125
  body_code = yield(body_env)
129
- return <<~RUBY.chomp
130
- #{emit_expr(iter_expr.items[1], env, current_scope)}.each do |#{key_var}, #{value_var}|
131
- #{bind_code}
132
- #{body_code}
133
- end
134
- RUBY
126
+ header = "#{emit_expr(iter_expr.items[1], env, current_scope)}.each do |#{key_var}, #{value_var}|"
127
+ return iteration_block(header, bind_code, body_code)
135
128
  end
136
129
  end
137
130
 
@@ -141,27 +134,21 @@ module Kapusta
141
134
  body_env = env.child
142
135
  bind_code, body_env = emit_iteration_bindings([[binding_pats[0], value_var]], body_env)
143
136
  body_code = yield(body_env)
144
- <<~RUBY.chomp
145
- #{coll_code}.each do |#{value_var}|
146
- #{bind_code}
147
- #{body_code}
148
- end
149
- RUBY
137
+ iteration_block("#{coll_code}.each do |#{value_var}|", bind_code, body_code)
150
138
  else
151
139
  parts_var = temp('parts')
152
140
  body_env = env.child
153
141
  pairs = binding_pats.each_with_index.map { |pattern, i| [pattern, "#{parts_var}[#{i}]"] }
154
142
  bind_code, body_env = emit_iteration_bindings(pairs, body_env)
155
143
  body_code = yield(body_env)
156
- <<~RUBY.chomp
157
- #{coll_code}.each do |*#{parts_var}|
158
- #{bind_code}
159
- #{body_code}
160
- end
161
- RUBY
144
+ iteration_block("#{coll_code}.each do |*#{parts_var}|", bind_code, body_code)
162
145
  end
163
146
  end
164
147
 
148
+ def iteration_block(header, bind_code, body_code)
149
+ [header, indent(join_code(bind_code, body_code)), 'end'].join("\n")
150
+ end
151
+
165
152
  def emit_iteration_bindings(pairs, env)
166
153
  current_env = env
167
154
  codes = pairs.compact.map do |pattern, value_code|
@@ -169,7 +156,7 @@ module Kapusta
169
156
 
170
157
  code, current_env = emit_pattern_bind(pattern, value_code, current_env)
171
158
  code
172
- end.compact
159
+ end.compact.reject(&:empty?)
173
160
  [codes.join("\n"), current_env]
174
161
  end
175
162
 
@@ -110,13 +110,17 @@ module Kapusta
110
110
  def emit_print(args, env, current_scope)
111
111
  return 'p' if args.empty?
112
112
 
113
- "p(#{args.map { |arg| emit_expr(arg, env, current_scope) }.join(', ')})"
113
+ rendered = args.map { |arg| emit_expr(arg, env, current_scope) }
114
+ return "p #{rendered[0]}" if rendered.length == 1 && simple_expression?(rendered[0])
115
+
116
+ "p(#{rendered.join(', ')})"
114
117
  end
115
118
 
116
119
  def emit_string_part(arg, env, current_scope)
117
120
  return arg.inspect if arg.is_a?(String)
118
121
 
119
- "(#{emit_expr(arg, env, current_scope)}).to_s"
122
+ code = emit_expr(arg, env, current_scope)
123
+ "#{simple_expression?(code) ? code : "(#{code})"}.to_s"
120
124
  end
121
125
  end
122
126
  end
@@ -21,20 +21,37 @@ module Kapusta
21
21
  runtime_call(:qget_path, object_code, "[#{keys}]")
22
22
  end
23
23
 
24
+ BINARY_OPERATOR_METHODS = %w[<=> ** << >> & | ^ === =~].freeze
25
+ private_constant :BINARY_OPERATOR_METHODS
26
+
24
27
  def emit_colon(args, env, current_scope)
25
28
  receiver = emit_expr(args[0], env, current_scope)
26
29
  method_form = args[1]
27
- positional, kwargs, block = split_call_args(args[2..], env, current_scope)
30
+ positional, kwargs, block_form = split_call_args(args[2..], env, current_scope)
28
31
  literal_name = method_form if method_form.is_a?(Symbol) || method_form.is_a?(String)
29
- if literal_name && !kwargs && !block && direct_method_name?(literal_name.to_s)
30
- return emit_direct_method_call(receiver, Kapusta.kebab_to_snake(literal_name.to_s), positional)
32
+ if literal_name && binary_operator_call?(literal_name.to_s, positional, kwargs, block_form)
33
+ return emit_binary_operator_call(receiver, literal_name.to_s, positional[0])
34
+ end
35
+ if literal_name && direct_method_name?(literal_name.to_s)
36
+ return emit_direct_method_call(receiver, Kapusta.kebab_to_snake(literal_name.to_s),
37
+ positional, kwargs, block_form, env, current_scope)
31
38
  end
32
39
 
33
40
  method_name = emit_method_name(method_form, env, current_scope)
41
+ block = emit_block_proc(block_form, env, current_scope)
34
42
  parts = build_call_args([method_name, *positional], kwargs, block)
35
43
  "#{parenthesize(receiver)}.public_send(#{parts})"
36
44
  end
37
45
 
46
+ def binary_operator_call?(name, positional, kwargs, block_form)
47
+ BINARY_OPERATOR_METHODS.include?(name) &&
48
+ positional.length == 1 && !kwargs && !block_form
49
+ end
50
+
51
+ def emit_binary_operator_call(receiver, operator, arg_code)
52
+ "#{parenthesize(receiver)} #{operator} #{parenthesize(arg_code)}"
53
+ end
54
+
38
55
  def emit_require(arg, env, current_scope)
39
56
  path_code =
40
57
  case arg
@@ -163,7 +180,14 @@ module Kapusta
163
180
  end
164
181
  end
165
182
 
166
- lines = ['begin', indent(emit_expr(args[0], env, current_scope))]
183
+ body_form = args[0]
184
+ body_code =
185
+ if body_form.is_a?(List) && body_form.head.is_a?(Sym) && body_form.head.name == 'do'
186
+ emit_sequence(body_form.rest, env, current_scope, allow_method_definitions: false).first
187
+ else
188
+ emit_expr(body_form, env, current_scope)
189
+ end
190
+ lines = ['begin', indent(body_code)]
167
191
  catches.each do |klass_form, bind_sym, body|
168
192
  rescue_env = env.child
169
193
  rescue_name = define_local(rescue_env, bind_sym.name)
@@ -209,6 +233,9 @@ module Kapusta
209
233
  def emit_compare(args, env, current_scope, operator)
210
234
  values = args.map { |arg| emit_expr(arg, env, current_scope) }
211
235
  return 'true' if values.length <= 1
236
+ if (nil_pred = nil_predicate(args, values, operator, negate: false))
237
+ return nil_pred
238
+ end
212
239
 
213
240
  (0...(values.length - 1)).map do |i|
214
241
  "#{parenthesize(values[i])} #{operator} #{parenthesize(values[i + 1])}"
@@ -218,12 +245,27 @@ module Kapusta
218
245
  def emit_compare_any(args, env, current_scope, operator)
219
246
  values = args.map { |arg| emit_expr(arg, env, current_scope) }
220
247
  return 'false' if values.length <= 1
248
+ if (nil_pred = nil_predicate(args, values, operator, negate: true))
249
+ return nil_pred
250
+ end
221
251
 
222
252
  (0...(values.length - 1)).map do |i|
223
253
  "#{parenthesize(values[i])} #{operator} #{parenthesize(values[i + 1])}"
224
254
  end.join(' || ')
225
255
  end
226
256
 
257
+ def nil_predicate(args, values, operator, negate:)
258
+ return unless args.length == 2
259
+ return unless (operator == '==' && !negate) || (operator == '!=' && negate)
260
+
261
+ nil_idx = args.find_index(&:nil?)
262
+ return unless nil_idx
263
+
264
+ other = values[1 - nil_idx]
265
+ receiver = simple_expression?(other) ? other : parenthesize(other)
266
+ "#{'!' if negate}#{receiver}.nil?"
267
+ end
268
+
227
269
  def emit_reduce(args, env, current_scope, empty_value, operator)
228
270
  return empty_value if args.empty?
229
271
 
@@ -246,7 +288,8 @@ module Kapusta
246
288
  end
247
289
 
248
290
  def emit_callable_call(callee_code, args, env, current_scope)
249
- positional, kwargs, block = split_call_args(args, env, current_scope)
291
+ positional, kwargs, block_form = split_call_args(args, env, current_scope)
292
+ block = emit_block_proc(block_form, env, current_scope)
250
293
  rendered = build_call_args(positional, kwargs, block)
251
294
  suffix = rendered.empty? ? '.call' : ".call(#{rendered})"
252
295
  "#{parenthesize(callee_code)}#{suffix}"
@@ -281,12 +324,17 @@ module Kapusta
281
324
  emit_callable_call(base_code, args, env, current_scope)
282
325
  else
283
326
  receiver = emit_method_path(base_code, segments[0...-1])
284
- positional, kwargs, block = split_call_args(args, env, current_scope)
285
- if !kwargs && !block && direct_method_name?(segments.last)
286
- return emit_direct_method_call(receiver, Kapusta.kebab_to_snake(segments.last), positional)
327
+ positional, kwargs, block_form = split_call_args(args, env, current_scope)
328
+ if binary_operator_call?(segments.last, positional, kwargs, block_form)
329
+ return emit_binary_operator_call(receiver, segments.last, positional[0])
330
+ end
331
+ if direct_method_name?(segments.last)
332
+ return emit_direct_method_call(receiver, Kapusta.kebab_to_snake(segments.last),
333
+ positional, kwargs, block_form, env, current_scope)
287
334
  end
288
335
 
289
336
  method_name = Kapusta.kebab_to_snake(segments.last).to_sym.inspect
337
+ block = emit_block_proc(block_form, env, current_scope)
290
338
  parts = build_call_args([method_name, *positional], kwargs, block)
291
339
  "#{receiver}.public_send(#{parts})"
292
340
  end
@@ -303,25 +351,43 @@ module Kapusta
303
351
  end
304
352
  end
305
353
 
306
- def emit_direct_method_call(receiver, method_name, positional)
307
- args = positional.join(', ')
354
+ def emit_direct_method_call(receiver, method_name, positional, kwargs = nil,
355
+ block_form = nil, env = nil, current_scope = nil)
356
+ attached = block_form && emit_attached_block(block_form, env, current_scope)
357
+ block = block_form && !attached ? emit_block_proc(block_form, env, current_scope) : nil
358
+ parts = build_call_args(positional, kwargs, block)
308
359
  rendered_receiver = simple_expression?(receiver) ? receiver : parenthesize(receiver)
309
- suffix = args.empty? ? method_name : "#{method_name}(#{args})"
310
- "#{rendered_receiver}.#{suffix}"
360
+ call = parts.empty? ? method_name : "#{method_name}(#{parts})"
361
+ call = "#{call} #{attached}" if attached
362
+ "#{rendered_receiver}.#{call}"
311
363
  end
312
364
 
313
365
  def emit_self_call(name, args, env, current_scope)
314
- positional, kwargs, block = split_call_args(args, env, current_scope)
315
- method_name = Kapusta.kebab_to_snake(name).to_sym.inspect
366
+ positional, kwargs, block_form = split_call_args(args, env, current_scope)
367
+ snake = Kapusta.kebab_to_snake(name)
368
+ if direct_method_name?(snake)
369
+ return emit_direct_self_call(snake, positional, kwargs, block_form, env, current_scope)
370
+ end
371
+
372
+ block = emit_block_proc(block_form, env, current_scope)
373
+ method_name = snake.to_sym.inspect
316
374
  parts = build_call_args([method_name, *positional], kwargs, block)
317
- "send(#{parts})"
375
+ "public_send(#{parts})"
376
+ end
377
+
378
+ def emit_direct_self_call(method_name, positional, kwargs, block_form, env, current_scope)
379
+ attached = block_form && emit_attached_block(block_form, env, current_scope)
380
+ block = block_form && !attached ? emit_block_proc(block_form, env, current_scope) : nil
381
+ parts = build_call_args(positional, kwargs, block)
382
+ call = parts.empty? ? "#{method_name}()" : "#{method_name}(#{parts})"
383
+ attached ? "#{call} #{attached}" : call
318
384
  end
319
385
 
320
386
  def split_call_args(args, env, current_scope)
321
- block = nil
387
+ block_form = nil
322
388
  remaining = args
323
389
  if !remaining.empty? && block_form?(remaining.last)
324
- block = emit_expr(remaining.last, env, current_scope)
390
+ block_form = remaining.last
325
391
  remaining = remaining[0...-1]
326
392
  end
327
393
 
@@ -332,7 +398,24 @@ module Kapusta
332
398
  kwargs = nil
333
399
  positional = remaining.map { |arg| emit_expr(arg, env, current_scope) }
334
400
  end
335
- [positional, kwargs, block]
401
+ [positional, kwargs, block_form]
402
+ end
403
+
404
+ def emit_block_proc(block_form, env, current_scope)
405
+ block_form && emit_expr(block_form, env, current_scope)
406
+ end
407
+
408
+ def emit_attached_block(block_form, env, current_scope)
409
+ return unless block_form.is_a?(List) && block_form.head.is_a?(Sym)
410
+ return unless %w[fn lambda λ].include?(block_form.head.name)
411
+
412
+ pattern = block_form.items[1]
413
+ return unless pattern.is_a?(Vec) && simple_parameter_pattern?(pattern)
414
+
415
+ body = block_form.items[2..]
416
+ params, body_code = build_simple_block_parts(pattern, body, env, current_scope)
417
+ header = params.empty? ? 'do' : "do |#{params.join(', ')}|"
418
+ [header, indent(body_code), 'end'].join("\n")
336
419
  end
337
420
 
338
421
  def emit_method_name(form, env, current_scope)
@@ -404,13 +487,17 @@ module Kapusta
404
487
 
405
488
  def simple_expression?(code)
406
489
  code.match?(/\A[a-z_]\w*\z/) ||
490
+ code.match?(/\A@@?[a-z_]\w*\z/) ||
491
+ code.match?(/\A\$[a-zA-Z_]\w*\z/) ||
407
492
  code.match?(/\A[A-Z]\w*(?:::[A-Z]\w*)*\z/) ||
408
493
  code.match?(/\A[a-z_]\w*[!?=]?\([^()\n]*\)\z/) ||
409
494
  code.match?(/\A\d+(?:\.\d+)?\z/) ||
410
495
  code.match?(/\A[a-z_]\w*(?:\.[a-z_]\w*[!?=]?(?:\([^()\n]*\))?|\[[^\[\]]*\])+\z/) ||
496
+ code.match?(/\A[A-Z]\w*(?:::[A-Z]\w*)*(?:\.[a-z_]\w*[!?=]?(?:\([^()\n]*\))?|\[[^\[\]]*\])+\z/) ||
411
497
  code.match?(/\A:[a-zA-Z_]\w*[!?=]?\z/) ||
412
498
  code.match?(/\A"(?:[^"\\]|\\.)*"\z/) ||
413
499
  code.match?(/\A'(?:[^'\\]|\\.)*'\z/) ||
500
+ code.match?(/\A\[[^\[\]\n]*\]\z/) ||
414
501
  %w[nil true false self].include?(code) ||
415
502
  negation_simple?(code)
416
503
  end
@@ -8,7 +8,7 @@ module Kapusta
8
8
 
9
9
  def emit_pattern_bind(pattern, value_code, env)
10
10
  if pattern.is_a?(Sym)
11
- return ['nil', env] if pattern.name == '_'
11
+ return ['', env] if pattern.name == '_'
12
12
 
13
13
  ruby_name = define_local(env, pattern)
14
14
  ["#{ruby_name} = #{value_code}", env]
@@ -266,8 +266,9 @@ module Kapusta
266
266
  until_code = until_form ? "break if #{emit_expr(until_form, loop_env, current_scope)}" : nil
267
267
  body = [until_code, body_code].compact.reject(&:empty?).join("\n")
268
268
  step_part = step_code == '1' ? '' : ", #{step_code}"
269
+ block_args = ruby_name == '_' ? '' : " |#{ruby_name}|"
269
270
  [
270
- "#{parenthesize(start_code)}.step(#{finish_code}#{step_part}) do |#{ruby_name}|",
271
+ "#{parenthesize(start_code)}.step(#{finish_code}#{step_part}) do#{block_args}",
271
272
  indent(body),
272
273
  'end'
273
274
  ].join("\n")
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kapusta
4
- VERSION = '0.2.1'
4
+ VERSION = '0.2.3'
5
5
  end
@@ -399,6 +399,10 @@ RSpec.describe 'examples' do
399
399
  expect(run_example('shapes.kap')).to eq("78.5\n9\n8\n0\n")
400
400
  end
401
401
 
402
+ it 'single-number.kap' do
403
+ expect(run_example('single-number.kap')).to eq("1\n4\n1\n")
404
+ end
405
+
402
406
  it 'squares.kap' do
403
407
  expect(run_example('squares.kap')).to eq("1\n4\n9\n16\n25\n")
404
408
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kapusta
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evgenii Morozov
@@ -80,6 +80,7 @@ files:
80
80
  - examples/safe-lookup.kap
81
81
  - examples/scopes.kap
82
82
  - examples/shapes.kap
83
+ - examples/single-number.kap
83
84
  - examples/squares.kap
84
85
  - examples/stack.kap
85
86
  - examples/sum.kap
@@ -123,10 +124,10 @@ files:
123
124
  - spec/reader_spec.rb
124
125
  - spec/spec_helper.rb
125
126
  homepage: https://github.com/evmorov/kapusta
126
- licenses: []
127
+ licenses:
128
+ - MIT
127
129
  metadata:
128
130
  rubygems_mfa_required: 'true'
129
- homepage_uri: https://github.com/evmorov/kapusta
130
131
  source_code_uri: https://github.com/evmorov/kapusta
131
132
  bug_tracker_uri: https://github.com/evmorov/kapusta/issues
132
133
  rdoc_options: []