julia 0.2.0 → 0.3.0.dev

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 761658bd92a75b136265135887ffe7ca82a3c42d7e5d15ea5f6f9d8212d23ec1
4
- data.tar.gz: 0052f5ad9249ff2063eceae0919573fea27039611824cad251b5aa63bdef57e1
3
+ metadata.gz: b6c14a8233ff0a3579610180d5696f5f7647a05a821103e90d2f29c38e5cc5c4
4
+ data.tar.gz: 2d8acdb2742ec06e627b2b0f1614aec7597a274380221dcc4973ed14c959a7c8
5
5
  SHA512:
6
- metadata.gz: d6cf4724a9648c91ec03ed60fc1e9f3a337adc11ba1320ac74fedb7a0b6d12bde7fe1f050e9ca4e1d594caf45991977ee8f68ed6620d5beeb9fae79f6ca04c5b
7
- data.tar.gz: 01d84c23f8c58efa7bd41a241389195e50a6842a6bd0ba0ae7fae77abb5b04bcb135d022b8cfe6a6372b5d4bcfbf18c8a3dd0b4f13f385057e898667c014b120
6
+ metadata.gz: 154d08d7ff8c9f75689034a0d0996a499daf1081d1d35e806d730faba824512e2fcbaee056d104676b1cbd3e590e2dd91dd34c2ef56164bef330928f9ea6fdb7
7
+ data.tar.gz: 010f472ce30703557beb5035d611c1a81b083d995680a8438c882c92beed3b9ea24bc1c58d3de7a67442c1d44df004cd4095b492bee262b32cffaf29dc172f67
@@ -1,4 +1,13 @@
1
+ dist: xenial
1
2
  language: ruby
2
3
  rvm:
3
- - 2.2.2
4
- before_install: gem install bundler -v 1.10.3
4
+ - ruby-head
5
+ - 2.6
6
+ - 2.5
7
+ - 2.4
8
+ - 2.3
9
+ before_install:
10
+ - wget -O /tmp/julia.tar.gz https://julialang-s3.julialang.org/bin/linux/x64/1.1/julia-1.1.0-linux-x86_64.tar.gz
11
+ - sudo mkdir /usr/local/julia
12
+ - sudo tar xf /tmp/julia.tar.gz -C /usr/local/julia --strip-components=1
13
+ - export PATH="/usr/local/julia/bin:$PATH"
data/README.md CHANGED
@@ -12,9 +12,8 @@ Julia on Ruby.
12
12
 
13
13
  ### Julia
14
14
 
15
+ - 1.1
15
16
  - 1.0
16
- - 0.7
17
- - 0.6
18
17
 
19
18
  ## Installation
20
19
 
