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.
- checksums.yaml +4 -4
- data/README.md +50 -11
- data/bin/check-all +6 -1
- data/bin/compile-examples +7 -2
- data/examples/anagram.kap +3 -3
- data/examples/app/args.kap +9 -0
- data/examples/arrange-coins.kap +3 -3
- data/examples/baseball-game.kap +5 -5
- data/examples/best-time-to-buy-sell-stock.kap +2 -2
- data/examples/binary-search.kap +2 -2
- data/examples/binary-to-decimal.kap +1 -1
- data/examples/blocks-and-kwargs.kap +2 -2
- data/examples/count-effects.kap +1 -1
- data/examples/count-items-matching-rule.kap +18 -0
- data/examples/digit-tools.kap +24 -0
- data/examples/doto-hygiene.kap +2 -2
- data/examples/doto.kap +2 -2
- data/examples/egg-count.kap +1 -1
- data/examples/excel-column.kap +26 -0
- data/examples/exceptions.kap +1 -1
- data/examples/falling-drops.kap +7 -7
- data/examples/fennel-parity-examples.txt +3 -6
- data/examples/good-pairs.kap +18 -0
- data/examples/greet.kap +1 -1
- data/examples/happy-number.kap +2 -2
- data/examples/left-right-difference.kap +60 -0
- data/examples/length-of-last-word.kap +4 -4
- data/examples/logger-rate-limiter.kap +26 -0
- data/examples/manhattan-distance.kap +1 -1
- data/examples/maximum-subarray.kap +23 -7
- data/examples/minimum-start-value.kap +19 -0
- data/examples/move-zeroes.kap +2 -2
- data/examples/mruby-runtime-examples.txt +10 -2
- data/examples/non-constant-local.kap +1 -1
- data/examples/number-of-1-bits.kap +1 -1
- data/examples/number-of-steps.kap +1 -1
- data/examples/palindrome.kap +2 -2
- data/examples/pangram.kap +4 -4
- data/examples/pcall.kap +3 -3
- data/examples/pipeline.kap +4 -4
- data/examples/plus-one.kap +3 -3
- data/examples/raindrops.kap +1 -1
- data/examples/range-width.kap +14 -0
- data/examples/recent-counter.kap +6 -6
- data/examples/require-local-args.kap +9 -0
- data/examples/require-local.kap +7 -0
- data/examples/require-module-local.kap +4 -0
- data/examples/require-module.kap +4 -0
- data/examples/reverse-integer.kap +1 -1
- data/examples/roman-to-integer.kap +3 -3
- data/examples/running-sum.kap +20 -0
- data/examples/safe-lookup.kap +2 -2
- data/examples/single-number.kap +1 -1
- data/examples/stack.kap +14 -14
- data/examples/subtract-product-sum.kap +1 -1
- data/examples/summary-ranges.kap +45 -0
- data/examples/threading.kap +5 -5
- data/examples/tset.kap +1 -1
- data/examples/two-sum-hash.kap +3 -3
- data/examples/two-sum.kap +1 -1
- data/examples/ugly-number.kap +1 -1
- data/examples/underground-system.kap +39 -0
- data/examples/valid-parentheses-1.kap +6 -6
- data/exe/kapusta-ls +49 -2
- data/lib/kapusta/ast.rb +8 -0
- data/lib/kapusta/compiler/emitter/bindings.rb +111 -89
- data/lib/kapusta/compiler/emitter/collections.rb +32 -40
- data/lib/kapusta/compiler/emitter/control_flow.rb +33 -31
- data/lib/kapusta/compiler/emitter/expressions.rb +21 -5
- data/lib/kapusta/compiler/emitter/interop.rb +172 -48
- data/lib/kapusta/compiler/emitter/patterns.rb +12 -14
- data/lib/kapusta/compiler/emitter/support.rb +70 -81
- data/lib/kapusta/compiler/language.rb +533 -0
- data/lib/kapusta/compiler/lua_compat.rb +23 -28
- data/lib/kapusta/compiler/macro_expander.rb +30 -30
- data/lib/kapusta/compiler/macro_lowerer.rb +12 -24
- data/lib/kapusta/compiler/normalizer.rb +25 -17
- data/lib/kapusta/compiler.rb +3 -24
- data/lib/kapusta/env.rb +2 -2
- data/lib/kapusta/errors.rb +2 -1
- data/lib/kapusta/formatter/ast_helpers.rb +78 -0
- data/lib/kapusta/formatter/cli.rb +125 -0
- data/lib/kapusta/formatter/line_helpers.rb +44 -0
- data/lib/kapusta/formatter/validator.rb +32 -0
- data/lib/kapusta/formatter.rb +363 -325
- data/lib/kapusta/lsp/identifier.rb +1 -1
- data/lib/kapusta/lsp/rename.rb +21 -11
- data/lib/kapusta/lsp/scope_walker.rb +122 -212
- data/lib/kapusta/lsp/workspace_index.rb +17 -5
- data/lib/kapusta/reader.rb +4 -2
- data/lib/kapusta/version.rb +1 -1
- data/lib/kapusta.rb +39 -6
- data/spec/cli_spec.rb +13 -0
- data/spec/examples_errors_spec.rb +3 -1
- data/spec/examples_spec.rb +99 -15
- data/spec/formatter_spec.rb +246 -0
- data/spec/lsp_spec.rb +69 -0
- data/spec/require_spec.rb +294 -0
- metadata +23 -2
- 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.
|
|
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:
|