crystalruby 0.1.8 → 0.1.9
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 +125 -0
- data/lib/crystalruby/template.rb +1 -1
- data/lib/crystalruby/templates/inline_chunk.cr +6 -0
- data/lib/crystalruby/version.rb +1 -1
- data/lib/crystalruby.rb +17 -3
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ca096d0563b6201c3ef4f084fff3304cfa212fda88e81085580b2de5ff10536f
|
4
|
+
data.tar.gz: ccc68dc96c30f973c9bafcbaec75a2461bbaa275e32913a0781c4cc5488f034f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 134e9888d563673d78dc0b9075a239ee3bab6c4a07eb63ff903c748b97684ec87e9bb33011e9f276504f855edd2a25c29860ebc626aa181f74350f68ace8b9e8
|
7
|
+
data.tar.gz: f3f7a25d12459178e5c8d3cb6a46cfa0e375f65099cdcde15c834a1ba0872198b8475919ec7e5472fa10529bfb71ede67e0edfb88105be5eb220226f2d0ba4ad
|
data/README.md
CHANGED
@@ -295,6 +295,131 @@ end
|
|
295
295
|
MyModule.add("1", "2")
|
296
296
|
```
|
297
297
|
|
298
|
+
## Inline Chunks
|
299
|
+
|
300
|
+
`crystalruby` also allows you to write inline Crystal code that does not require binding to Ruby. This can be useful for e.g. performing setup or teardown operations.
|
301
|
+
|
302
|
+
Follow these steps for a toy example of how we can use crystalized ruby and inline chunks to expose the [crystal-redis](https://github.com/stefanwille/crystal-redis) library to Ruby.
|
303
|
+
|
304
|
+
1. Start our toy project
|
305
|
+
|
306
|
+
```bash
|
307
|
+
mkdir crystalredis
|
308
|
+
cd crystalredis
|
309
|
+
bundle init
|
310
|
+
```
|
311
|
+
|
312
|
+
2. Add dependencies to our Gemfile and run `bundle install`
|
313
|
+
|
314
|
+
```ruby
|
315
|
+
# frozen_string_literal: true
|
316
|
+
|
317
|
+
source "https://rubygems.org"
|
318
|
+
|
319
|
+
gem 'crystalruby'
|
320
|
+
|
321
|
+
# Let's see if performance is comparable to that of the redis gem.
|
322
|
+
gem 'benchmark-ips'
|
323
|
+
gem 'redis'
|
324
|
+
```
|
325
|
+
|
326
|
+
3. Write our Redis client
|
327
|
+
|
328
|
+
```ruby
|
329
|
+
# Filename: crystalredis.rb
|
330
|
+
require 'crystalruby'
|
331
|
+
|
332
|
+
module CrystalRedis
|
333
|
+
|
334
|
+
crystal do
|
335
|
+
CLIENT = Redis.new
|
336
|
+
def self.client
|
337
|
+
CLIENT
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
crystalize [key: :string, value: :string] => :void
|
342
|
+
def set(key, value)
|
343
|
+
client.set(key, value)
|
344
|
+
end
|
345
|
+
|
346
|
+
crystalize [key: :string] => :string
|
347
|
+
def get(key)
|
348
|
+
client.get(key).to_s
|
349
|
+
end
|
350
|
+
end
|
351
|
+
```
|
352
|
+
|
353
|
+
4. Load the modules (without running them) to generate our Crystal project skeleton.
|
354
|
+
|
355
|
+
```bash
|
356
|
+
bundle exec ruby crystalredis.rb
|
357
|
+
```
|
358
|
+
|
359
|
+
5. Add the missing Redis dependency to our shard.yml
|
360
|
+
|
361
|
+
```yaml
|
362
|
+
# filename: crystalruby/src/shard.yml
|
363
|
+
dependencies:
|
364
|
+
redis:
|
365
|
+
github: stefanwille/crystal-redis
|
366
|
+
```
|
367
|
+
|
368
|
+
```ruby
|
369
|
+
# filename: main.cr
|
370
|
+
require "redis"
|
371
|
+
require "./generated/index"
|
372
|
+
```
|
373
|
+
|
374
|
+
```bash
|
375
|
+
bundle exec crystalruby install
|
376
|
+
```
|
377
|
+
|
378
|
+
6. Compile and benchmark our new module in Ruby
|
379
|
+
|
380
|
+
```ruby
|
381
|
+
# Filename: benchmark.rb
|
382
|
+
# Let's compare the performance of our CrystalRedis module to the Ruby Redis gem
|
383
|
+
require_relative "crystalredis"
|
384
|
+
require 'redis'
|
385
|
+
require 'benchmark/ips'
|
386
|
+
|
387
|
+
Benchmark.ips do |x|
|
388
|
+
rbredis = Redis.new
|
389
|
+
|
390
|
+
x.report(:crredis) do
|
391
|
+
CrystalRedis.set("hello", "world")
|
392
|
+
CrystalRedis.get("hello")
|
393
|
+
end
|
394
|
+
|
395
|
+
x.report(:rbredis) do
|
396
|
+
rbredis.set("hello", "world")
|
397
|
+
rbredis.get("hello")
|
398
|
+
end
|
399
|
+
end
|
400
|
+
```
|
401
|
+
|
402
|
+
7. Run the benchmark
|
403
|
+
|
404
|
+
```bash
|
405
|
+
$ bundle exec ruby benchmark.rb
|
406
|
+
```
|
407
|
+
|
408
|
+
### Output
|
409
|
+
|
410
|
+
```bash
|
411
|
+
|
412
|
+
#crystalredis wins! (Warm up during first run will be slow for crredis, due to first compilation)
|
413
|
+
|
414
|
+
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [arm64-darwin22]
|
415
|
+
Warming up --------------------------------------
|
416
|
+
crredis 1.946k i/100ms
|
417
|
+
rbredis 1.749k i/100ms
|
418
|
+
Calculating -------------------------------------
|
419
|
+
crredis 22.319k (± 1.7%) i/s - 112.868k in 5.058448s
|
420
|
+
rbredis 16.861k (± 9.1%) i/s - 83.952k in 5.024941s
|
421
|
+
```
|
422
|
+
|
298
423
|
## Release Builds
|
299
424
|
|
300
425
|
You can control whether CrystalRuby builds in debug or release mode by setting following config option
|
data/lib/crystalruby/template.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module CrystalRuby
|
2
2
|
module Template
|
3
3
|
Dir[File.join(File.dirname(__FILE__), "templates", "*.cr")].each do |file|
|
4
|
-
template_name = File.basename(file, File.extname(file)).capitalize
|
4
|
+
template_name = File.basename(file, File.extname(file)).split("_").map(&:capitalize).join
|
5
5
|
const_set(template_name, File.read(file))
|
6
6
|
end
|
7
7
|
|
data/lib/crystalruby/version.rb
CHANGED
data/lib/crystalruby.rb
CHANGED
@@ -22,6 +22,19 @@ module CrystalRuby
|
|
22
22
|
@crystalize_next = { raw: type.to_sym == :raw, args: args, returns: returns, block: block }
|
23
23
|
end
|
24
24
|
|
25
|
+
def crystal(type = :src, &block)
|
26
|
+
inline_crystal_body = Template.render(
|
27
|
+
Template::InlineChunk,
|
28
|
+
{
|
29
|
+
module_name: name,
|
30
|
+
body: block.source.lines[
|
31
|
+
type == :raw ? 2...-2 : 1...-1
|
32
|
+
].join("\n")
|
33
|
+
}
|
34
|
+
)
|
35
|
+
CrystalRuby.write_chunk(self, body: inline_crystal_body)
|
36
|
+
end
|
37
|
+
|
25
38
|
def crtype(&block)
|
26
39
|
TypeBuilder.with_injected_type_dsl(self) do
|
27
40
|
TypeBuilder.build(&block)
|
@@ -56,7 +69,7 @@ module CrystalRuby
|
|
56
69
|
args ||= {}
|
57
70
|
@crystalize_next = nil
|
58
71
|
function = build_function(self, method_name, args, returns, function_body)
|
59
|
-
CrystalRuby.
|
72
|
+
CrystalRuby.write_chunk(self, name: function[:name], body: function[:body]) do
|
60
73
|
extend FFI::Library
|
61
74
|
ffi_lib "#{config.crystal_lib_dir}/#{config.crystal_lib_name}"
|
62
75
|
attach_function method_name, fname, function[:ffi_types], function[:return_ffi_type]
|
@@ -226,6 +239,7 @@ module CrystalRuby
|
|
226
239
|
extend FFI::Library
|
227
240
|
ffi_lib "#{config.crystal_lib_dir}/#{config.crystal_lib_name}"
|
228
241
|
attach_function "init!", :init, [:pointer], :void
|
242
|
+
send(:remove_const, :ErrorCallback) if defined?(ErrorCallback)
|
229
243
|
const_set(:ErrorCallback, FFI::Function.new(:void, %i[string string]) do |error_type, message|
|
230
244
|
error_type = error_type.to_sym
|
231
245
|
is_exception_type = Object.const_defined?(error_type) && Object.const_get(error_type).ancestors.include?(Exception)
|
@@ -314,7 +328,7 @@ module CrystalRuby
|
|
314
328
|
|
315
329
|
def self.attach!
|
316
330
|
@block_store.each do |function|
|
317
|
-
function[:compile_callback]
|
331
|
+
function[:compile_callback]&.call
|
318
332
|
end
|
319
333
|
@attached = true
|
320
334
|
end
|
@@ -335,7 +349,7 @@ module CrystalRuby
|
|
335
349
|
File.read(digest_file_name) if File.exist?(digest_file_name)
|
336
350
|
end
|
337
351
|
|
338
|
-
def self.
|
352
|
+
def self.write_chunk(owner, body:, name: Digest::MD5.hexdigest(body), &compile_callback)
|
339
353
|
@block_store ||= []
|
340
354
|
@block_store << { owner: owner, name: name, body: body, compile_callback: compile_callback }
|
341
355
|
FileUtils.mkdir_p("#{config.crystal_src_dir}/#{config.crystal_codegen_dir}")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crystalruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wouter Coppieters
|
@@ -87,6 +87,7 @@ files:
|
|
87
87
|
- lib/crystalruby/template.rb
|
88
88
|
- lib/crystalruby/templates/function.cr
|
89
89
|
- lib/crystalruby/templates/index.cr
|
90
|
+
- lib/crystalruby/templates/inline_chunk.cr
|
90
91
|
- lib/crystalruby/typebuilder.rb
|
91
92
|
- lib/crystalruby/typemaps.rb
|
92
93
|
- lib/crystalruby/types.rb
|