@@ -0,0 +1,191 @@
1
+ __precompile__()
2
+
3
+ module RbCall
4
+
5
+ export _refcnt, _incref, _decref, gc_guard_references
6
+
7
+ #########################################################################
8
+ # prepare
9
+
10
+ import Libdl
11
+
12
+ struct Dl_info
13
+ dli_fname::Ptr{UInt8}
14
+ dli_fbase::Ptr{Cvoid}
15
+ dli_sname::Ptr{UInt8}
16
+ dli_saddr::Ptr{Cvoid}
17
+ end
18
+
19
+ hassym(lib, sym) = Libdl.dlsym_e(lib, sym) != C_NULL
20
+
21
+ proc_handle = unsafe_load(cglobal(:jl_exe_handle, Ptr{Cvoid}))
22
+
23
+ symbols_present = false
24
+ @static if Sys.iswindows()
25
+ # TODO support windows
26
+ else
27
+ global symbols_present = hassym(proc_handle, :rb_define_class)
28
+ end
29
+
30
+ if !symbols_present
31
+ # TODO load libruby dynamically
32
+ else
33
+ @static if Sys.iswindows()
34
+ # TODO support windows
35
+ else
36
+ libruby_handle = proc_handle
37
+ # Now determine the name of the ruby library that these symbols are from
38
+ some_address_in_libruby = Libdl.dlsym(libruby_handle, :rb_define_class)
39
+ some_address_in_main_exe = Libdl.dlsym_e(proc_handle, Sys.isapple() ? :_mh_execute_header : :main)
40
+ if some_address_in_main_exe == nothing
41
+ # NOTE: we cannot get main symbol from ruby executable in travis-ci
42
+ some_address_in_main_exe = Libdl.dlsym_e(proc_handle, :_start)
43
+ end
44
+ dlinfo1 = Ref{Dl_info}()
45
+ dlinfo2 = Ref{Dl_info}()
46
+ ccall(:dladdr, Cint, (Ptr{Cvoid}, Ptr{Dl_info}), some_address_in_libruby, dlinfo1)
47
+ ccall(:dladdr, Cint, (Ptr{Cvoid}, Ptr{Dl_info}), some_address_in_main_exe, dlinfo2)
48
+ if dlinfo1[].dli_fbase == dlinfo2[].dli_fbase
49
+ const libruby = nothing
50
+ else
51
+ const libruby = unsafe_string(dlinfo1[].dli_fname)
52
+ end
53
+ end
54
+ end
55
+
56
+ #########################################################################
57
+ # basic types
58
+
59
+ @static if sizeof(Clong) == sizeof(Ptr{Cvoid})
60
+ const VALUE = Culong
61
+ const SVALUE = Clong
62
+ const ID = Culong
63
+ const Cintptr_t = Clong
64
+ const Cuintptr_t = Culong
65
+ elseif sizeof(Clonglong) == sizeof(Ptr{Cvoid})
66
+ const VALUE = Culonglong
67
+ const SVALUE = Clonglong
68
+ const ID = Culonglong
69
+ const Cintptr_t = Clonglong
70
+ const Cuintptr_t = Culonglong
71
+ else
72
+ error("ruby requires sizeof(Ptr{Cvoid}) == sizeof(Clong) or sizeof(Clonglong) to be compiled.")
73
+ end
74
+
75
+ struct RBasic_struct
76
+ flags::VALUE
77
+ klass::VALUE
78
+ end
79
+
80
+ struct RVALUE_struct
81
+ basic::RBasic_struct
82
+ v1::VALUE
83
+ v2::VALUE
84
+ v3::VALUE
85
+ end
86
+
87
+ const RbPtr = Ptr{RVALUE_struct}
88
+
89
+ #########################################################################
90
+ # basic constants
91
+
92
+ const RUBY_FIXNUM_MAX = typemax(Clong) >> 1
93
+ const RUBY_FIXNUM_MIN = typemin(Clong) >> 1
94
+
95
+ @static if sizeof(VALUE) >= sizeof(Cdouble)
96
+ const RUBY_USE_FLONUM = true
97
+ else
98
+ const RUBY_USE_FLONUM = false
99
+ error("currently RbCall.jl only supports Ruby with flonum.")
100
+ end
101
+
102
+ @static if RUBY_USE_FLONUM
103
+ const RUBY_Qfalse = 0x00
104
+ const RUBY_Qtrue = 0x14
105
+ const RUBY_Qnil = 0x08
106
+ const RUBY_Qundef = 0x34
107
+ const RUBY_IMMEDIATE_MASK = 0x07
108
+ const RUBY_FIXNUM_FLAG = 0x01
109
+ const RUBY_FLONUM_MASK = 0x03
110
+ const RUBY_FLONUM_FLAG = 0x02
111
+ const RUBY_SYMBOL_FLAG = 0x0c
112
+ else
113
+ const RUBY_Qfalse = 0
114
+ const RUBY_Qtrue = 2
115
+ const RUBY_Qnil = 4
116
+ const RUBY_Qundef = 6
117
+ const RUBY_IMMEDIATE_MASK = 0x03
118
+ const RUBY_FIXNUM_FLAG = 0x01
119
+ const RUBY_FLONUM_MASK = 0x00
120
+ const RUBY_FLONUM_FLAG = 0x02
121
+ const RUBY_SYMBOL_FLAG = 0x0e
122
+ end
123
+ const RUBY_SPECIAL_SHIFT = 8
124
+
125
+ #########################################################################
126
+ # basic utilities
127
+
128
+ RB_FIXNUM_P(v::VALUE) = (x & RUBY_FIXNUM_FLAG) != 0
129
+ RB_POSFIXABLE(x::Integer) = x <= RUBY_FIXNUM_MAX
130
+ RB_NEGFIXABLE(x::Integer) = x >= RUBY_FIXNUM_MIN
131
+ RB_FIXABLE(x::Integer) = RB_POSFIXABLE(x) && RB_NEGFIXABLE(x)
132
+
133
+ RB_INT2FIX(i::Integer) = (VALUE(i) << 1) | RUBY_FIXNUM_FLAG
134
+ RB_LONG2FIX(i::Clong) = RB_INT2FIX(i)
135
+
136
+ function RB_LONG2NUM(i::Clong)
137
+ if RB_FIXABLE(i)
138
+ return RB_LONG2FIX(i)
139
+ else
140
+ return ccall(:rb_int2big, VALUE, (Cintptr_t,), Cintptr_t(i))
141
+ end
142
+ end
143
+
144
+ function RB_ULONG2NUM(i::Culong)
145
+ if RB_POSFIXABLE(i)
146
+ return RB_LONG2FIX(Clong(i))
147
+ else
148
+ return ccall(:rb_uint2big, VALUE, (Cuintptr_t,), Cuintptr_t(i))
149
+ end
150
+ end
151
+
152
+ RB_LL2NUM(i::Clonglong) = ccall(:rb_ll2inum, VALUE, (Clonglong,), i)
153
+ RB_ULL2NUM(i::Culonglong) = ccall(:rb_ull2inum, VALUE, (Culonglong,), i)
154
+
155
+ DBL2NUM(d::Cdouble) = ccall(:rb_float_new, VALUE, (Cdouble,), d)
156
+
157
+ HAVE_RB_DBL_COMPLEX_NEW = hassym(libruby_handle, :rb_dbl_complex_new)
158
+
159
+ #########################################################################
160
+ # conversion
161
+
162
+ include("conversion.jl")
163
+
164
+ #########################################################################
165
+ # gc
166
+
167
+ const gc_guard_references = Dict{Any,Clong}()
168
+
169
+ function _refcnt(value::Any)
170
+ return get(gc_guard_references, value , 0)
171
+ end
172
+
173
+ function _incref(value::Any)
174
+ gc_guard_references[value] = _refcnt(value) + 1
175
+ return value
176
+ end
177
+
178
+ function _decref(value::Any)
179
+ if haskey(gc_guard_references, value)
180
+ new_count = _refcnt(value) - 1
181
+ if new_count == 0
182
+ delete!(gc_guard_references, value)
183
+ else
184
+ gc_guard_references[value] = new_count
185
+ end
186
+ end
187
+ end
188
+
189
+ #########################################################################
190
+
191
+ end # module RbCall
@@ -0,0 +1,56 @@
1
+ convert(::Type{VALUE}, ::Nothing) = RUBY_Qnil
2
+
3
+ convert(::Type{VALUE}, b::Bool) = b ? RUBY_Qtrue : RUBY_Qfalse
4
+
5
+ convert(::Type{VALUE}, i::Int8) = RB_INT2FIX(Cint(i))
6
+ convert(::Type{VALUE}, i::UInt8) = RB_INT2FIX(Cint(i))
7
+ convert(::Type{VALUE}, i::Int16) = RB_INT2FIX(Cint(i))
8
+ convert(::Type{VALUE}, i::UInt16) = RB_INT2FIX(Cint(i))
9
+ convert(::Type{VALUE}, i::Int32) = RB_LONG2NUM(Clong(i))
10
+ convert(::Type{VALUE}, i::UInt32) = RB_ULONG2NUM(Culong(i))
11
+
12
+ if sizeof(Clong) == sizeof(Int64)
13
+ convert(::Type{VALUE}, i::Int64) = RB_LONG2NUM(Clong(i))
14
+ convert(::Type{VALUE}, i::UInt64) = RB_ULONG2NUM(Culong(i))
15
+ else
16
+ convert(::Type{VALUE}, i::Int64) = RB_LL2NUM(Clonglong(i))
17
+ convert(::Type{VALUE}, i::UInt64) = RB_ULL2NUM(Culonglong(i))
18
+ end
19
+
20
+ if sizeof(Clonglong) == sizeof(Int128)
21
+ convert(::Type{VALUE}, i::Int128) = RB_LL2NUM(Clonglong(i))
22
+ convert(::Type{VALUE}, i::UInt128) = RB_ULL2NUM(Culonglong(i))
23
+ end
24
+
25
+ function convert(::Type{VALUE}, i::Integer)
26
+ # TODO convert to Bignum
27
+ return RUBY_Qnil
28
+ end
29
+
30
+ convert(::Type{VALUE}, d::Union{Float64,Float32}) = DBL2NUM(Cdouble(d))
31
+
32
+ if HAVE_RB_DBL_COMPLEX_NEW
33
+ function convert(::Type{VALUE}, c::Union{ComplexF64,ComplexF32})
34
+ c64 = ComplexF64(c)
35
+ return ccall(:rb_dbl_complex_new, VALUE, (Cdouble, Cdouble), real(c64), imag(c64))
36
+ end
37
+ else
38
+ function convert(::Type{VALUE}, c::Union{ComplexF64,ComplexF32})
39
+ c64 = ComplexF64(c)
40
+ return ccall(:rb_complex_new, VALUE, (VALUE, VALUE),
41
+ convert(VALUE, real(c64)), convert(VALUE, imag(c64)))
42
+ end
43
+ end
44
+
45
+ function convert(::Type{VALUE}, s::AbstractString)
46
+ sb = String(s)
47
+ return ccall(:rb_utf8_str_new, VALUE, (Cstring, Clong), sb, sizeof(sb))
48
+ end
49
+
50
+ # TODO
51
+ convert(::Type{VALUE}, ::Any) = RUBY_Qnil
52
+
53
+ function convert_to_ruby(value::Any)
54
+ rbobj = convert(VALUE, value)
55
+ return rbobj
56
+ end
@@ -1,6 +1,27 @@
1
1
  #include "julia_internal.h"
