crystalruby 0.2.3 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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(", ")}")