kapusta 0.13.2 → 0.15.0

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.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +50 -11
  3. data/bin/check-all +6 -1
  4. data/bin/compile-examples +7 -2
  5. data/examples/anagram.kap +3 -3
  6. data/examples/app/args.kap +9 -0
  7. data/examples/arrange-coins.kap +3 -3
  8. data/examples/baseball-game.kap +5 -5
  9. data/examples/best-time-to-buy-sell-stock.kap +2 -2
  10. data/examples/binary-search.kap +2 -2
  11. data/examples/binary-to-decimal.kap +1 -1
  12. data/examples/blocks-and-kwargs.kap +2 -2
  13. data/examples/count-effects.kap +1 -1
  14. data/examples/count-items-matching-rule.kap +18 -0
  15. data/examples/digit-tools.kap +24 -0
  16. data/examples/doto-hygiene.kap +2 -2
  17. data/examples/doto.kap +2 -2
  18. data/examples/egg-count.kap +1 -1
  19. data/examples/excel-column.kap +26 -0
  20. data/examples/exceptions.kap +1 -1
  21. data/examples/falling-drops.kap +7 -7
  22. data/examples/fennel-parity-examples.txt +3 -6
  23. data/examples/good-pairs.kap +18 -0
  24. data/examples/greet.kap +1 -1
  25. data/examples/happy-number.kap +2 -2
  26. data/examples/left-right-difference.kap +60 -0
  27. data/examples/length-of-last-word.kap +4 -4
  28. data/examples/logger-rate-limiter.kap +26 -0
  29. data/examples/manhattan-distance.kap +1 -1
  30. data/examples/maximum-subarray.kap +23 -7
  31. data/examples/minimum-start-value.kap +19 -0
  32. data/examples/move-zeroes.kap +2 -2
  33. data/examples/mruby-runtime-examples.txt +10 -2
  34. data/examples/non-constant-local.kap +1 -1
  35. data/examples/number-of-1-bits.kap +1 -1
  36. data/examples/number-of-steps.kap +1 -1
  37. data/examples/palindrome.kap +2 -2
  38. data/examples/pangram.kap +4 -4
  39. data/examples/pcall.kap +3 -3
  40. data/examples/pipeline.kap +4 -4
  41. data/examples/plus-one.kap +3 -3
  42. data/examples/raindrops.kap +1 -1
  43. data/examples/range-width.kap +14 -0
  44. data/examples/recent-counter.kap +6 -6
  45. data/examples/require-local-args.kap +9 -0
  46. data/examples/require-local.kap +7 -0
  47. data/examples/require-module-local.kap +4 -0
  48. data/examples/require-module.kap +4 -0
  49. data/examples/reverse-integer.kap +1 -1
  50. data/examples/roman-to-integer.kap +3 -3
  51. data/examples/running-sum.kap +20 -0
  52. data/examples/safe-lookup.kap +2 -2
  53. data/examples/single-number.kap +1 -1
  54. data/examples/stack.kap +14 -14
  55. data/examples/subtract-product-sum.kap +1 -1
  56. data/examples/summary-ranges.kap +45 -0
  57. data/examples/threading.kap +5 -5
  58. data/examples/tset.kap +1 -1
  59. data/examples/two-sum-hash.kap +3 -3
  60. data/examples/two-sum.kap +1 -1
  61. data/examples/ugly-number.kap +1 -1
  62. data/examples/underground-system.kap +39 -0
  63. data/examples/valid-parentheses-1.kap +6 -6
  64. data/exe/kapusta-ls +49 -2
  65. data/lib/kapusta/ast.rb +8 -0
  66. data/lib/kapusta/compiler/emitter/bindings.rb +111 -89
  67. data/lib/kapusta/compiler/emitter/collections.rb +32 -40
  68. data/lib/kapusta/compiler/emitter/control_flow.rb +33 -31
  69. data/lib/kapusta/compiler/emitter/expressions.rb +21 -5
  70. data/lib/kapusta/compiler/emitter/interop.rb +172 -48
  71. data/lib/kapusta/compiler/emitter/patterns.rb +12 -14
  72. data/lib/kapusta/compiler/emitter/support.rb +70 -81
  73. data/lib/kapusta/compiler/language.rb +533 -0
  74. data/lib/kapusta/compiler/lua_compat.rb +23 -28
  75. data/lib/kapusta/compiler/macro_expander.rb +30 -30
  76. data/lib/kapusta/compiler/macro_lowerer.rb +12 -24
  77. data/lib/kapusta/compiler/normalizer.rb +25 -17
  78. data/lib/kapusta/compiler.rb +3 -24
  79. data/lib/kapusta/env.rb +2 -2
  80. data/lib/kapusta/errors.rb +2 -1
  81. data/lib/kapusta/formatter/ast_helpers.rb +78 -0
  82. data/lib/kapusta/formatter/cli.rb +125 -0
  83. data/lib/kapusta/formatter/line_helpers.rb +44 -0
  84. data/lib/kapusta/formatter/validator.rb +32 -0
  85. data/lib/kapusta/formatter.rb +363 -325
  86. data/lib/kapusta/lsp/identifier.rb +1 -1
  87. data/lib/kapusta/lsp/rename.rb +21 -11
  88. data/lib/kapusta/lsp/scope_walker.rb +122 -212
  89. data/lib/kapusta/lsp/workspace_index.rb +17 -5
  90. data/lib/kapusta/reader.rb +4 -2
  91. data/lib/kapusta/version.rb +1 -1
  92. data/lib/kapusta.rb +39 -6
  93. data/spec/cli_spec.rb +13 -0
  94. data/spec/examples_errors_spec.rb +3 -1
  95. data/spec/examples_spec.rb +99 -15
  96. data/spec/formatter_spec.rb +246 -0
  97. data/spec/lsp_spec.rb +69 -0
  98. data/spec/require_spec.rb +294 -0
  99. metadata +23 -2
  100. data/examples/describe.kap +0 -9
