crystalruby 0.2.3 → 0.3.1

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2 -0
  3. data/Dockerfile +23 -2
  4. data/README.md +395 -198
  5. data/Rakefile +4 -3
  6. data/crystalruby.gemspec +2 -2
  7. data/examples/adder/adder.rb +1 -1
  8. data/exe/crystalruby +1 -0
  9. data/lib/crystalruby/adapter.rb +143 -73
  10. data/lib/crystalruby/arc_mutex.rb +47 -0
  11. data/lib/crystalruby/compilation.rb +32 -3
  12. data/lib/crystalruby/config.rb +41 -37
  13. data/lib/crystalruby/function.rb +216 -73
  14. data/lib/crystalruby/library.rb +157 -51
  15. data/lib/crystalruby/reactor.rb +63 -44
  16. data/lib/crystalruby/source_reader.rb +92 -0
  17. data/lib/crystalruby/template.rb +16 -5
  18. data/lib/crystalruby/templates/function.cr +11 -10
  19. data/lib/crystalruby/templates/index.cr +53 -66
  20. data/lib/crystalruby/templates/inline_chunk.cr +1 -1
  21. data/lib/crystalruby/templates/ruby_interface.cr +34 -0
  22. data/lib/crystalruby/templates/top_level_function.cr +62 -0
  23. data/lib/crystalruby/templates/top_level_ruby_interface.cr +33 -0
  24. data/lib/crystalruby/typebuilder.rb +11 -55
  25. data/lib/crystalruby/typemaps.rb +92 -67
  26. data/lib/crystalruby/types/concerns/allocator.rb +80 -0
  27. data/lib/crystalruby/types/fixed_width/named_tuple.cr +80 -0
  28. data/lib/crystalruby/types/fixed_width/named_tuple.rb +86 -0
  29. data/lib/crystalruby/types/fixed_width/proc.cr +45 -0
  30. data/lib/crystalruby/types/fixed_width/proc.rb +79 -0
  31. data/lib/crystalruby/types/fixed_width/tagged_union.cr +53 -0
  32. data/lib/crystalruby/types/fixed_width/tagged_union.rb +113 -0
  33. data/lib/crystalruby/types/fixed_width/tuple.cr +82 -0
  34. data/lib/crystalruby/types/fixed_width/tuple.rb +92 -0
  35. data/lib/crystalruby/types/fixed_width.cr +138 -0
  36. data/lib/crystalruby/types/fixed_width.rb +205 -0
  37. data/lib/crystalruby/types/primitive.cr +21 -0
  38. data/lib/crystalruby/types/primitive.rb +117 -0
  39. data/lib/crystalruby/types/primitive_types/bool.cr +34 -0
  40. data/lib/crystalruby/types/primitive_types/bool.rb +11 -0
  41. data/lib/crystalruby/types/primitive_types/nil.cr +35 -0
  42. data/lib/crystalruby/types/primitive_types/nil.rb +16 -0
  43. data/lib/crystalruby/types/primitive_types/numbers.cr +37 -0
  44. data/lib/crystalruby/types/primitive_types/numbers.rb +28 -0
  45. data/lib/crystalruby/types/primitive_types/symbol.cr +55 -0
  46. data/lib/crystalruby/types/primitive_types/symbol.rb +35 -0
  47. data/lib/crystalruby/types/primitive_types/time.cr +35 -0
  48. data/lib/crystalruby/types/primitive_types/time.rb +25 -0
  49. data/lib/crystalruby/types/type.cr +64 -0
  50. data/lib/crystalruby/types/type.rb +249 -30
  51. data/lib/crystalruby/types/variable_width/array.cr +74 -0
  52. data/lib/crystalruby/types/variable_width/array.rb +88 -0
  53. data/lib/crystalruby/types/variable_width/hash.cr +146 -0
  54. data/lib/crystalruby/types/variable_width/hash.rb +117 -0
  55. data/lib/crystalruby/types/variable_width/string.cr +36 -0
  56. data/lib/crystalruby/types/variable_width/string.rb +18 -0
  57. data/lib/crystalruby/types/variable_width.cr +23 -0
  58. data/lib/crystalruby/types/variable_width.rb +46 -0
  59. data/lib/crystalruby/types.rb +32 -13
  60. data/lib/crystalruby/version.rb +2 -2
  61. data/lib/crystalruby.rb +13 -6
  62. metadata +42 -22
  63. data/lib/crystalruby/types/array.rb +0 -15
  64. data/lib/crystalruby/types/bool.rb +0 -3
  65. data/lib/crystalruby/types/hash.rb +0 -17
  66. data/lib/crystalruby/types/named_tuple.rb +0 -28
  67. data/lib/crystalruby/types/nil.rb +0 -3
  68. data/lib/crystalruby/types/numbers.rb +0 -5
  69. data/lib/crystalruby/types/string.rb +0 -3
  70. data/lib/crystalruby/types/symbol.rb +0 -3
  71. data/lib/crystalruby/types/time.rb +0 -8
  72. data/lib/crystalruby/types/tuple.rb +0 -17
  73. data/lib/crystalruby/types/type_serializer/json.rb +0 -41
  74. data/lib/crystalruby/types/type_serializer.rb +0 -37
  75. data/lib/crystalruby/types/typedef.rb +0 -57
  76. data/lib/crystalruby/types/union_type.rb +0 -43
  77. data/lib/module.rb +0 -3
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CrystalRuby::Types
4
+ Array = VariableWidth.build(error: "Array type must have a type parameter. E.g. Array(Float64)")
5
+
6
+ # An array-like, reference counted manually managed memory type.
7
+ # Shareable between Crystal and Crystal.
8
+ def self.Array(type)
9
+ VariableWidth.build(:Array, inner_types: [type], convert_if: [Array, Root::Array], superclass: Array) do
10
+ include Enumerable
11
+
12
+ # Implement the Enumerable interface
13
+ # Helps this object to act like an Array
14
+ def each
15
+ size.times { |i| yield self[i] }
16
+ end
17
+
18
+ # We only accept Array-like values, from which all elements
19
+ # can successfully be cast to our inner type
20
+ def self.cast!(value)
21
+ unless value.is_a?(Array) || value.is_a?(Root::Array) && value.all?(&inner_type.method(:valid_cast?))
22
+ raise CrystalRuby::InvalidCastError, "Cannot cast #{value} to #{inspect}"
23
+ end
24
+
25
+ if inner_type.primitive?
26
+ value.map(&inner_type.method(:to_ffi_repr))
27
+ else
28
+ value
29
+ end
30
+ end
31
+
32
+ def self.copy_to!(rbval, memory:)
33
+ data_pointer = malloc(rbval.size * inner_type.refsize)
34
+
35
+ memory[size_offset].write_uint32(rbval.size)
36
+ memory[data_offset].write_pointer(data_pointer)
37
+
38
+ if inner_type.primitive?
39
+ data_pointer.send("put_array_of_#{inner_type.ffi_type}", 0, rbval)
40
+ else
41
+ rbval.each_with_index do |val, i|
42
+ inner_type.write_single(data_pointer[i * refsize], val)
43
+ end
44
+ end
45
+ end
46
+
47
+ def self.each_child_address(pointer)
48
+ size = pointer[size_offset].get_int32(0)
49
+ pointer = pointer[data_offset].read_pointer
50
+ size.times do |i|
51
+ yield inner_type, pointer[i * inner_type.refsize]
52
+ end
53
+ end
54
+
55
+ def checked_offset!(index, size)
56
+ raise "Index out of bounds: #{index} >= #{size}" if index >= size
57
+
58
+ if index < 0
59
+ raise "Index out of bounds: #{index} < -#{size}" if index < -size
60
+
61
+ index += size
62
+ end
63
+ index
64
+ end
65
+
66
+ # Return the element at the given index.
67
+ # This will automatically increment
68
+ # the reference count if not a primitive type.
69
+ def [](index)
70
+ inner_type.fetch_single(data_pointer[checked_offset!(index, size) * inner_type.refsize])
71
+ end
72
+
73
+ # Overwrite the element at the given index
74
+ # The replaced element will have
75
+ # its reference count decremented.
76
+ def []=(index, value)
77
+ inner_type.write_single(data_pointer[checked_offset!(index, size) * inner_type.refsize], value)
78
+ end
79
+
80
+ # Load values stored inside array type.
81
+ # If it's a primitive type, we can quickly bulk load the values.
82
+ # Otherwise we need toinstantiate new ref-checked instances.
83
+ def value(native: false)
84
+ inner_type.fetch_multi(data_pointer, size, native: native)
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,146 @@
1
+ class <%= base_crystal_class_name %> < CrystalRuby::Types::VariableWidth
2
+
3
+ def initialize(hash : Hash(<%= key_type.native_type_expr %>, <%= value_type.native_type_expr %>))
4
+ @memory = malloc(data_offset + 8)
5
+ self.value = hash
6
+ increment_ref_count!
7
+ end
8
+
9
+ def value=(hash : Hash(<%= key_type.native_type_expr %>, <%= value_type.native_type_expr %>))
10
+ if self.ref_count > 0
11
+ self.class.decr_inner_ref_counts!(memory)
12
+ end
13
+ self.class.copy_to!(hash, self.memory)
14
+ end
15
+
16
+ def ==(other : <%= native_type_expr %>)
17
+ native == other
18
+ end
19
+
20
+ def self.copy_to!(hash : Hash(<%= key_type.native_type_expr %>, <%= value_type.native_type_expr %>), memory : Pointer(::UInt8))
21
+ data_pointer = malloc(hash.size * (keysize + valsize)).as(Pointer(::UInt8))
22
+
23
+ hash.keys.each_with_index do |key, i|
24
+ <%= key_type.crystal_class_name %>.write_single(data_pointer + i * keysize, key)
25
+ end
26
+
27
+ hash.values.each_with_index do |value, i|
28
+ <%= value_type.crystal_class_name %>.write_single(data_pointer + hash.size * keysize + i * valsize, value)
29
+ end
30
+
31
+ (memory+size_offset).as(Pointer(::UInt32)).value = hash.size.to_u32
32
+ (memory+data_offset).as(Pointer(::UInt64)).value = data_pointer.address
33
+ end
34
+
35
+ def value
36
+ ::Hash.zip(keys, values)
37
+ end
38
+
39
+ def native : ::Hash(<%= key_type.native_type_expr %>, <%= value_type.native_type_expr %>)
40
+ ::Hash.zip(keys_native, values_native)
41
+ end
42
+
43
+ include Enumerable(::Tuple(<%= key_type.native_type_expr %>, <%= value_type.native_type_expr %>))
44
+
45
+ def each
46
+ size.times do |i|
47
+ yield({keys_native[i], values_native[i]})
48
+ end
49
+ end
50
+
51
+ def size
52
+ (memory+size_offset).as(Pointer(::UInt32)).value.to_i
53
+ end
54
+
55
+ def self.keysize
56
+ <%= key_type.refsize %>
57
+ end
58
+
59
+ def keysize
60
+ <%= key_type.refsize %>
61
+ end
62
+
63
+ def self.valsize
64
+ <%= value_type.refsize %>
65
+ end
66
+
67
+ def valsize
68
+ <%= value_type.refsize %>
69
+ end
70
+
71
+ def []=(key : <%= key_type.native_type_expr %>, value : <%= value_type.native_type_expr %>)
72
+ index = index_of(key)
73
+ if index
74
+ <%= value_type.crystal_class_name %>.write_single(data_pointer + size * keysize + index * valsize, value)
75
+ else
76
+ self.value = self.native.merge({key => value})
77
+ end
78
+ end
79
+
80
+ def key_ptr : Pointer(<%= !key_type.numeric? ? "UInt64" : key_type.native_type_expr %>)
81
+ data_pointer.as(Pointer(<%= !key_type.numeric? ? "UInt8" : key_type.native_type_expr %>))
82
+ end
83
+
84
+ def value_ptr : Pointer(<%= !value_type.numeric? ? "UInt64" : value_type.native_type_expr %>)
85
+ (data_pointer + size * keysize).as(Pointer(<%= !value_type.numeric? ? "UInt8" : value_type.native_type_expr %>))
86
+ end
87
+
88
+ def []?(key : <%= key_type.native_type_expr %>)
89
+ index = index_of(key)
90
+ if index
91
+ values[index]
92
+ else
93
+ nil
94
+ end
95
+ end
96
+
97
+ def [](key : <%= key_type.native_type_expr %>)
98
+ index = index_of(key)
99
+ if index
100
+ values[index]
101
+ else
102
+ raise "Key not found"
103
+ end
104
+ end
105
+
106
+
107
+ def data_pointer
108
+ Pointer(::UInt8).new((@memory + data_offset).as(::Pointer(UInt64)).value)
109
+ end
110
+
111
+ def keys
112
+ keys = [] of <%= key_type.numeric? ? key_type.native_type_expr : key_type.crystal_class_name %>
113
+ size.times do |i|
114
+ keys << <%= !key_type.numeric? ? "#{key_type.crystal_class_name}.fetch_single(data_pointer + i * keysize)" : "key_ptr[i]" %>
115
+ end
116
+ keys
117
+ end
118
+
119
+ def values
120
+ values = [] of <%= value_type.numeric? ? value_type.native_type_expr : value_type.crystal_class_name %>
121
+ size.times do |i|
122
+ values << <%= !value_type.numeric? ? "#{value_type.crystal_class_name}.fetch_single(data_pointer + size * keysize + i * valsize)" : "value_ptr[i]" %>
123
+ end
124
+ values
125
+ end
126
+
127
+ def keys_native
128
+ keys = [] of <%= key_type.native_type_expr %>
129
+ size.times do |i|
130
+ keys << <%= !key_type.numeric? ? "#{key_type.crystal_class_name}.fetch_single(data_pointer + i * keysize).native" : "key_ptr[i]" %>.as(<%= key_type.native_type_expr %>)
131
+ end
132
+ keys
133
+ end
134
+
135
+ def values_native
136
+ values = [] of <%= value_type.native_type_expr %>
137
+ size.times do |i|
138
+ values << <%= !value_type.numeric? ? "#{value_type.crystal_class_name}.fetch_single(data_pointer + size * keysize + i * valsize).native" : "value_ptr[i]" %>.as(<%= value_type.native_type_expr %>)
139
+ end
140
+ values
141
+ end
142
+
143
+ def index_of(key : <%= key_type.native_type_expr %>)
144
+ keys.index(key)
145
+ end
146
+ end
@@ -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"
@@ -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"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Crystalruby
4
- VERSION = "0.2.3"
3
+ module CrystalRuby
4
+ VERSION = "0.3.1"
5
5
  end
data/lib/crystalruby.rb CHANGED
@@ -3,11 +3,12 @@
3
3
  require "ffi"
4
4
  require "digest"
5
5
  require "fileutils"
6
- require "method_source"
6
+ require "prism"
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 "module"
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
- raise "Crystal executable not found. Please ensure Crystal is installed and in your PATH." \
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(", ")}")