2
2
 
3
- VALUE julia_mJulia;
3
+ VALUE rbjl_mJulia;
4
+
5
+ void
6
+ rbjl_check_julia_exception(const char *message)
7
+ {
8
+ jl_function_t *sprint;
9
+ jl_function_t *showerror;
10
+
11
+ jl_value_t *error = JULIA_API(jl_exception_occurred)();
12
+ if (!error) return;
13
+
14
+ JULIA_API(jl_exception_clear)();
15
+
16
+ sprint = (jl_function_t *)JULIA_API(jl_eval_string)("sprint");
17
+ showerror = (jl_function_t *)JULIA_API(jl_eval_string)("showerror");
18
+
19
+ jl_value_t *res = JULIA_API(jl_call2)(sprint, showerror, error);
20
+ if (res && jl_is_string(res)) {
21
+ const char * c_str = JULIA_API(jl_string_ptr)(res);
22
+ rb_raise(rb_eRuntimeError, "JuliaError: %s (%s)", c_str, message);
23
+ }
24
+ }
4
25
 
5
26
  static void
6
27
  init_julia(void)
@@ -11,9 +32,12 @@ init_julia(void)
11
32
  void
12
33
  Init_julia(void)
13
34
  {
14
- julia_mJulia = rb_define_module("Julia");
35
+ rbjl_mJulia = rb_define_module("Julia");
15
36
 
16
- julia_init_libjulia();
37
+ rbjl_init_libjulia();
17
38
 
18
39
  init_julia();
40
+
41
+ rbjl_init_rbcall();
42
+ rbjl_init_value_ptr();
19
43
  }
