julia 0.2.0 → 0.3.0.dev

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