crystalruby 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -0
- data/README.md +389 -193
- data/Rakefile +4 -3
- data/crystalruby.gemspec +2 -2
- data/exe/crystalruby +1 -0
- data/lib/crystalruby/adapter.rb +131 -65
- data/lib/crystalruby/arc_mutex.rb +47 -0
- data/lib/crystalruby/compilation.rb +32 -3
- data/lib/crystalruby/config.rb +41 -37
- data/lib/crystalruby/function.rb +211 -68
- data/lib/crystalruby/library.rb +153 -48
- data/lib/crystalruby/reactor.rb +40 -23
- data/lib/crystalruby/source_reader.rb +86 -0
- data/lib/crystalruby/template.rb +16 -5
- data/lib/crystalruby/templates/function.cr +11 -10
- data/lib/crystalruby/templates/index.cr +53 -66
- data/lib/crystalruby/templates/inline_chunk.cr +1 -1
- data/lib/crystalruby/templates/ruby_interface.cr +34 -0
- data/lib/crystalruby/templates/top_level_function.cr +62 -0
- data/lib/crystalruby/templates/top_level_ruby_interface.cr +33 -0
- data/lib/crystalruby/typebuilder.rb +11 -55
- data/lib/crystalruby/typemaps.rb +92 -67
- data/lib/crystalruby/types/concerns/allocator.rb +80 -0
- data/lib/crystalruby/types/fixed_width/named_tuple.cr +80 -0
- data/lib/crystalruby/types/fixed_width/named_tuple.rb +86 -0
- data/lib/crystalruby/types/fixed_width/proc.cr +45 -0
- data/lib/crystalruby/types/fixed_width/proc.rb +79 -0
- data/lib/crystalruby/types/fixed_width/tagged_union.cr +53 -0
- data/lib/crystalruby/types/fixed_width/tagged_union.rb +109 -0
- data/lib/crystalruby/types/fixed_width/tuple.cr +82 -0
- data/lib/crystalruby/types/fixed_width/tuple.rb +92 -0
- data/lib/crystalruby/types/fixed_width.cr +138 -0
- data/lib/crystalruby/types/fixed_width.rb +205 -0
- data/lib/crystalruby/types/primitive.cr +21 -0
- data/lib/crystalruby/types/primitive.rb +117 -0
- data/lib/crystalruby/types/primitive_types/bool.cr +34 -0
- data/lib/crystalruby/types/primitive_types/bool.rb +11 -0
- data/lib/crystalruby/types/primitive_types/nil.cr +35 -0
- data/lib/crystalruby/types/primitive_types/nil.rb +16 -0
- data/lib/crystalruby/types/primitive_types/numbers.cr +37 -0
- data/lib/crystalruby/types/primitive_types/numbers.rb +28 -0
- data/lib/crystalruby/types/primitive_types/symbol.cr +55 -0
- data/lib/crystalruby/types/primitive_types/symbol.rb +35 -0
- data/lib/crystalruby/types/primitive_types/time.cr +35 -0
- data/lib/crystalruby/types/primitive_types/time.rb +25 -0
- data/lib/crystalruby/types/type.cr +64 -0
- data/lib/crystalruby/types/type.rb +239 -30
- data/lib/crystalruby/types/variable_width/array.cr +74 -0
- data/lib/crystalruby/types/variable_width/array.rb +88 -0
- data/lib/crystalruby/types/variable_width/hash.cr +146 -0
- data/lib/crystalruby/types/variable_width/hash.rb +117 -0
- data/lib/crystalruby/types/variable_width/string.cr +36 -0
- data/lib/crystalruby/types/variable_width/string.rb +18 -0
- data/lib/crystalruby/types/variable_width.cr +23 -0
- data/lib/crystalruby/types/variable_width.rb +46 -0
- data/lib/crystalruby/types.rb +32 -13
- data/lib/crystalruby/version.rb +2 -2
- data/lib/crystalruby.rb +13 -6
- metadata +41 -19
- data/lib/crystalruby/types/array.rb +0 -15
- data/lib/crystalruby/types/bool.rb +0 -3
- data/lib/crystalruby/types/hash.rb +0 -17
- data/lib/crystalruby/types/named_tuple.rb +0 -28
- data/lib/crystalruby/types/nil.rb +0 -3
- data/lib/crystalruby/types/numbers.rb +0 -5
- data/lib/crystalruby/types/string.rb +0 -3
- data/lib/crystalruby/types/symbol.rb +0 -3
- data/lib/crystalruby/types/time.rb +0 -8
- data/lib/crystalruby/types/tuple.rb +0 -17
- data/lib/crystalruby/types/type_serializer/json.rb +0 -41
- data/lib/crystalruby/types/type_serializer.rb +0 -37
- data/lib/crystalruby/types/typedef.rb +0 -57
- data/lib/crystalruby/types/union_type.rb +0 -43
- data/lib/module.rb +0 -3
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CrystalRuby::Types
|
4
|
+
Hash = VariableWidth.build(error: "Hash type must have 2 type parameters. E.g. Hash(Float64, String)")
|
5
|
+
|
6
|
+
def self.Hash(key_type, value_type)
|
7
|
+
VariableWidth.build(:Hash, inner_types: [key_type, value_type], convert_if: [Root::Hash], superclass: Hash) do
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
def_delegators :@class, :value_type, :key_type
|
11
|
+
|
12
|
+
# Implement the Enumerable interface
|
13
|
+
# Helps this object to act like a true Hash
|
14
|
+
def each
|
15
|
+
if block_given?
|
16
|
+
size.times { |i| yield key_for_index(i), value_for_index(i) }
|
17
|
+
else
|
18
|
+
to_enum(:each)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def keys
|
23
|
+
each.map { |k, _| k }
|
24
|
+
end
|
25
|
+
|
26
|
+
def values
|
27
|
+
each.map { |_, v| v }
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.key_type
|
31
|
+
inner_types.first
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.value_type
|
35
|
+
inner_types.last
|
36
|
+
end
|
37
|
+
|
38
|
+
# We only accept Hash-like values, from which all elements
|
39
|
+
# can successfully be cast to our inner types
|
40
|
+
def self.cast!(value)
|
41
|
+
unless (value.is_a?(Hash) || value.is_a?(Root::Hash)) && value.keys.all?(&key_type.method(:valid_cast?)) && value.values.all?(&value_type.method(:valid_cast?))
|
42
|
+
raise CrystalRuby::InvalidCastError, "Cannot cast #{value} to #{inspect}"
|
43
|
+
end
|
44
|
+
|
45
|
+
[[key_type, value.keys], [value_type, value.values]].map do |type, values|
|
46
|
+
if type.primitive?
|
47
|
+
values.map(&type.method(:to_ffi_repr))
|
48
|
+
else
|
49
|
+
values
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.copy_to!((keys, values), memory:)
|
55
|
+
data_pointer = malloc(values.size * (key_type.refsize + value_type.refsize))
|
56
|
+
|
57
|
+
memory[size_offset].write_uint32(values.size)
|
58
|
+
memory[data_offset].write_pointer(data_pointer)
|
59
|
+
|
60
|
+
[
|
61
|
+
[key_type, data_pointer, keys],
|
62
|
+
[value_type, data_pointer[values.length * key_type.refsize], values]
|
63
|
+
].each do |type, pointer, list|
|
64
|
+
if type.primitive?
|
65
|
+
pointer.send("put_array_of_#{type.ffi_type}", 0, list)
|
66
|
+
else
|
67
|
+
list.each_with_index do |val, i|
|
68
|
+
type.write_single(pointer[i * type.refsize], val)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def index_for_key(key)
|
75
|
+
size.times { |i| return i if key_for_index(i) == key }
|
76
|
+
nil
|
77
|
+
end
|
78
|
+
|
79
|
+
def key_for_index(index)
|
80
|
+
key_type.fetch_single(data_pointer[index * key_type.refsize])
|
81
|
+
end
|
82
|
+
|
83
|
+
def value_for_index(index)
|
84
|
+
value_type.fetch_single(data_pointer[key_type.refsize * size + index * value_type.refsize])
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.each_child_address(pointer)
|
88
|
+
size = pointer[size_offset].read_int32
|
89
|
+
pointer = pointer[data_offset].read_pointer
|
90
|
+
size.times do |i|
|
91
|
+
yield key_type, pointer[i * key_type.refsize]
|
92
|
+
yield value_type, pointer[size * key_type.refsize + i * value_type.refsize]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def [](key)
|
97
|
+
return nil unless index = index_for_key(key)
|
98
|
+
|
99
|
+
value_for_index(index)
|
100
|
+
end
|
101
|
+
|
102
|
+
def []=(key, value)
|
103
|
+
if index = index_for_key(key)
|
104
|
+
value_type.write_single(data_pointer[key_type.refsize * size + index * value_type.refsize], value)
|
105
|
+
else
|
106
|
+
method_missing(:[]=, key, value)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def value(native: false)
|
111
|
+
keys = key_type.fetch_multi(data_pointer, size, native: native)
|
112
|
+
values = value_type.fetch_multi(data_pointer[key_type.refsize * size], size, native: native)
|
113
|
+
keys.zip(values).to_h
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class <%= base_crystal_class_name %> < CrystalRuby::Types::VariableWidth
|
2
|
+
|
3
|
+
def initialize(string : ::String)
|
4
|
+
@memory = malloc(data_offset + 8)
|
5
|
+
self.value = string
|
6
|
+
increment_ref_count!
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.copy_to!(value : ::String, memory : Pointer(::UInt8))
|
10
|
+
data_pointer = malloc(value.bytesize.to_u32).as(Pointer(::UInt8))
|
11
|
+
data_pointer.copy_from(value.to_unsafe, value.bytesize)
|
12
|
+
(memory+size_offset).as(Pointer(::UInt32)).value = value.bytesize.to_u32
|
13
|
+
(memory+data_offset).as(Pointer(::UInt64)).value = data_pointer.address
|
14
|
+
end
|
15
|
+
|
16
|
+
def value=(string : ::String)
|
17
|
+
if self.ref_count > 0
|
18
|
+
self.class.decr_inner_ref_counts!(memory)
|
19
|
+
end
|
20
|
+
self.class.copy_to!(string, self.memory)
|
21
|
+
end
|
22
|
+
|
23
|
+
def ==(other : <%= native_type_expr %>)
|
24
|
+
native == other
|
25
|
+
end
|
26
|
+
|
27
|
+
def value : ::String
|
28
|
+
char_ptr = (memory + data_offset).as(Pointer(Pointer(::UInt8)))
|
29
|
+
size = (memory + size_offset).as(Pointer(::UInt32))
|
30
|
+
::String.new(char_ptr[0], size[0])
|
31
|
+
end
|
32
|
+
|
33
|
+
def native : ::String
|
34
|
+
value
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module CrystalRuby::Types
|
2
|
+
String = VariableWidth.build(:String, convert_if: [String, Root::String]) do
|
3
|
+
def self.cast!(rbval)
|
4
|
+
rbval.to_s
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.copy_to!(rbval, memory:)
|
8
|
+
data_pointer = malloc(rbval.bytesize)
|
9
|
+
data_pointer.write_string(rbval)
|
10
|
+
memory[size_offset].write_uint32(rbval.size)
|
11
|
+
memory[data_offset].write_pointer(data_pointer)
|
12
|
+
end
|
13
|
+
|
14
|
+
def value(native: false)
|
15
|
+
data_pointer.read_string(size)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module CrystalRuby
|
2
|
+
module Types
|
3
|
+
class VariableWidth < FixedWidth
|
4
|
+
|
5
|
+
def self.size_offset
|
6
|
+
4
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.data_offset
|
10
|
+
8
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.memsize
|
14
|
+
8
|
15
|
+
end
|
16
|
+
|
17
|
+
def variable_width?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module CrystalRuby
|
2
|
+
module Types
|
3
|
+
# A variable with type operates much like a fixed width type, but
|
4
|
+
# it writes a size and a pointer to the type memory instead of the data itself.
|
5
|
+
# When we decrement our internal ref count we need to resolve the pointer.
|
6
|
+
# The layout is a tiny bit different (data begins at byte 8 to allow room for size uint32 at byte 4)
|
7
|
+
class VariableWidth < FixedWidth
|
8
|
+
def self.variable_width?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.crystal_supertype
|
13
|
+
"CrystalRuby::Types::VariableWidth"
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.build(
|
17
|
+
typename = nil,
|
18
|
+
error: nil,
|
19
|
+
inner_types: nil,
|
20
|
+
inner_keys: nil,
|
21
|
+
ffi_type: :pointer,
|
22
|
+
size_offset: 4,
|
23
|
+
data_offset: 8,
|
24
|
+
memsize: FFI.type_size(ffi_type),
|
25
|
+
refsize: 8,
|
26
|
+
convert_if: [],
|
27
|
+
superclass: VariableWidth,
|
28
|
+
&block
|
29
|
+
)
|
30
|
+
inner_types&.each(&Type.method(:validate!))
|
31
|
+
|
32
|
+
Class.new(superclass) do
|
33
|
+
bind_local_vars!(
|
34
|
+
%i[typename error inner_types inner_keys ffi_type memsize convert_if data_offset size_offset
|
35
|
+
refsize], binding
|
36
|
+
)
|
37
|
+
class_eval(&block) if block_given?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
require_relative "variable_width/string"
|
45
|
+
require_relative "variable_width/array"
|
46
|
+
require_relative "variable_width/hash"
|
data/lib/crystalruby/types.rb
CHANGED
@@ -1,18 +1,37 @@
|
|
1
|
-
require_relative "types/type"
|
2
|
-
require_relative "types/union_type"
|
3
|
-
require_relative "types/typedef"
|
4
|
-
require_relative "types/string"
|
5
|
-
require_relative "types/time"
|
6
|
-
require_relative "types/symbol"
|
7
|
-
require_relative "types/array"
|
8
|
-
require_relative "types/hash"
|
9
|
-
require_relative "types/nil"
|
10
|
-
require_relative "types/bool"
|
11
|
-
require_relative "types/named_tuple"
|
12
|
-
require_relative "types/tuple"
|
13
|
-
require_relative "types/numbers"
|
14
1
|
|
15
2
|
module CrystalRuby
|
16
3
|
module Types
|
4
|
+
# Store references to root types so that we can reference these in places where
|
5
|
+
# we load the CrystalRuby equivalents into the global namespace
|
6
|
+
module Root
|
7
|
+
Symbol = ::Symbol
|
8
|
+
String = ::String
|
9
|
+
Array = ::Array
|
10
|
+
Hash = ::Hash
|
11
|
+
Time = ::Time
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.const_missing(const_name)
|
15
|
+
return @fallback.const_get(const_name) if @fallback&.const_defined?(const_name)
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.method_missing(method_name, *args)
|
20
|
+
return @fallback.send(method_name, *args) if @fallback&.method_defined?(method_name)
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.with_binding_fallback(fallback)
|
25
|
+
@fallback, previous_fallback = fallback, @fallback
|
26
|
+
@fallback = @fallback.class unless @fallback.kind_of?(Module)
|
27
|
+
yield binding
|
28
|
+
ensure
|
29
|
+
@fallback = previous_fallback
|
30
|
+
end
|
17
31
|
end
|
18
32
|
end
|
33
|
+
require_relative "types/concerns/allocator"
|
34
|
+
require_relative "types/type"
|
35
|
+
require_relative "types/primitive"
|
36
|
+
require_relative "types/fixed_width"
|
37
|
+
require_relative "types/variable_width"
|
data/lib/crystalruby/version.rb
CHANGED
data/lib/crystalruby.rb
CHANGED
@@ -3,11 +3,12 @@
|
|
3
3
|
require "ffi"
|
4
4
|
require "digest"
|
5
5
|
require "fileutils"
|
6
|
-
require "
|
6
|
+
require "syntax_tree"
|
7
7
|
require "pathname"
|
8
8
|
|
9
9
|
require_relative "crystalruby/config"
|
10
10
|
require_relative "crystalruby/version"
|
11
|
+
require_relative "crystalruby/arc_mutex"
|
11
12
|
require_relative "crystalruby/typemaps"
|
12
13
|
require_relative "crystalruby/types"
|
13
14
|
require_relative "crystalruby/typebuilder"
|
@@ -17,7 +18,7 @@ require_relative "crystalruby/adapter"
|
|
17
18
|
require_relative "crystalruby/reactor"
|
18
19
|
require_relative "crystalruby/library"
|
19
20
|
require_relative "crystalruby/function"
|
20
|
-
require_relative "
|
21
|
+
require_relative "crystalruby/source_reader"
|
21
22
|
|
22
23
|
module CrystalRuby
|
23
24
|
module_function
|
@@ -37,19 +38,25 @@ module CrystalRuby
|
|
37
38
|
def check_crystal_ruby!
|
38
39
|
return if system("which crystal > /dev/null 2>&1")
|
39
40
|
|
40
|
-
|
41
|
-
"See https://crystal-lang.org/install
|
41
|
+
msg = "Crystal executable not found. Please ensure Crystal is installed and in your PATH. " \
|
42
|
+
"See https://crystal-lang.org/install/."
|
43
|
+
|
44
|
+
if config.crystal_missing_ignore
|
45
|
+
config.logger.error msg
|
46
|
+
else
|
47
|
+
raise msg
|
48
|
+
end
|
42
49
|
end
|
43
50
|
|
44
51
|
def check_config!
|
45
52
|
return if config.crystal_src_dir
|
46
53
|
|
47
|
-
raise "Missing config option `crystal_src_dir`. \nProvide this inside crystalruby.yaml "\
|
54
|
+
raise "Missing config option `crystal_src_dir`. \nProvide this inside crystalruby.yaml " \
|
48
55
|
"(run `bundle exec crystalruby init` to generate this file with detaults)"
|
49
56
|
end
|
50
57
|
|
51
58
|
%w[debug info warn error].each do |level|
|
52
|
-
define_method("log_#{level}") do |*msg|
|
59
|
+
define_method(:"log_#{level}") do |*msg|
|
53
60
|
prefix = config.colorize_log_output ? "\e[33mcrystalruby\e[0m\e[90m [#{Thread.current.object_id}]\e[0m" : "[crystalruby] #{Thread.current.object_id}"
|
54
61
|
|
55
62
|
config.logger.send(level, "#{prefix} #{msg.join(", ")}")
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crystalruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wouter Coppieters
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: digest
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: syntax_tree
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
@@ -87,35 +87,57 @@ files:
|
|
87
87
|
- exe/crystalruby
|
88
88
|
- lib/crystalruby.rb
|
89
89
|
- lib/crystalruby/adapter.rb
|
90
|
+
- lib/crystalruby/arc_mutex.rb
|
90
91
|
- lib/crystalruby/compilation.rb
|
91
92
|
- lib/crystalruby/config.rb
|
92
93
|
- lib/crystalruby/function.rb
|
93
94
|
- lib/crystalruby/library.rb
|
94
95
|
- lib/crystalruby/reactor.rb
|
96
|
+
- lib/crystalruby/source_reader.rb
|
95
97
|
- lib/crystalruby/template.rb
|
96
98
|
- lib/crystalruby/templates/function.cr
|
97
99
|
- lib/crystalruby/templates/index.cr
|
98
100
|
- lib/crystalruby/templates/inline_chunk.cr
|
101
|
+
- lib/crystalruby/templates/ruby_interface.cr
|
102
|
+
- lib/crystalruby/templates/top_level_function.cr
|
103
|
+
- lib/crystalruby/templates/top_level_ruby_interface.cr
|
99
104
|
- lib/crystalruby/typebuilder.rb
|
100
105
|
- lib/crystalruby/typemaps.rb
|
101
106
|
- lib/crystalruby/types.rb
|
102
|
-
- lib/crystalruby/types/
|
103
|
-
- lib/crystalruby/types/
|
104
|
-
- lib/crystalruby/types/
|
105
|
-
- lib/crystalruby/types/named_tuple.
|
106
|
-
- lib/crystalruby/types/
|
107
|
-
- lib/crystalruby/types/
|
108
|
-
- lib/crystalruby/types/
|
109
|
-
- lib/crystalruby/types/
|
110
|
-
- lib/crystalruby/types/
|
111
|
-
- lib/crystalruby/types/tuple.
|
107
|
+
- lib/crystalruby/types/concerns/allocator.rb
|
108
|
+
- lib/crystalruby/types/fixed_width.cr
|
109
|
+
- lib/crystalruby/types/fixed_width.rb
|
110
|
+
- lib/crystalruby/types/fixed_width/named_tuple.cr
|
111
|
+
- lib/crystalruby/types/fixed_width/named_tuple.rb
|
112
|
+
- lib/crystalruby/types/fixed_width/proc.cr
|
113
|
+
- lib/crystalruby/types/fixed_width/proc.rb
|
114
|
+
- lib/crystalruby/types/fixed_width/tagged_union.cr
|
115
|
+
- lib/crystalruby/types/fixed_width/tagged_union.rb
|
116
|
+
- lib/crystalruby/types/fixed_width/tuple.cr
|
117
|
+
- lib/crystalruby/types/fixed_width/tuple.rb
|
118
|
+
- lib/crystalruby/types/primitive.cr
|
119
|
+
- lib/crystalruby/types/primitive.rb
|
120
|
+
- lib/crystalruby/types/primitive_types/bool.cr
|
121
|
+
- lib/crystalruby/types/primitive_types/bool.rb
|
122
|
+
- lib/crystalruby/types/primitive_types/nil.cr
|
123
|
+
- lib/crystalruby/types/primitive_types/nil.rb
|
124
|
+
- lib/crystalruby/types/primitive_types/numbers.cr
|
125
|
+
- lib/crystalruby/types/primitive_types/numbers.rb
|
126
|
+
- lib/crystalruby/types/primitive_types/symbol.cr
|
127
|
+
- lib/crystalruby/types/primitive_types/symbol.rb
|
128
|
+
- lib/crystalruby/types/primitive_types/time.cr
|
129
|
+
- lib/crystalruby/types/primitive_types/time.rb
|
130
|
+
- lib/crystalruby/types/type.cr
|
112
131
|
- lib/crystalruby/types/type.rb
|
113
|
-
- lib/crystalruby/types/
|
114
|
-
- lib/crystalruby/types/
|
115
|
-
- lib/crystalruby/types/
|
116
|
-
- lib/crystalruby/types/
|
132
|
+
- lib/crystalruby/types/variable_width.cr
|
133
|
+
- lib/crystalruby/types/variable_width.rb
|
134
|
+
- lib/crystalruby/types/variable_width/array.cr
|
135
|
+
- lib/crystalruby/types/variable_width/array.rb
|
136
|
+
- lib/crystalruby/types/variable_width/hash.cr
|
137
|
+
- lib/crystalruby/types/variable_width/hash.rb
|
138
|
+
- lib/crystalruby/types/variable_width/string.cr
|
139
|
+
- lib/crystalruby/types/variable_width/string.rb
|
117
140
|
- lib/crystalruby/version.rb
|
118
|
-
- lib/module.rb
|
119
141
|
- logo.png
|
120
142
|
- sig/crystalruby.rbs
|
121
143
|
homepage: https://github.com/wouterken/crystalruby
|
@@ -140,7 +162,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
162
|
- !ruby/object:Gem::Version
|
141
163
|
version: '0'
|
142
164
|
requirements: []
|
143
|
-
rubygems_version: 3.
|
165
|
+
rubygems_version: 3.5.3
|
144
166
|
signing_key:
|
145
167
|
specification_version: 4
|
146
168
|
summary: Embed Crystal code directly in Ruby.
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module CrystalRuby::Types
|
4
|
-
Array = Type.new(
|
5
|
-
:Array,
|
6
|
-
error: "Array type must have a type parameter. E.g. Array(Float64)"
|
7
|
-
)
|
8
|
-
|
9
|
-
def self.Array(type)
|
10
|
-
Type.validate!(type)
|
11
|
-
Type.new("Array", inner_types: [type], accept_if: [::Array]) do |a|
|
12
|
-
a.map! { |v| type.interpret!(v) }
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module CrystalRuby::Types
|
4
|
-
Hash = Type.new(
|
5
|
-
:Hash,
|
6
|
-
error: "Hash type must have 2 type parameters. E.g. Hash(Float64, String)"
|
7
|
-
)
|
8
|
-
|
9
|
-
def self.Hash(key_type, value_type)
|
10
|
-
Type.validate!(key_type)
|
11
|
-
Type.validate!(value_type)
|
12
|
-
Type.new("Hash", inner_types: [key_type, value_type], accept_if: [::Hash]) do |h|
|
13
|
-
h.transform_keys! { |k| key_type.interpret!(k) }
|
14
|
-
h.transform_values! { |v| value_type.interpret!(v) }
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module CrystalRuby::Types
|
4
|
-
NamedTuple = Type.new(
|
5
|
-
:NamedTuple,
|
6
|
-
error: "NamedTuple type must contain one or more symbol -> type pairs. E.g. NamedTuple(hello: Int32, world: String)"
|
7
|
-
)
|
8
|
-
|
9
|
-
def self.NamedTuple(types_hash)
|
10
|
-
types_hash.keys.each do |key|
|
11
|
-
raise "NamedTuple keys must be symbols" unless key.is_a?(::Symbol) || key.respond_to?(:to_sym)
|
12
|
-
end
|
13
|
-
types_hash.values.each do |value_type|
|
14
|
-
Type.validate!(value_type)
|
15
|
-
end
|
16
|
-
keys = types_hash.keys.map(&:to_sym)
|
17
|
-
values = types_hash.values
|
18
|
-
Type.new("NamedTuple", inner_types: values, inner_keys: keys, accept_if: [::Hash]) do |h|
|
19
|
-
h.transform_keys! { |k| k.to_sym }
|
20
|
-
raise "Invalid keys for named tuple" unless h.keys.length == keys.length
|
21
|
-
raise "Invalid keys for named tuple" unless h.keys.all? { |k| keys.include?(k) }
|
22
|
-
|
23
|
-
h.each do |key, value|
|
24
|
-
h[key] = values[keys.index(key)].interpret!(value)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module CrystalRuby::Types
|
4
|
-
Tuple = Type.new(
|
5
|
-
:Tuple,
|
6
|
-
error: "Tuple type must contain one or more types E.g. Tuple(Int32, String)"
|
7
|
-
)
|
8
|
-
|
9
|
-
def self.Tuple(*types)
|
10
|
-
types.each do |value_type|
|
11
|
-
Type.validate!(value_type)
|
12
|
-
end
|
13
|
-
Type.new("Tuple", inner_types: types, accept_if: [::Array]) do |a|
|
14
|
-
a.map!.with_index { |v, i| inner_types[i].interpret!(v) }
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "json"
|
4
|
-
|
5
|
-
module CrystalRuby::Types
|
6
|
-
class TypeSerializer
|
7
|
-
class JSON < TypeSerializer
|
8
|
-
def lib_type
|
9
|
-
"UInt8*"
|
10
|
-
end
|
11
|
-
|
12
|
-
def crystal_type
|
13
|
-
type_expr
|
14
|
-
end
|
15
|
-
|
16
|
-
def error_value
|
17
|
-
'"{}".to_unsafe'
|
18
|
-
end
|
19
|
-
|
20
|
-
def ffi_type
|
21
|
-
:string
|
22
|
-
end
|
23
|
-
|
24
|
-
def prepare_argument(arg)
|
25
|
-
arg.to_json
|
26
|
-
end
|
27
|
-
|
28
|
-
def prepare_retval(retval)
|
29
|
-
@typedef.interpret!(::JSON.parse(retval))
|
30
|
-
end
|
31
|
-
|
32
|
-
def lib_to_crystal_type_expr(expr)
|
33
|
-
"(#{type_expr}).from_json(String.new(%s))" % expr
|
34
|
-
end
|
35
|
-
|
36
|
-
def crystal_to_lib_type_expr(expr)
|
37
|
-
"%s.to_json.to_unsafe" % expr
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
module CrystalRuby::Types
|
2
|
-
class TypeSerializer
|
3
|
-
include FFI::DataConverter
|
4
|
-
def self.for(format)
|
5
|
-
case format
|
6
|
-
when :json then JSON
|
7
|
-
else raise "Unknown type format: #{format}"
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
def error_value
|
12
|
-
0
|
13
|
-
end
|
14
|
-
|
15
|
-
def initialize(typedef)
|
16
|
-
@typedef = typedef
|
17
|
-
end
|
18
|
-
|
19
|
-
def type_expr
|
20
|
-
@typedef.type_expr
|
21
|
-
end
|
22
|
-
|
23
|
-
def type_defn
|
24
|
-
@typedef.type_defn
|
25
|
-
end
|
26
|
-
|
27
|
-
def anonymous?
|
28
|
-
@typedef.anonymous?
|
29
|
-
end
|
30
|
-
|
31
|
-
def name
|
32
|
-
@typedef.name
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
require_relative "type_serializer/json"
|