@@ -21,9 +21,34 @@ extern "C" {
21
21
  # error ---->> ruby requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<----
22
22
  #endif
23
23
 
24
+ /* from src/support/htable.h */
25
+
26
+ #define HT_N_INLINE 32
27
+
28
+ typedef struct {
29
+ size_t size;
30
+ void **table;
31
+ void *_space[HT_N_INLINE];
32
+ } htable_t;
33
+
34
+ /* from src/support/arraylist.h */
35
+
36
+ #define AL_N_INLINE 29
37
+
38
+ typedef struct {
39
+ size_t len;
40
+ size_t max;
41
+ void **items;
42
+ void *_space[AL_N_INLINE];
43
+ } arraylist_t;
44
+
45
+ /* from src/julia.h */
46
+
24
47
  typedef struct _jl_value_t jl_value_t;
25
48
  typedef struct _jl_taggedvalue_t jl_taggedvalue_t;
26
49
 
50
+ typedef jl_value_t jl_function_t;
51
+
27
52
  typedef struct _jl_sym_t {
28
53
  JL_DATA_TYPE
29
54
  struct _jl_sym_t *left;
@@ -80,25 +105,55 @@ typedef struct _jl_datatype_t {
80
105
  void *ditype;
81
106
  } jl_datatype_t;
82
107
 
83
- struct julia_api_table {
108
+ typedef struct {
109
+ uint64_t hi;
110
+ uint64_t lo;
111
+ } jl_uuid_t;
112
+
113
+ typedef struct _jl_module_t {
114
+ JL_DATA_TYPE
115
+ jl_sym_t *name;
116
+ struct _jl_module_t *parent;
117
+ htable_t bindings;
118
+ arraylist_t usings; // modules with all bindings potentially imported
119
+ uint64_t build_id;
120
+ jl_uuid_t uuid;
121
+ size_t primary_world;
122
+ uint32_t counter;
123
+ int32_t nospecialize; // global bit flags: initialization for new methods
124
+ uint8_t istopmod;
125
+ } jl_module_t;
126
+
127
+ struct rbjl_api_table {
84
128
  int (* jl_is_initialized)(void);
85
129
  void (* jl_init)(void);
86
130
  char const * (* jl_ver_string)(void);
87
- jl_datatype_t *jl_bool_type;
88
- jl_datatype_t *jl_char_type;
89
- jl_datatype_t *jl_string_type;
90
- jl_datatype_t *jl_int8_type;
91
- jl_datatype_t *jl_uint8_type;
92
- jl_datatype_t *jl_int16_type;
93
- jl_datatype_t *jl_uint16_type;
94
- jl_datatype_t *jl_int32_type;
95
- jl_datatype_t *jl_uint32_type;
96
- jl_datatype_t *jl_int64_type;
97
- jl_datatype_t *jl_uint64_type;
98
- jl_datatype_t *jl_float16_type;
99
- jl_datatype_t *jl_float32_type;
100
- jl_datatype_t *jl_float64_type;
131
+ jl_datatype_t **jl_bool_type;
132
+ jl_datatype_t **jl_char_type;
133
+ jl_datatype_t **jl_string_type;
134
+ jl_datatype_t **jl_int8_type;
135
+ jl_datatype_t **jl_uint8_type;
136
+ jl_datatype_t **jl_int16_type;
137
+ jl_datatype_t **jl_uint16_type;
138
+ jl_datatype_t **jl_int32_type;
139
+ jl_datatype_t **jl_uint32_type;
140
+ jl_datatype_t **jl_int64_type;
141
+ jl_datatype_t **jl_uint64_type;
142
+ jl_datatype_t **jl_float16_type;
143
+ jl_datatype_t **jl_float32_type;
144
+ jl_datatype_t **jl_float64_type;
145
+ jl_datatype_t **jl_module_type;
146
+
147
+ jl_module_t **jl_main_module;
148
+ jl_module_t **jl_base_module;
149
+
150
+ jl_value_t * (* jl_call1)(jl_function_t *f, jl_value_t *a);
151
+ jl_value_t * (* jl_call2)(jl_function_t *f, jl_value_t *a, jl_value_t *b);
152
+ jl_value_t * (* jl_exception_occurred)(void);
153
+ void (* jl_exception_clear)(void);
101
154
  jl_value_t * (* jl_eval_string)(const char *str);
155
+ jl_value_t * (* jl_get_global)(jl_module_t *m, jl_sym_t *var);
156
+ jl_sym_t * (* jl_symbol)(const char *str);
102
157
  jl_value_t * (* jl_typeof)(jl_value_t *v);
103
158
  const char * (* jl_typeof_str)(jl_value_t *v);
104
159
  const char * (* jl_string_ptr)(jl_value_t *s);
@@ -113,13 +168,70 @@ struct julia_api_table {
113
168
  uint64_t (* jl_unbox_uint64)(jl_value_t *v);
114
169
  float (* jl_unbox_float32)(jl_value_t *v);
115
170
  double (* jl_unbox_float64)(jl_value_t *v);
171
+ void * (* jl_unbox_voidpointer)(jl_value_t *v);
116
172
  };
117
173
 
118
- struct julia_api_table *julia_get_api_table(void);
119
- #define JULIA_API(name) (julia_get_api_table()->name)
174
+ struct rbjl_api_table *rbjl_get_api_table(void);
175
+ #define JULIA_API(name) (rbjl_get_api_table()->name)
176
+
177
+ #define jl_typeis(v,t) (JULIA_API(jl_typeof)(v)==(jl_value_t*)(t))
178
+
179
+ // basic predicates -----------------------------------------------------------
180
+ #define jl_is_nothing(v) (((jl_value_t*)(v)) == ((jl_value_t*)jl_nothing))
181
+ #define jl_is_tuple(v) (((jl_datatype_t*)JULIA_API(jl_typeof)(v))->name == *JULIA_API(jl_tuple_typename))
182
+ #define jl_is_svec(v) jl_typeis(v,*JULIA_API(jl_simplevector_type))
183
+ #define jl_is_simplevector(v) jl_is_svec(v)
184
+ #define jl_is_datatype(v) jl_typeis(v,*JULIA_API(jl_datatype_type))
185
+ #define jl_is_mutable(t) (((jl_datatype_t*)t)->mutabl)
186
+ #define jl_is_mutable_datatype(t) (jl_is_datatype(t) && (((jl_datatype_t*)t)->mutabl))
187
+ #define jl_is_immutable(t) (!((jl_datatype_t*)t)->mutabl)
188
+ #define jl_is_immutable_datatype(t) (jl_is_datatype(t) && (!((jl_datatype_t*)t)->mutabl))
189
+ #define jl_is_uniontype(v) jl_typeis(v,*JULIA_API(jl_uniontype_type))
190
+ #define jl_is_typevar(v) jl_typeis(v,*JULIA_API(jl_tvar_type))
191
+ #define jl_is_unionall(v) jl_typeis(v,*JULIA_API(jl_unionall_type))
192
+ #define jl_is_typename(v) jl_typeis(v,*JULIA_API(jl_typename_type))
193
+ #define jl_is_int8(v) jl_typeis(v,*JULIA_API(jl_int8_type))
194
+ #define jl_is_int16(v) jl_typeis(v,*JULIA_API(jl_int16_type))
195
+ #define jl_is_int32(v) jl_typeis(v,*JULIA_API(jl_int32_type))
196
+ #define jl_is_int64(v) jl_typeis(v,*JULIA_API(jl_int64_type))
197
+ #define jl_is_uint8(v) jl_typeis(v,*JULIA_API(jl_uint8_type))
198
+ #define jl_is_uint16(v) jl_typeis(v,*JULIA_API(jl_uint16_type))
199
+ #define jl_is_uint32(v) jl_typeis(v,*JULIA_API(jl_uint32_type))
200
+ #define jl_is_uint64(v) jl_typeis(v,*JULIA_API(jl_uint64_type))
201
+ #define jl_is_float32(v) jl_typeis(v,*JULIA_API(jl_float32_type))
202
+ #define jl_is_float64(v) jl_typeis(v,*JULIA_API(jl_float64_type))
203
+ #define jl_is_bool(v) jl_typeis(v,*JULIA_API(jl_bool_type))
204
+ #define jl_is_symbol(v) jl_typeis(v,*JULIA_API(jl_sym_type))
205
+ #define jl_is_method_instance(v) jl_typeis(v,*JULIA_API(jl_method_instance_type))
206
+ #define jl_is_method(v) jl_typeis(v,*JULIA_API(jl_method_type))
207
+ #define jl_is_module(v) jl_typeis(v,*JULIA_API(jl_module_type))
208
+ #define jl_is_string(v) jl_typeis(v,*JULIA_API(jl_string_type))
209
+ /*#define jl_is_cpointer(v) jl_is_cpointer_type(jl_typeof(v))*/
210
+ /*#define jl_is_pointer(v) jl_is_cpointer_type(jl_typeof(v))*/
211
+
212
+ static inline jl_function_t *
213
+ jl_get_function(jl_module_t *m, const char *name)
214
+ {
215
+ return (jl_function_t*)JULIA_API(jl_get_global)(m, JULIA_API(jl_symbol)(name));
216
+ }
217
+
218
+ void rbjl_check_julia_exception(const char *message);
219
+
220
+ void rbjl_init_libjulia(void);
221
+ void rbjl_init_rbcall(void);
222
+ void rbjl_init_value_ptr(void);
223
+
224
+ VALUE rbjl_rbcall_convert_to_ruby(jl_value_t *value);
225
+ void rbjl_rbcall_incref(jl_value_t *value);
226
+ void rbjl_rbcall_decref(jl_value_t *value);
227
+ long rbjl_rbcall_refcnt(jl_value_t *jlobj);
228
+
229
+ VALUE rbjl_value_ptr_new(jl_value_t *value);
230
+
231
+ extern VALUE rbjl_mJulia;
232
+ extern VALUE rbjl_mLibJulia;
233
+ extern VALUE rbjl_cJuliaValuePtr;
120
234
 
121
- void julia_init_libjulia(void);
235
+ extern jl_module_t *rbjl_rbcall_module;
122
236
 
123
- extern VALUE julia_mJulia;
124
- extern VALUE julia_mLibJulia;
125
237
  #endif /* JULIA_INTERNAL_H */
@@ -1,13 +1,11 @@
1
1
  #include "julia_internal.h"
2
2
 
3
- VALUE julia_mLibJulia;
4
- VALUE julia_eAPINotFound;
5
- struct julia_api_table api_table;
6
- jl_value_t *ans;
7
- int8_t ans_bool;
8
-
9
- struct julia_api_table *
10
- julia_get_api_table(void)
3
+ VALUE rbjl_mLibJulia;
4
+ VALUE rbjl_eAPINotFound;
5
+ struct rbjl_api_table api_table;
6
+
7
+ struct rbjl_api_table *
8
+ rbjl_get_api_table(void)
11
9
  {
12
10
  return &api_table;
13
11
  }
@@ -44,7 +42,7 @@ init_api_table(VALUE handle)
44
42
  #define INIT_API_TABLE_ENTRY2(member_name, api_name) do { \
45
43
  void *fptr = LOOKUP_API_ENTRY(api_name); \
46
44
  if (!fptr) { \
47
- rb_raise(julia_eAPINotFound, "Unable to find the required symbol in libjulia: %s", #api_name); \
45
+ rb_raise(rbjl_eAPINotFound, "Unable to find the required symbol in libjulia: %s", #api_name); \
48
46
  } \
49
47
  ((api_table).member_name) = fptr; \
50
48
  } while (0)
@@ -74,6 +72,17 @@ init_api_table(VALUE handle)
74
72
  INIT_API_TABLE_ENTRY(jl_float16_type);
75
73
  INIT_API_TABLE_ENTRY(jl_float32_type);
76
74
  INIT_API_TABLE_ENTRY(jl_float64_type);
75
+ INIT_API_TABLE_ENTRY(jl_module_type);
76
+
77
+ INIT_API_TABLE_ENTRY(jl_main_module);
78
+ INIT_API_TABLE_ENTRY(jl_base_module);
79
+
80
+ INIT_API_TABLE_ENTRY(jl_call1);
81
+ INIT_API_TABLE_ENTRY(jl_call2);
82
+ INIT_API_TABLE_ENTRY(jl_exception_occurred);
83
+ INIT_API_TABLE_ENTRY(jl_exception_clear);
84
+ INIT_API_TABLE_ENTRY(jl_get_global);
85
+ INIT_API_TABLE_ENTRY(jl_symbol);
77
86
  INIT_API_TABLE_ENTRY(jl_eval_string);
78
87
  INIT_API_TABLE_ENTRY(jl_typeof);
79
88
  INIT_API_TABLE_ENTRY(jl_typeof_str);
@@ -89,160 +98,37 @@ init_api_table(VALUE handle)
89
98
  INIT_API_TABLE_ENTRY(jl_unbox_uint64);
90
99
  INIT_API_TABLE_ENTRY(jl_unbox_float32);
91
100
  INIT_API_TABLE_ENTRY(jl_unbox_float64);
92
- }
93
-
94
- int
95
- jl_typeis(jl_value_t *v, jl_datatype_t *t){
96
- return ((jl_typename_t *)JULIA_API(jl_typeof)(v) == t->name);
97
- }
98
-
99
- int
100
- jl_is_bool(jl_value_t *v)
101
- {
102
- return jl_typeis(v, JULIA_API(jl_bool_type));
103
- }
104
-
105
- int
106
- jl_is_char(jl_value_t *v)
107
- {
108
- return jl_typeis(v, JULIA_API(jl_char_type));
109
- }
110
-
111
- int
112
- jl_is_string(jl_value_t *v)
113
- {
114
- return jl_typeis(v, JULIA_API(jl_string_type));
115
- }
116
-
117
- int
118
- jl_is_int8(jl_value_t *v)
119
- {
120
- return jl_typeis(v, JULIA_API(jl_int8_type));
121
- }
122
-
123
- int
124
- jl_is_uint8(jl_value_t *v)
125
- {
126
- return jl_typeis(v, JULIA_API(jl_uint8_type));
127
- }
128
-
129
- int
130
- jl_is_int16(jl_value_t *v)
131
- {
132
- return jl_typeis(v, JULIA_API(jl_int16_type));
133
- }
134
-
135
- int
136
- jl_is_uint16(jl_value_t *v)
137
- {
138
- return jl_typeis(v, JULIA_API(jl_uint16_type));
139
- }
140
-
141
- int
142
- jl_is_int32(jl_value_t *v)
143
- {
144
- return jl_typeis(v, JULIA_API(jl_int32_type));
145
- }
146
-
147
- int
148
- jl_is_uint32(jl_value_t *v)
149
- {
150
- return jl_typeis(v, JULIA_API(jl_uint32_type));
151
- }
152
-
153
- int
154
- jl_is_int64(jl_value_t *v)
155
- {
156
- return jl_typeis(v, JULIA_API(jl_int64_type));
157
- }
158
-
159
- int
160
- jl_is_uint64(jl_value_t *v)
161
- {
162
- return jl_typeis(v, JULIA_API(jl_uint64_type));
163
- }
164
-
165
- int
166
- jl_is_float16(jl_value_t *v)
167
- {
168
- return jl_typeis(v, JULIA_API(jl_float16_type));
169
- }
170
-
171
- int
172
- jl_is_float32(jl_value_t *v)
173
- {
174
- return jl_typeis(v, JULIA_API(jl_float32_type));
175
- }
176
-
177
- int
178
- jl_is_float64(jl_value_t *v)
179
- {
180
- return jl_typeis(v, JULIA_API(jl_float64_type));
101
+ INIT_API_TABLE_ENTRY(jl_unbox_voidpointer);
181
102
  }
182
103
 
183
104
  static VALUE
184
- jl_eval_string(VALUE handle, VALUE arg)
105
+ jl_eval_string(VALUE handle, VALUE arg, VALUE raw_p)
185
106
  {
186
107
  Check_Type(arg, T_STRING);
187
- ans = JULIA_API(jl_eval_string)(StringValuePtr(arg));
188
- if (jl_is_string(ans)) {
189
- return rb_str_new2(JULIA_API(jl_string_ptr)(ans));
190
- }
191
- if (jl_is_bool(ans)) {
192
- ans_bool = JULIA_API(jl_unbox_bool)(ans);
193
- if (ans_bool == 1){
194
- return Qtrue;
195
- }else{
196
- return Qfalse;
197
- }
198
- }
199
- if (jl_is_int8(ans)) {
200
- return INT2NUM(JULIA_API(jl_unbox_int8)(ans));
201
- }
202
- if (jl_is_uint8(ans)) {
203
- return INT2NUM(JULIA_API(jl_unbox_uint8)(ans));
204
- }
205
- if (jl_is_int16(ans)) {
206
- return INT2NUM(JULIA_API(jl_unbox_int16)(ans));
207
- }
208
- if (jl_is_uint16(ans)) {
209
- return INT2NUM(JULIA_API(jl_unbox_uint16)(ans));
210
- }
211
- if (jl_is_int32(ans)) {
212
- return INT2NUM(JULIA_API(jl_unbox_int32)(ans));
213
- }
214
- if (jl_is_uint32(ans)) {
215
- return INT2NUM(JULIA_API(jl_unbox_uint32)(ans));
216
- }
217
- if (jl_is_int64(ans)) {
218
- return INT2NUM(JULIA_API(jl_unbox_int64)(ans));
219
- }
220
- if (jl_is_uint64(ans)) {
221
- return INT2NUM(JULIA_API(jl_unbox_uint64)(ans));
222
- }
223
- if (jl_is_float32(ans)) {
224
- return DBL2NUM(JULIA_API(jl_unbox_float32)(ans));
225
- }
226
- if (jl_is_float64(ans)) {
227
- return DBL2NUM(JULIA_API(jl_unbox_float64)(ans));
108
+ jl_value_t *ans = JULIA_API(jl_eval_string)(StringValuePtr(arg));
109
+ rbjl_check_julia_exception("LibJulia.eval_string");
110
+
111
+ if (RTEST(raw_p)) {
112
+ return rbjl_value_ptr_new(ans);
228
113
  }
229
- return rb_str_new2(JULIA_API(jl_typeof_str)(ans));
114
+
115
+ return rbjl_rbcall_convert_to_ruby(ans);
230
116
  }
231
117
 
232
118
  static void
233
119
  define_JULIA_VERSION(void)
234
120
  {
235
121
  char const *version = JULIA_API(jl_ver_string)();
236
- rb_define_const(julia_mLibJulia, "JULIA_VERSION", rb_usascii_str_new_static(version, strlen(version)));
122
+ rb_define_const(rbjl_mLibJulia, "JULIA_VERSION", rb_usascii_str_new_static(version, strlen(version)));
237
123
  }
238
124
 
239
125
  void
240
- julia_init_libjulia(void)
126
+ rbjl_init_libjulia(void)
241
127
  {
242
128
  VALUE handle;
243
- julia_mLibJulia = rb_const_get_at(julia_mJulia, rb_intern("LibJulia"));
244
- handle = rb_funcall(julia_mLibJulia, rb_intern("handle"), 0);
245
- rb_define_module_function(julia_mLibJulia, "jl_eval_string", jl_eval_string, 1);
129
+ rbjl_mLibJulia = rb_const_get_at(rbjl_mJulia, rb_intern("LibJulia"));
130
+ handle = rb_funcall(rbjl_mLibJulia, rb_intern("handle"), 0);
131
+ rb_define_module_function(rbjl_mLibJulia, "jl_eval_string", jl_eval_string, 2);
246
132
  init_api_table(handle);
247
133
 
248
134
  if (JULIA_API(jl_is_initialized)() == 0) {
@@ -0,0 +1,66 @@
1
+ #include "julia_internal.h"
2
+
3
+ jl_module_t *rbjl_rbcall_module;
4
+
5
+ static jl_function_t *convert_to_ruby_function;
6
+ static jl_function_t *incref_function;
7
+ static jl_function_t *decref_function;
8
+ static jl_function_t *refcnt_function;
9
+
10
+ VALUE
11
+ rbjl_rbcall_convert_to_ruby(jl_value_t *jlobj)
12
+ {
13
+ jl_value_t *ans = JULIA_API(jl_call1)(convert_to_ruby_function, jlobj);
14
+ rbjl_check_julia_exception("rbjl_rbcall_convert_to_ruby");
15
+ return (VALUE)JULIA_API(jl_unbox_voidpointer)(ans);
16
+ }
17
+
18
+ void
19
+ rbjl_rbcall_incref(jl_value_t *jlobj)
20
+ {
21
+ (void)JULIA_API(jl_call1)(incref_function, jlobj);
22
+ }
23
+
24
+ void
25
+ rbjl_rbcall_decref(jl_value_t *jlobj)
26
+ {
27
+ (void)JULIA_API(jl_call1)(decref_function, jlobj);
28
+ }
29
+
30
+ long
31
+ rbjl_rbcall_refcnt(jl_value_t *jlobj)
32
+ {
33
+ jl_value_t *res = JULIA_API(jl_call1)(refcnt_function, jlobj);
34
+ /* TODO: exception handling */
35
+ if (jl_is_int32(res)) {
36
+ return JULIA_API(jl_unbox_int32)(res);
37
+ }
38
+ else if (jl_is_int64(res)) {
39
+ return JULIA_API(jl_unbox_int64)(res);
40
+ }
41
+
42
+ return -1;
43
+ }
44
+
45
+ void
46
+ rbjl_init_rbcall(void)
47
+ {
48
+ VALUE rbcall_dir = rb_ivar_get(rbjl_mJulia, rb_intern("@rbcall_dir"));
49
+ StringValue(rbcall_dir);
50
+
51
+ VALUE include_rbcall = rb_sprintf("Base.include(Main, \"%"PRIsVALUE"/src/RbCall.jl\")", rbcall_dir);
52
+ const char *include_rbcall_cstr = StringValueCStr(include_rbcall);
53
+ (void)JULIA_API(jl_eval_string)(include_rbcall_cstr);
54
+ rbjl_check_julia_exception("include RbCall.jl");
55
+
56
+ jl_module_t *main_module = *JULIA_API(jl_main_module);
57
+ jl_value_t *rbcall_module = JULIA_API(jl_get_global)(main_module, JULIA_API(jl_symbol)("RbCall"));
58
+ if (!rbcall_module || !jl_is_module(rbcall_module)) {
59
+ rb_raise(rb_eRuntimeError, "RbCall is not a module");
60
+ }
61
+ rbjl_rbcall_module = (jl_module_t *)rbcall_module;
62
+ convert_to_ruby_function = jl_get_function(rbjl_rbcall_module, "convert_to_ruby");
63
+ incref_function = jl_get_function(rbjl_rbcall_module, "_incref");
64
+ decref_function = jl_get_function(rbjl_rbcall_module, "_decref");
65
+ refcnt_function = jl_get_function(rbjl_rbcall_module, "_refcnt");
66
+ }
@@ -0,0 +1,49 @@
1
+ #include "julia_internal.h"
2
+
3
+ VALUE rbjl_cJuliaValuePtr;
4
+
5
+ static void
6
+ rbjl_value_ptr_free(void *ptr)
7
+ {
8
+ jl_value_t *jlobj = ptr;
9
+ rbjl_rbcall_decref(jlobj);
10
+ }
11
+
12
+ static size_t
13
+ rbjl_value_ptr_memsize(void const *ptr)
14
+ {
15
+ /* FIXME */
16
+ return 0;
17
+ }
18
+
19
+ const rb_data_type_t rbjl_value_ptr_data_type = {
20
+ "Julia::ValuePtr",
21
+ { 0, rbjl_value_ptr_free, rbjl_value_ptr_memsize, },
22
+ #ifdef RUBY_TYPED_FREE_IMMEDIATELY
23
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
24
+ #endif
25
+ };
26
+
27
+ VALUE
28
+ rbjl_value_ptr_new(jl_value_t *jlobj)
29
+ {
30
+ VALUE rbobj = TypedData_Wrap_Struct(rbjl_cJuliaValuePtr, &rbjl_value_ptr_data_type, jlobj);
31
+ rbjl_rbcall_incref(jlobj);
32
+ return rbobj;
33
+ }
34
+
35
+ static VALUE
36
+ value_ptr_refcnt(VALUE self)
37
+ {
38
+ jl_value_t *value;
39
+ TypedData_Get_Struct(self, jl_value_t, &rbjl_value_ptr_data_type, value);
40
+ long refcnt = rbjl_rbcall_refcnt(value);
41
+ return LONG2NUM(refcnt);
42
+ }
43
+
44
+ void
45
+ rbjl_init_value_ptr(void)
46
+ {
47
+ rbjl_cJuliaValuePtr = rb_define_class_under(rbjl_mJulia, "ValuePtr", rb_cData);
48
+ rb_define_method(rbjl_cJuliaValuePtr, "__refcnt__", value_ptr_refcnt, 0);
49
+ }
@@ -5,9 +5,15 @@ require 'julia/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "julia"
8
- spec.version = Julia::VERSION
8
+ version_components = [
9
+ Julia::Version::MAJOR.to_s,
10
+ Julia::Version::MINOR.to_s,
11
+ Julia::Version::MICRO.to_s,
12
+ Julia::Version::TAG,
13
+ ]
14
+ spec.version = version_components.compact.join(".")
9
15
  spec.authors = ["Kenta Murata"]
10
- spec.email = ["mrkn@cookpad.com"]
16
+ spec.email = ["mrkn@mrkn.jp"]
11
17
 
12
18
  spec.summary = 'Julia on Ruby'
13
19
  spec.description = 'Julia on Ruby'
@@ -21,11 +27,12 @@ Gem::Specification.new do |spec|
21
27
  spec.bindir = "exe"
22
28
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
29
  spec.require_paths = ["lib"]
30
+ spec.extensions = ["ext/julia/extconf.rb"]
24
31
 
25
- spec.add_development_dependency "bundler", "~> 1.10"
32
+ spec.add_development_dependency "bundler", ">= 1.17.2"
26
33
  spec.add_development_dependency "pry"
27
34
  spec.add_development_dependency "pry-byebug"
28
- spec.add_development_dependency "rake", "~> 10.0"
35
+ spec.add_development_dependency "rake"
29
36
  spec.add_development_dependency "rake-compiler"
30
37
  spec.add_development_dependency "rspec"
31
38
  end
@@ -5,8 +5,8 @@ module Julia
5
5
 
6
6
  module_function
7
7
 
8
- def eval(str)
9
- Julia.init unless LibJulia.respond_to? :jl_eval_string
10
- LibJulia.jl_eval_string(str)
8
+ def eval(str, raw: false)
9
+ Julia.init unless defined? Julia::JULIA_VERSION
10
+ LibJulia.jl_eval_string(str, raw)
11
11
  end
12
12
  end
@@ -1,34 +1,43 @@
1
1
  module Julia
2
2
  def self.const_missing(name)
3
3
  case name
4
- when :JULIA_VERSION
5
- Julia.init
6
- const_get(name)
7
- else
8
- super
4
+ when :JULIA_VERSION, :ValuePtr
5
+ return const_get(name) if Julia.init
9
6
  end
7
+ super
8
+ end
9
+
10
+ def self.method_missing(*args)
11
+ return send(*args) if Julia.init
12
+ super
10
13
  end
11
14
 
12
15
  module LibJulia
13
16
  def self.const_missing(name)
14
17
  case name
15
18
  when :JULIA_VERSION
16
- Julia.init
17
- const_get(name)
18
- else
19
- super
19
+ return const_get(name) if Julia.init
20
20
  end
21
+ super
22
+ end
23
+
24
+ def self.method_missing(*args)
25
+ return send(*args) if Julia.init
26
+ super
21
27
  end
22
28
  end
23
29
 
30
+ def self.initialized?
31
+ @initialized
32
+ end
33
+
24
34
  def self.init(julia = ENV['JULIA'])
25
- return false if LibJulia.instance_variable_defined? :@handle
26
- class << Julia
27
- remove_method :const_missing
28
- end
29
- class << Julia::LibJulia
30
- remove_method :const_missing
31
- end
35
+ return false if initialized?
36
+
37
+ require 'pathname'
38
+ top_dir = Pathname(__dir__).parent.parent
39
+ rbcall_dir = top_dir / "RbCall.jl"
40
+ Julia.instance_variable_set :@rbcall_dir, rbcall_dir.to_s
32
41
 
33
42
  LibJulia.instance_variable_set :@handle, LibJulia::Finder.find_libjulia(julia)
34
43
  class << LibJulia
@@ -44,6 +53,17 @@ module Julia
44
53
  end
45
54
 
46
55
  const_set(:JULIA_VERSION, LibJulia::JULIA_VERSION)
47
- true
56
+
57
+ class << Julia
58
+ remove_method :const_missing
59
+ remove_method :method_missing
60
+ end
61
+
62
+ class << Julia::LibJulia
63
+ remove_method :const_missing
64
+ remove_method :method_missing
65
+ end
66
+
67
+ @initialized = true
48
68
  end
49
69
  end
@@ -1,3 +1,9 @@
1
1
  module Julia
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0-dev"
3
+
4
+ module Version
5
+ numbers, TAG = VERSION.split("-")
6
+ MAJOR, MINOR, MICRO = numbers.split(".").map(&:to_i)
7
+ STRING = VERSION
8
+ end
3
9
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: julia
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0.dev
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenta Murata
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-29 00:00:00.000000000 Z
11
+ date: 2019-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.10'
19
+ version: 1.17.2
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.10'
26
+ version: 1.17.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: pry
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '10.0'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '10.0'
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake-compiler
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -96,9 +96,10 @@ dependencies:
96
96
  version: '0'
97
97
  description: Julia on Ruby
98
98
  email:
99
- - mrkn@cookpad.com
99
+ - mrkn@mrkn.jp
100
100
  executables: []
101
- extensions: []
101
+ extensions:
102
+ - ext/julia/extconf.rb
102
103
  extra_rdoc_files: []
103
104
  files:
104
105
  - ".gitignore"
@@ -108,6 +109,8 @@ files:
108
109
  - LICENSE.txt
109
110
  - README.md
110
111
  - Rakefile
112
+ - RbCall.jl/src/RbCall.jl
113
+ - RbCall.jl/src/conversion.jl
111
114
  - bin/console
112
115
  - bin/setup
113
116
  - examples/pkg_status.rb
@@ -115,6 +118,8 @@ files:
115
118
  - ext/julia/julia.c
116
119
  - ext/julia/julia_internal.h
117
120
  - ext/julia/libjulia.c
121
+ - ext/julia/rbcall.c
122
+ - ext/julia/value_ptr.c
118
123
  - julia.gemspec
119
124
  - lib/julia.rb
120
125
  - lib/julia/error.rb
@@ -140,12 +145,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
140
145
  version: '0'
141
146
  required_rubygems_version: !ruby/object:Gem::Requirement
142
147
  requirements:
143
- - - ">="
148
+ - - ">"
144
149
  - !ruby/object:Gem::Version
145
- version: '0'
150
+ version: 1.3.1
146
151
  requirements: []
147
- rubyforge_project:
148
- rubygems_version: 2.7.6
152
+ rubygems_version: 3.0.2
149
153
  signing_key:
150
154
  specification_version: 4
151
155
  summary: Julia on Ruby