data/spec/lsp_spec.rb CHANGED
@@ -111,6 +111,16 @@ RSpec.describe Kapusta::LSP do
111
111
  expect(responses.last.dig('params', 'diagnostics')).to be_empty
112
112
  end
113
113
 
114
+ it 'publishes diagnostics for an unknown class body form' do
115
+ responses = run(
116
+ frame_initialize,
117
+ frame_did_open('file:///x.kap', "(class BankAccount)\n\n(n initialize [owner balance]\n owner)\n\n(end)\n")
118
+ )
119
+
120
+ expect(responses.last.dig('params', 'diagnostics', 0, 'message'))
121
+ .to eq('class body form must be a declaration or known special form: n')
122
+ end
123
+
114
124
  it 'returns a TextEdit for formatting' do
115
125
  responses = run(
116
126
  frame_initialize,
@@ -123,6 +133,18 @@ RSpec.describe Kapusta::LSP do
123
133
  expect(edits.first).to include('range', 'newText')
124
134
  end
125
135
 
136
+ it 'formats through the LSP without collapsing full hash pairs into shorthand' do
137
+ text = "(let [active [] id 7]\n{:active active : id})\n"
138
+ responses = run(
139
+ frame_initialize,
140
+ frame_did_open('file:///x.kap', text),
141
+ frame_formatting(uri: 'file:///x.kap')
142
+ )
143
+ edits = result_for(responses)['result']
144
+
145
+ expect(edits.first['newText']).to include('{:active active : id}')
146
+ end
147
+
126
148
  it 'rejects requests sent before initialize' do
127
149
  responses = run(
128
150
  frame(jsonrpc: '2.0', id: 1, method: 'textDocument/formatting',
@@ -145,6 +167,35 @@ RSpec.describe Kapusta::LSP do
145
167
  expect(changes.first['edits'].map { |e| e['newText'] }).to eq(%w[y y y])
146
168
  end
147
169
 
170
+ it 'renames only the base binding in a colon hash lookup shorthand' do
171
+ text = "(let [user {:name \"Ada\"}]\n (print user:name))\n"
172
+ responses = run(
173
+ frame_initialize,
174
+ frame_did_open('file:///x.kap', text),
175
+ frame_rename(uri: 'file:///x.kap', **cursor_at(text, 'user:name'), new_name: 'person')
176
+ )
177
+ edits = result_for(responses)['result']['documentChanges'].first['edits']
178
+
179
+ expect(edits.map { |e| e['newText'] }).to eq(%w[person person])
180
+ expect(edits.map { |e| [e['range']['start']['line'], e['range']['start']['character']] })
181
+ .to contain_exactly([0, 6], [1, 9])
182
+ end
183
+
184
+ it 'does not offer rename on a colon hash key segment' do
185
+ text = "(let [user {:name \"Ada\"}]\n (print user:name))\n"
186
+ key_index = text.index('user:name') + 'user:'.length
187
+ prefix = text[0...key_index]
188
+ last_nl = prefix.rindex("\n")
189
+ position = { line: prefix.count("\n"), character: last_nl ? key_index - last_nl - 1 : key_index }
190
+ responses = run(
191
+ frame_initialize,
192
+ frame_did_open('file:///x.kap', text),
193
+ frame_prepare_rename(uri: 'file:///x.kap', **position)
194
+ )
195
+
196
+ expect(result_for(responses)['result']).to be_nil
197
+ end
198
+
148
199
  it 'renames a let binding referenced inside an accumulate iterator with multiple binders' do
149
200
  text = "(let [xs [1 2 3]\n total (accumulate [s 0 _ x (ipairs xs)] (+ s x))]\n (print total))\n"
150
201
  idx = text.index('(ipairs xs)') + 'ipairs '.length + 1
@@ -359,6 +410,24 @@ RSpec.describe Kapusta::LSP do
359
410
  )
360
411
  end
361
412
 
413
+ it 'jumps from a colon hash lookup base to its local binding' do
414
+ text = "(let [user {:name \"Ada\"}]\n user:name)\n"
415
+ responses = run(
416
+ frame_initialize,
417
+ frame_did_open('file:///x.kap', text),
418
+ frame_definition(uri: 'file:///x.kap', **cursor_at(text, 'user:name'))
419
+ )
420
+ result = result_for(responses)['result']
421
+
422
+ expect(result).to eq(
423
+ 'uri' => 'file:///x.kap',
424
+ 'range' => {
425
+ 'start' => { 'line' => 0, 'character' => 6 },
426
+ 'end' => { 'line' => 0, 'character' => 10 }
427
+ }
428
+ )
429
+ end
430
+
362
431
  it 'rejects renaming a class to a lowercase name with a clear message' do
363
432
  text = "(class Accumulator)\n\n(end)\n"
364
433
  responses = run(
@@ -0,0 +1,294 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'fileutils'
5
+ require 'tmpdir'
6
+
7
+ RSpec.describe 'Kapusta require' do
8
+ it 'returns cached final values from .kap relative requires resolved from the current .kap file' do
9
+ Dir.mktmpdir('kapusta-require-local') do |dir|
10
+ app_dir = File.join(dir, 'app')
11
+ other_dir = File.join(dir, 'other')
12
+ FileUtils.mkdir_p([app_dir, other_dir])
13
+ counter_path = File.join(dir, 'loads.txt')
14
+
15
+ File.write(File.join(app_dir, 'args.kap'), <<~KAP)
16
+ (ruby #{"File.write(#{counter_path.inspect}, 'x', mode: 'a')".inspect})
17
+
18
+ (fn parse [argv]
19
+ (argv.join ","))
20
+
21
+ {: parse}
22
+ KAP
23
+
24
+ File.write(File.join(app_dir, 'main.kap'), <<~KAP)
25
+ (local args (require "./args"))
26
+ (local again (require "./args"))
27
+
28
+ [((: args :parse) ["alpha" "beta"])
29
+ ((: again :parse) ["gamma"])]
30
+ KAP
31
+
32
+ result = Dir.chdir(other_dir) do
33
+ Kapusta.dofile(File.join(app_dir, 'main.kap'))
34
+ end
35
+
36
+ expect(result).to eq(['alpha,beta', 'gamma'])
37
+ expect(File.read(counter_path)).to eq('x')
38
+ end
39
+ end
40
+
41
+ it 'calls functions on required .kap module maps with colon syntax' do
42
+ Dir.mktmpdir('kapusta-require-local-map-call') do |dir|
43
+ File.write(File.join(dir, 'probe.kap'), <<~KAP)
44
+ (fn parse-size [output]
45
+ (.. "size:" output))
46
+
47
+ {: parse-size}
48
+ KAP
49
+
50
+ File.write(File.join(dir, 'main.kap'), <<~KAP)
51
+ (local probe (require "./probe"))
52
+
53
+ (probe:parse-size "42 120")
54
+ KAP
55
+
56
+ expect(Kapusta.dofile(File.join(dir, 'main.kap'))).to eq('size:42 120')
57
+ end
58
+ end
59
+
60
+ it 'keeps dotted calls on required .kap module maps as method calls' do
61
+ Dir.mktmpdir('kapusta-require-local-map-dotted-call') do |dir|
62
+ File.write(File.join(dir, 'probe.kap'), <<~KAP)
63
+ (fn parse-size [output]
64
+ (.. "size:" output))
65
+
66
+ {: parse-size}
67
+ KAP
68
+
69
+ main_path = File.join(dir, 'main.kap')
70
+ File.write(main_path, <<~KAP)
71
+ (local probe (require "./probe"))
72
+
73
+ (probe.parse-size "42 120")
74
+ KAP
75
+
76
+ expect(Kapusta.compile(File.read(main_path), path: main_path)).to eq(<<~RUBY)
77
+ probe = require_relative "probe"
78
+ probe.parse_size("42 120")
79
+ RUBY
80
+ end
81
+ end
82
+
83
+ it 'compiles local aliases for .kap module requires to plain Ruby require and constant assignment' do
84
+ Dir.mktmpdir('kapusta-require-module-local-alias') do |dir|
85
+ app_dir = File.join(dir, 'app')
86
+ FileUtils.mkdir_p(app_dir)
87
+ File.write(File.join(app_dir, 'search.kap'), <<~KAP)
88
+ (module App.Search)
89
+
90
+ (defn active? [state]
91
+ true)
92
+
93
+ (end)
94
+ KAP
95
+ main_path = File.join(dir, 'main.kap')
96
+ File.write(main_path, <<~KAP)
97
+ (local search (require :app.search))
98
+ (search.active? {})
99
+ KAP
100
+
101
+ expect(Kapusta.compile(File.read(main_path), path: main_path)).to eq(<<~RUBY)
102
+ require_relative "app/search"
103
+ search = App::Search
104
+ search.active?({})
105
+ RUBY
106
+ end
107
+ end
108
+
109
+ it 'keeps nested module require aliases isolated when names repeat' do
110
+ Dir.mktmpdir('kapusta-require-module-nested-alias') do |dir|
111
+ app_dir = File.join(dir, 'app')
112
+ FileUtils.mkdir_p(app_dir)
113
+
114
+ File.write(File.join(app_dir, 'base.kap'), <<~KAP)
115
+ (module App.Base)
116
+
117
+ (defn value []
118
+ "base")
119
+
120
+ (end)
121
+ KAP
122
+
123
+ File.write(File.join(app_dir, 'inner.kap'), <<~KAP)
124
+ (module App.Inner)
125
+
126
+ (local mod (require "./base"))
127
+
128
+ (defn value []
129
+ (.. "inner:" (mod.value)))
130
+
131
+ (end)
132
+ KAP
133
+
134
+ File.write(File.join(app_dir, 'outer.kap'), <<~KAP)
135
+ (module App.Outer)
136
+
137
+ (local mod (require "./inner"))
138
+
139
+ (defn value []
140
+ (.. "outer:" (mod.value)))
141
+
142
+ (end)
143
+ KAP
144
+
145
+ main_path = File.join(dir, 'main.kap')
146
+ File.write(main_path, <<~KAP)
147
+ (local mod (require :app.outer))
148
+ (mod.value)
149
+ KAP
150
+
151
+ expect(Kapusta.dofile(main_path)).to eq('outer:inner:base')
152
+ end
153
+ end
154
+
155
+ it 'compiles class instances created after relative requires' do
156
+ Dir.mktmpdir('kapusta-require-class-instance') do |dir|
157
+ app_dir = File.join(dir, 'app')
158
+ platform_dir = File.join(dir, 'platform')
159
+ FileUtils.mkdir_p([app_dir, platform_dir])
160
+
161
+ File.write(File.join(platform_dir, 'browser.kap'), <<~KAP)
162
+ (class RequireClassInstance.Browser)
163
+
164
+ (fn open [url]
165
+ url)
166
+
167
+ (end)
168
+ KAP
169
+
170
+ commands_path = File.join(app_dir, 'commands.kap')
171
+ File.write(commands_path, <<~KAP)
172
+ (class App.Commands)
173
+
174
+ (fn open [url]
175
+ (let [browser (do (require "../platform/browser") (RequireClassInstance.Browser.new))]
176
+ (browser.open url)))
177
+
178
+ (end)
179
+ KAP
180
+
181
+ expect(Kapusta.compile(File.read(commands_path), path: commands_path)).to eq(<<~RUBY)
182
+ module App
183
+ class Commands
184
+ def open(url)
185
+ browser = begin
186
+ require_relative "../platform/browser"
187
+ RequireClassInstance::Browser.new
188
+ end
189
+ browser.open(url)
190
+ end
191
+ end
192
+ end
193
+ RUBY
194
+ end
195
+ end
196
+
197
+ it 'keeps class instances isolated when required modules repeat local names' do
198
+ Dir.mktmpdir('kapusta-require-class-instance-isolation') do |dir|
199
+ app_dir = File.join(dir, 'app')
200
+ platform_dir = File.join(dir, 'platform')
201
+ FileUtils.mkdir_p([app_dir, platform_dir])
202
+
203
+ File.write(File.join(platform_dir, 'browser.kap'), <<~KAP)
204
+ (class RequireClassInstance.Browser)
205
+
206
+ (fn initialize [name]
207
+ (set @name name))
208
+
209
+ (fn open [url]
210
+ (.. @name ":" url))
211
+
212
+ (end)
213
+ KAP
214
+
215
+ File.write(File.join(app_dir, 'inner.kap'), <<~KAP)
216
+ (module App.Inner)
217
+
218
+ (defn open [url]
219
+ (let [browser (do (require "../platform/browser")
220
+ (RequireClassInstance.Browser.new "inner-browser"))]
221
+ (browser.open (.. "inner:" url))))
222
+
223
+ (end)
224
+ KAP
225
+
226
+ File.write(File.join(app_dir, 'outer.kap'), <<~KAP)
227
+ (module App.Outer)
228
+
229
+ (require "./inner")
230
+
231
+ (defn open [url]
232
+ (let [browser (do (require "../platform/browser")
233
+ (RequireClassInstance.Browser.new "outer-browser"))]
234
+ (.. (browser.open (.. "outer:" url)) "|" (App.Inner.open url))))
235
+
236
+ (end)
237
+ KAP
238
+
239
+ main_path = File.join(dir, 'main.kap')
240
+ File.write(main_path, <<~KAP)
241
+ (require :app.outer)
242
+ (App.Outer.open "x")
243
+ KAP
244
+
245
+ expect(Kapusta.dofile(main_path)).to eq('outer-browser:outer:x|inner-browser:inner:x')
246
+ end
247
+ end
248
+
249
+ it 'delegates relative requires to Ruby for .rb files' do
250
+ Dir.mktmpdir('kapusta-require-local-ruby') do |dir|
251
+ mod_name = "KapustaRequireRelativeRubyFeature#{rand(1_000_000)}"
252
+ File.write(File.join(dir, 'feature.rb'), <<~RUBY)
253
+ module #{mod_name}
254
+ VALUE = 7
255
+ end
256
+ RUBY
257
+ File.write(File.join(dir, 'main.kap'), <<~KAP)
258
+ (require "./feature")
259
+ (ruby "#{mod_name}::VALUE")
260
+ KAP
261
+
262
+ expect(Kapusta.dofile(File.join(dir, 'main.kap'))).to eq(7)
263
+ end
264
+ end
265
+
266
+ it 'returns cached final values from .kap module-path requires' do
267
+ Dir.mktmpdir('kapusta-require-module') do |dir|
268
+ app_dir = File.join(dir, 'app')
269
+ FileUtils.mkdir_p(app_dir)
270
+ counter_path = File.join(dir, 'loads.txt')
271
+
272
+ File.write(File.join(app_dir, 'args.kap'), <<~KAP)
273
+ (ruby #{"File.write(#{counter_path.inspect}, 'x', mode: 'a')".inspect})
274
+
275
+ (fn parse [argv]
276
+ (argv.join ":"))
277
+
278
+ {: parse}
279
+ KAP
280
+
281
+ begin
282
+ $LOAD_PATH.unshift(dir)
283
+ first = Kapusta.require(:'app.args')
284
+ second = Kapusta.require(:'app.args')
285
+
286
+ expect(first[:parse].call(%w[left right])).to eq('left:right')
287
+ expect(second).to equal(first)
288
+ expect(File.read(counter_path)).to eq('x')
289
+ ensure
290
+ $LOAD_PATH.delete(dir)
291
+ end
292
+ end
293
+ end
294
+ 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.13.2
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evgenii Morozov
@@ -31,6 +31,7 @@ files:
31
31
  - examples/ackermann.kap
32
32
  - examples/anagram.kap
33
33
  - examples/anonymous-greeter.kap
34
+ - examples/app/args.kap
34
35
  - examples/arrange-coins.kap
35
36
  - examples/array-sign.kap
36
37
  - examples/bank-account.kap
@@ -49,15 +50,17 @@ files:
49
50
  - examples/contains-duplicate.kap
50
51
  - examples/convert-temperature.kap
51
52
  - examples/count-effects.kap
53
+ - examples/count-items-matching-rule.kap
52
54
  - examples/counter.kap
53
- - examples/describe.kap
54
55
  - examples/destructure.kap
56
+ - examples/digit-tools.kap
55
57
  - examples/divisibility-stats.kap
56
58
  - examples/doto-hygiene.kap
57
59
  - examples/doto.kap
58
60
  - examples/egg-count.kap
59
61
  - examples/equal-sums.kap
60
62
  - examples/even-squares.kap
63
+ - examples/excel-column.kap
61
64
  - examples/exceptions.kap
62
65
  - examples/factorial.kap
63
66
  - examples/falling-drops.kap
@@ -66,6 +69,7 @@ files:
66
69
  - examples/files.kap
67
70
  - examples/fizzbuzz.kap
68
71
  - examples/gcd.kap
72
+ - examples/good-pairs.kap
69
73
  - examples/greet.kap
70
74
  - examples/happy-number.kap
71
75
  - examples/hashfn.kap
@@ -73,7 +77,9 @@ files:
73
77
  - examples/import-helpers.kapm
74
78
  - examples/kwargs.kap
75
79
  - examples/leap-year.kap
80
+ - examples/left-right-difference.kap
76
81
  - examples/length-of-last-word.kap
82
+ - examples/logger-rate-limiter.kap
77
83
  - examples/macros-dbg.kap
78
84
  - examples/macros-import-helpers.kap
79
85
  - examples/macros-import-whole.kap
@@ -89,6 +95,7 @@ files:
89
95
  - examples/max-achievable.kap
90
96
  - examples/maximum-subarray.kap
91
97
  - examples/min-max.kap
98
+ - examples/minimum-start-value.kap
92
99
  - examples/module-header.kap
93
100
  - examples/move-zeroes.kap
94
101
  - examples/mruby-runtime-examples.txt
@@ -109,12 +116,18 @@ files:
109
116
  - examples/power-of-three.kap
110
117
  - examples/primes.kap
111
118
  - examples/raindrops.kap
119
+ - examples/range-width.kap
112
120
  - examples/recent-counter.kap
113
121
  - examples/record.kap
114
122
  - examples/regex.kap
123
+ - examples/require-local-args.kap
124
+ - examples/require-local.kap
125
+ - examples/require-module-local.kap
126
+ - examples/require-module.kap
115
127
  - examples/reverse-integer.kap
116
128
  - examples/roman-to-integer.kap
117
129
  - examples/ruby-eval.kap
130
+ - examples/running-sum.kap
118
131
  - examples/safe-lookup.kap
119
132
  - examples/scopes.kap
120
133
  - examples/shapes.kap
@@ -125,6 +138,7 @@ files:
125
138
  - examples/stack.kap
126
139
  - examples/subtract-product-sum.kap
127
140
  - examples/sum.kap
141
+ - examples/summary-ranges.kap
128
142
  - examples/thread-styles.kap
129
143
  - examples/threading.kap
130
144
  - examples/tic-tac-toe.kap
@@ -132,6 +146,7 @@ files:
132
146
  - examples/two-sum-hash.kap
133
147
  - examples/two-sum.kap
134
148
  - examples/ugly-number.kap
149
+ - examples/underground-system.kap
135
150
  - examples/underscore-patterns.kap
136
151
  - examples/use_bank_account.rb
137
152
  - examples/valid-parentheses-1.kap
@@ -155,6 +170,7 @@ files:
155
170
  - lib/kapusta/compiler/emitter/patterns.rb
156
171
  - lib/kapusta/compiler/emitter/simple_expression.rb
157
172
  - lib/kapusta/compiler/emitter/support.rb
173
+ - lib/kapusta/compiler/language.rb
158
174
  - lib/kapusta/compiler/lua_compat.rb
159
175
  - lib/kapusta/compiler/macro_expander.rb
160
176
  - lib/kapusta/compiler/macro_gensym.rb
@@ -165,6 +181,10 @@ files:
165
181
  - lib/kapusta/error.rb
166
182
  - lib/kapusta/errors.rb
167
183
  - lib/kapusta/formatter.rb
184
+ - lib/kapusta/formatter/ast_helpers.rb
185
+ - lib/kapusta/formatter/cli.rb
186
+ - lib/kapusta/formatter/line_helpers.rb
187
+ - lib/kapusta/formatter/validator.rb
168
188
  - lib/kapusta/lsp.rb
169
189
  - lib/kapusta/lsp/definition.rb
170
190
  - lib/kapusta/lsp/diagnostics.rb
@@ -181,6 +201,7 @@ files:
181
201
  - spec/examples_spec.rb
182
202
  - spec/formatter_spec.rb
183
203
  - spec/lsp_spec.rb
204
+ - spec/require_spec.rb
184
205
  - spec/spec_helper.rb
185
206
  homepage: https://github.com/evmorov/kapusta
186
207
  licenses:
@@ -1,9 +0,0 @@
1
- (fn describe [x]
2
- (case x
3
- 0 "zero"
4
- 1 "one"
5
- (where n (< n 0)) "negative"
6
- _ "many"))
7
-
8
- (each [_ n (ipairs [-3 0 1 2 99])]
9
- (print n (describe n)))