jsonnet 0.1.0 → 0.4.0
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 +5 -5
- data/.clang-format +11 -0
- data/.travis.yml +19 -0
- data/README.md +72 -13
- data/ext/jsonnet/callbacks.c +241 -0
- data/ext/jsonnet/extconf.rb +56 -0
- data/ext/jsonnet/helpers.c +74 -0
- data/ext/jsonnet/jsonnet.c +4 -357
- data/ext/jsonnet/jsonnet_values.c +206 -0
- data/ext/jsonnet/ruby_jsonnet.h +39 -0
- data/ext/jsonnet/vm.c +508 -0
- data/jsonnet.gemspec +6 -4
- data/lib/jsonnet.rb +42 -2
- data/lib/jsonnet/version.rb +1 -1
- data/lib/jsonnet/vm.rb +127 -8
- data/test/fixtures/jpath.libsonnet +3 -0
- data/test/test_jsonnet.rb +44 -1
- data/test/test_vm.rb +313 -10
- metadata +37 -16
@@ -0,0 +1,74 @@
|
|
1
|
+
#include <string.h>
|
2
|
+
|
3
|
+
#include <libjsonnet.h>
|
4
|
+
#include <ruby/ruby.h>
|
5
|
+
#include <ruby/encoding.h>
|
6
|
+
|
7
|
+
#include "ruby_jsonnet.h"
|
8
|
+
|
9
|
+
static ID id_message;
|
10
|
+
|
11
|
+
/*
|
12
|
+
* Indicates that the encoding of the given string is not allowed by
|
13
|
+
* the C++ implementation of Jsonnet.
|
14
|
+
*/
|
15
|
+
static VALUE eUnsupportedEncodingError;
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Asserts that the given string-like object is in an
|
19
|
+
* ASCII-compatible encoding.
|
20
|
+
*
|
21
|
+
* @param[in] str a String-like object
|
22
|
+
* @throw UnsupportedEncodingError on assertion failure.
|
23
|
+
*/
|
24
|
+
rb_encoding *
|
25
|
+
rubyjsonnet_assert_asciicompat(VALUE str)
|
26
|
+
{
|
27
|
+
rb_encoding *enc = rb_enc_get(str);
|
28
|
+
if (!rb_enc_asciicompat(enc)) {
|
29
|
+
rb_raise(eUnsupportedEncodingError, "jsonnet encoding must be ASCII-compatible but got %s",
|
30
|
+
rb_enc_name(enc));
|
31
|
+
}
|
32
|
+
return enc;
|
33
|
+
}
|
34
|
+
|
35
|
+
/**
|
36
|
+
* Allocates a C string whose content is equal to \c str with jsonnet_realloc.
|
37
|
+
*/
|
38
|
+
char *
|
39
|
+
rubyjsonnet_str_to_cstr(struct JsonnetVm *vm, VALUE str)
|
40
|
+
{
|
41
|
+
const char *const cstr = StringValueCStr(str);
|
42
|
+
char *const buf = jsonnet_realloc(vm, NULL, strlen(cstr));
|
43
|
+
strcpy(buf, cstr);
|
44
|
+
return buf;
|
45
|
+
}
|
46
|
+
|
47
|
+
/**
|
48
|
+
* @return a human readable string which contains the class name of the
|
49
|
+
* exception and its message. It might be nil on failure
|
50
|
+
*/
|
51
|
+
VALUE
|
52
|
+
rubyjsonnet_format_exception(VALUE exc)
|
53
|
+
{
|
54
|
+
VALUE name = rb_class_name(rb_obj_class(exc));
|
55
|
+
VALUE msg = rb_funcall(exc, id_message, 0);
|
56
|
+
if (RB_TYPE_P(name, RUBY_T_STRING) && rb_str_strlen(name)) {
|
57
|
+
if (RB_TYPE_P(msg, RUBY_T_STRING) && rb_str_strlen(msg)) {
|
58
|
+
return rb_str_concat(rb_str_cat_cstr(name, " : "), msg);
|
59
|
+
} else {
|
60
|
+
return name;
|
61
|
+
}
|
62
|
+
} else if (RB_TYPE_P(msg, RUBY_T_STRING) && rb_str_strlen(msg)) {
|
63
|
+
return msg;
|
64
|
+
}
|
65
|
+
return Qnil;
|
66
|
+
}
|
67
|
+
|
68
|
+
void
|
69
|
+
rubyjsonnet_init_helpers(VALUE mJsonnet)
|
70
|
+
{
|
71
|
+
id_message = rb_intern("message");
|
72
|
+
eUnsupportedEncodingError =
|
73
|
+
rb_define_class_under(mJsonnet, "UnsupportedEncodingError", rb_eEncodingError);
|
74
|
+
}
|
data/ext/jsonnet/jsonnet.c
CHANGED
@@ -1,127 +1,8 @@
|
|
1
|
-
#include <
|
1
|
+
#include <libjsonnet.h>
|
2
2
|
#include <ruby/ruby.h>
|
3
|
-
#include <ruby/intern.h>
|
4
3
|
#include <ruby/encoding.h>
|
5
|
-
#include <libjsonnet.h>
|
6
4
|
|
7
|
-
|
8
|
-
static ID id_message;
|
9
|
-
|
10
|
-
/*
|
11
|
-
* Jsonnet evaluator
|
12
|
-
*/
|
13
|
-
static VALUE cVM;
|
14
|
-
static VALUE eEvaluationError;
|
15
|
-
/**
|
16
|
-
* Indicates that the encoding of the given string is not allowed by
|
17
|
-
* the C++ implementation of Jsonnet.
|
18
|
-
*/
|
19
|
-
static VALUE eUnsupportedEncodingError;
|
20
|
-
|
21
|
-
struct jsonnet_vm_wrap {
|
22
|
-
struct JsonnetVm *vm;
|
23
|
-
VALUE callback;
|
24
|
-
};
|
25
|
-
|
26
|
-
static void vm_free(void *ptr);
|
27
|
-
static void vm_mark(void *ptr);
|
28
|
-
|
29
|
-
static const rb_data_type_t jsonnet_vm_type = {
|
30
|
-
"JsonnetVm",
|
31
|
-
{
|
32
|
-
/* dmark = */ vm_mark,
|
33
|
-
/* dfree = */ vm_free,
|
34
|
-
/* dsize = */ 0,
|
35
|
-
},
|
36
|
-
/* parent = */ 0,
|
37
|
-
/* data = */ 0,
|
38
|
-
/* flags = */ RUBY_TYPED_FREE_IMMEDIATELY
|
39
|
-
};
|
40
|
-
|
41
|
-
/**
|
42
|
-
* raises an EvaluationError whose message is \c msg.
|
43
|
-
* @param[in] vm a JsonnetVM
|
44
|
-
* @param[in] msg must be a NUL-terminated string returned by \c vm.
|
45
|
-
* @return never returns
|
46
|
-
* @throw EvaluationError
|
47
|
-
*/
|
48
|
-
static void
|
49
|
-
raise_eval_error(struct JsonnetVm *vm, char *msg, rb_encoding *enc)
|
50
|
-
{
|
51
|
-
VALUE ex = rb_exc_new3(eEvaluationError, rb_enc_str_new_cstr(msg, enc));
|
52
|
-
jsonnet_realloc(vm, msg, 0);
|
53
|
-
rb_exc_raise(ex);
|
54
|
-
}
|
55
|
-
|
56
|
-
/**
|
57
|
-
* Returns a String whose contents is equal to \c json.
|
58
|
-
* It automatically frees \c json just after constructing the return value.
|
59
|
-
*
|
60
|
-
* @param[in] vm a JsonnetVM
|
61
|
-
* @param[in] json must be a NUL-terminated string returned by \c vm.
|
62
|
-
* @return Ruby string equal to \c json.
|
63
|
-
*/
|
64
|
-
static VALUE
|
65
|
-
str_new_json(struct JsonnetVm *vm, char *json, rb_encoding *enc)
|
66
|
-
{
|
67
|
-
VALUE str = rb_enc_str_new_cstr(json, enc);
|
68
|
-
jsonnet_realloc(vm, json, 0);
|
69
|
-
return str;
|
70
|
-
}
|
71
|
-
|
72
|
-
/**
|
73
|
-
* Returns a Hash, whose keys are file names in the multi-mode of Jsonnet,
|
74
|
-
* and whose values are corresponding JSON values.
|
75
|
-
* It automatically frees \c json just after constructing the return value.
|
76
|
-
*
|
77
|
-
* @param[in] vm a JsonnetVM
|
78
|
-
* @param[in] buf NUL-separated and double-NUL-terminated sequence of strings returned by \c vm.
|
79
|
-
* @return Hash
|
80
|
-
*/
|
81
|
-
static VALUE
|
82
|
-
fileset_new(struct JsonnetVm *vm, char *buf, rb_encoding *enc)
|
83
|
-
{
|
84
|
-
VALUE fileset = rb_hash_new();
|
85
|
-
char *ptr, *json;
|
86
|
-
for (ptr = buf; *ptr; ptr = json + strlen(json)+1) {
|
87
|
-
json = ptr + strlen(ptr) + 1;
|
88
|
-
if (!*json) {
|
89
|
-
VALUE ex = rb_exc_new3(
|
90
|
-
eEvaluationError,
|
91
|
-
rb_enc_sprintf(enc, "output file %s without body", ptr));
|
92
|
-
jsonnet_realloc(vm, buf, 0);
|
93
|
-
rb_exc_raise(ex);
|
94
|
-
}
|
95
|
-
|
96
|
-
rb_hash_aset(fileset, rb_enc_str_new_cstr(ptr, enc), rb_enc_str_new_cstr(json, enc));
|
97
|
-
}
|
98
|
-
jsonnet_realloc(vm, buf, 0);
|
99
|
-
return fileset;
|
100
|
-
}
|
101
|
-
|
102
|
-
/**
|
103
|
-
* Allocates a C string whose content is equal to \c str with jsonnet_realloc.
|
104
|
-
*/
|
105
|
-
static char *
|
106
|
-
str_jsonnet_cstr(struct JsonnetVm *vm, VALUE str)
|
107
|
-
{
|
108
|
-
const char *const cstr = StringValueCStr(str);
|
109
|
-
char *const buf = jsonnet_realloc(vm, NULL, strlen(cstr));
|
110
|
-
strcpy(buf, cstr);
|
111
|
-
return buf;
|
112
|
-
}
|
113
|
-
|
114
|
-
static rb_encoding *
|
115
|
-
enc_assert_asciicompat(VALUE str) {
|
116
|
-
rb_encoding *enc = rb_enc_get(str);
|
117
|
-
if (!rb_enc_asciicompat(enc)) {
|
118
|
-
rb_raise(
|
119
|
-
eUnsupportedEncodingError,
|
120
|
-
"jsonnet encoding must be ASCII-compatible but got %s",
|
121
|
-
rb_enc_name(enc));
|
122
|
-
}
|
123
|
-
return enc;
|
124
|
-
}
|
5
|
+
#include "ruby_jsonnet.h"
|
125
6
|
|
126
7
|
/*
|
127
8
|
* call-seq:
|
@@ -135,246 +16,12 @@ jw_s_version(VALUE mod)
|
|
135
16
|
return rb_usascii_str_new_cstr(jsonnet_version());
|
136
17
|
}
|
137
18
|
|
138
|
-
static VALUE
|
139
|
-
vm_s_new(VALUE mod)
|
140
|
-
{
|
141
|
-
struct jsonnet_vm_wrap *vm;
|
142
|
-
VALUE self = TypedData_Make_Struct(cVM, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
|
143
|
-
vm->vm = jsonnet_make();
|
144
|
-
vm->callback = Qnil;
|
145
|
-
return self;
|
146
|
-
}
|
147
|
-
|
148
|
-
static void
|
149
|
-
vm_free(void *ptr)
|
150
|
-
{
|
151
|
-
struct jsonnet_vm_wrap *vm = (struct jsonnet_vm_wrap*)ptr;
|
152
|
-
jsonnet_destroy(vm->vm);
|
153
|
-
REALLOC_N(vm, struct jsonnet_vm_wrap, 0);
|
154
|
-
}
|
155
|
-
|
156
|
-
static void
|
157
|
-
vm_mark(void *ptr)
|
158
|
-
{
|
159
|
-
struct jsonnet_vm_wrap *vm = (struct jsonnet_vm_wrap*)ptr;
|
160
|
-
rb_gc_mark(vm->callback);
|
161
|
-
}
|
162
|
-
|
163
|
-
static VALUE
|
164
|
-
vm_evaluate_file(VALUE self, VALUE fname, VALUE encoding, VALUE multi_p)
|
165
|
-
{
|
166
|
-
struct jsonnet_vm_wrap *vm;
|
167
|
-
int error;
|
168
|
-
char *result;
|
169
|
-
rb_encoding *const enc = rb_to_encoding(encoding);
|
170
|
-
|
171
|
-
TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
|
172
|
-
FilePathValue(fname);
|
173
|
-
if (RTEST(multi_p)) {
|
174
|
-
result = jsonnet_evaluate_file_multi(vm->vm, StringValueCStr(fname), &error);
|
175
|
-
}
|
176
|
-
else {
|
177
|
-
result = jsonnet_evaluate_file(vm->vm, StringValueCStr(fname), &error);
|
178
|
-
}
|
179
|
-
|
180
|
-
if (error) {
|
181
|
-
raise_eval_error(vm->vm, result, rb_enc_get(fname));
|
182
|
-
}
|
183
|
-
return RTEST(multi_p) ? fileset_new(vm->vm, result, enc) : str_new_json(vm->vm, result, enc);
|
184
|
-
}
|
185
|
-
|
186
|
-
static VALUE
|
187
|
-
vm_evaluate(VALUE self, VALUE snippet, VALUE fname, VALUE multi_p)
|
188
|
-
{
|
189
|
-
struct jsonnet_vm_wrap *vm;
|
190
|
-
int error;
|
191
|
-
char *result;
|
192
|
-
|
193
|
-
rb_encoding *enc = enc_assert_asciicompat(StringValue(snippet));
|
194
|
-
TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
|
195
|
-
FilePathValue(fname);
|
196
|
-
if (RTEST(multi_p)) {
|
197
|
-
result = jsonnet_evaluate_snippet_multi(
|
198
|
-
vm->vm,
|
199
|
-
StringValueCStr(fname), StringValueCStr(snippet), &error);
|
200
|
-
}
|
201
|
-
else {
|
202
|
-
result = jsonnet_evaluate_snippet(
|
203
|
-
vm->vm,
|
204
|
-
StringValueCStr(fname), StringValueCStr(snippet), &error);
|
205
|
-
}
|
206
|
-
|
207
|
-
if (error) {
|
208
|
-
raise_eval_error(vm->vm, result, rb_enc_get(fname));
|
209
|
-
}
|
210
|
-
return RTEST(multi_p) ? fileset_new(vm->vm, result, enc) : str_new_json(vm->vm, result, enc);
|
211
|
-
}
|
212
|
-
|
213
|
-
static VALUE
|
214
|
-
import_callback_thunk0(VALUE args)
|
215
|
-
{
|
216
|
-
VALUE callback = rb_ary_entry(args, 0);
|
217
|
-
return rb_funcall(callback, id_call, 2, rb_ary_entry(args, 1), rb_ary_entry(args, 2));
|
218
|
-
}
|
219
|
-
|
220
|
-
static char *
|
221
|
-
import_callback_thunk(void *ctx, const char *base, const char *rel, char **found_here, int *success)
|
222
|
-
{
|
223
|
-
struct jsonnet_vm_wrap *const vm = (struct jsonnet_vm_wrap*)ctx;
|
224
|
-
int state;
|
225
|
-
VALUE result, args;
|
226
|
-
|
227
|
-
args = rb_ary_tmp_new(3);
|
228
|
-
rb_ary_push(args, vm->callback);
|
229
|
-
rb_ary_push(args, rb_enc_str_new_cstr(base, rb_filesystem_encoding()));
|
230
|
-
rb_ary_push(args, rb_enc_str_new_cstr(rel, rb_filesystem_encoding()));
|
231
|
-
result = rb_protect(import_callback_thunk0, args, &state);
|
232
|
-
|
233
|
-
if (state) {
|
234
|
-
VALUE err = rb_errinfo();
|
235
|
-
VALUE msg, name;
|
236
|
-
|
237
|
-
rb_set_errinfo(Qnil);
|
238
|
-
name = rb_class_name(rb_obj_class(err));
|
239
|
-
msg = rb_funcall(err, id_message, 0);
|
240
|
-
if (rb_str_strlen(name)) {
|
241
|
-
if (rb_str_strlen(msg)) {
|
242
|
-
msg = rb_str_concat(rb_str_cat_cstr(name, " : "), msg);
|
243
|
-
} else {
|
244
|
-
msg = name;
|
245
|
-
}
|
246
|
-
} else if (!rb_str_strlen(msg)) {
|
247
|
-
msg = rb_sprintf("cannot import %s from %s", rel, base);
|
248
|
-
}
|
249
|
-
*success = 0;
|
250
|
-
return str_jsonnet_cstr(vm->vm, msg);
|
251
|
-
}
|
252
|
-
|
253
|
-
result = rb_Array(result);
|
254
|
-
*success = 1;
|
255
|
-
*found_here = str_jsonnet_cstr(vm->vm, rb_ary_entry(result, 1));
|
256
|
-
return str_jsonnet_cstr(vm->vm, rb_ary_entry(result, 0));
|
257
|
-
}
|
258
|
-
|
259
|
-
/**
|
260
|
-
* Sets a custom way to resolve "import" expression.
|
261
|
-
* @param [#call] callback receives two parameters and returns two values.
|
262
|
-
* The first parameter "base" is a base directory to resolve
|
263
|
-
* "rel" from.
|
264
|
-
* The second parameter "rel" is an absolute or a relative
|
265
|
-
* path to the file to import.
|
266
|
-
* The first return value is the content of the imported file.
|
267
|
-
* The second return value is the resolved path of the imported file.
|
268
|
-
*/
|
269
|
-
static VALUE
|
270
|
-
vm_set_import_callback(VALUE self, VALUE callback)
|
271
|
-
{
|
272
|
-
struct jsonnet_vm_wrap *vm;
|
273
|
-
TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
|
274
|
-
|
275
|
-
vm->callback = callback;
|
276
|
-
jsonnet_import_callback(vm->vm, import_callback_thunk, vm);
|
277
|
-
return callback;
|
278
|
-
}
|
279
|
-
|
280
|
-
/*
|
281
|
-
* Binds an external variable to a value.
|
282
|
-
* @param [String] key name of the variable
|
283
|
-
* @param [String] val the value
|
284
|
-
*/
|
285
|
-
static VALUE
|
286
|
-
vm_ext_var(VALUE self, VALUE key, VALUE val)
|
287
|
-
{
|
288
|
-
struct jsonnet_vm_wrap *vm;
|
289
|
-
|
290
|
-
enc_assert_asciicompat(StringValue(key));
|
291
|
-
enc_assert_asciicompat(StringValue(val));
|
292
|
-
TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
|
293
|
-
jsonnet_ext_var(vm->vm, StringValueCStr(key), StringValueCStr(val));
|
294
|
-
return Qnil;
|
295
|
-
}
|
296
|
-
|
297
|
-
static VALUE
|
298
|
-
vm_set_max_stack(VALUE self, VALUE val)
|
299
|
-
{
|
300
|
-
struct jsonnet_vm_wrap *vm;
|
301
|
-
TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
|
302
|
-
jsonnet_max_stack(vm->vm, NUM2UINT(val));
|
303
|
-
return Qnil;
|
304
|
-
}
|
305
|
-
|
306
|
-
static VALUE
|
307
|
-
vm_set_gc_min_objects(VALUE self, VALUE val)
|
308
|
-
{
|
309
|
-
struct jsonnet_vm_wrap *vm;
|
310
|
-
TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
|
311
|
-
jsonnet_gc_min_objects(vm->vm, NUM2UINT(val));
|
312
|
-
return Qnil;
|
313
|
-
}
|
314
|
-
|
315
|
-
static VALUE
|
316
|
-
vm_set_gc_growth_trigger(VALUE self, VALUE val)
|
317
|
-
{
|
318
|
-
struct jsonnet_vm_wrap *vm;
|
319
|
-
TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
|
320
|
-
jsonnet_gc_growth_trigger(vm->vm, NUM2DBL(val));
|
321
|
-
return Qnil;
|
322
|
-
}
|
323
|
-
|
324
|
-
/*
|
325
|
-
* Let #evalutae and #evaluate_file return a raw String instead of JSON-encoded string if val is true
|
326
|
-
* @param [Boolean] val
|
327
|
-
*/
|
328
|
-
static VALUE
|
329
|
-
vm_set_string_output(VALUE self, VALUE val)
|
330
|
-
{
|
331
|
-
struct jsonnet_vm_wrap *vm;
|
332
|
-
TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
|
333
|
-
jsonnet_string_output(vm->vm, RTEST(val));
|
334
|
-
return Qnil;
|
335
|
-
}
|
336
|
-
|
337
|
-
static VALUE
|
338
|
-
vm_set_max_trace(VALUE self, VALUE val)
|
339
|
-
{
|
340
|
-
struct jsonnet_vm_wrap *vm;
|
341
|
-
TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
|
342
|
-
jsonnet_max_trace(vm->vm, NUM2UINT(val));
|
343
|
-
return Qnil;
|
344
|
-
}
|
345
|
-
|
346
|
-
static VALUE
|
347
|
-
vm_set_debug_ast(VALUE self, VALUE val)
|
348
|
-
{
|
349
|
-
struct jsonnet_vm_wrap *vm;
|
350
|
-
TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
|
351
|
-
jsonnet_debug_ast(vm->vm, RTEST(val));
|
352
|
-
return Qnil;
|
353
|
-
}
|
354
|
-
|
355
19
|
void
|
356
20
|
Init_jsonnet_wrap(void)
|
357
21
|
{
|
358
|
-
id_call = rb_intern("call");
|
359
|
-
id_message = rb_intern("message");
|
360
|
-
|
361
22
|
VALUE mJsonnet = rb_define_module("Jsonnet");
|
362
23
|
rb_define_singleton_method(mJsonnet, "libversion", jw_s_version, 0);
|
363
24
|
|
364
|
-
|
365
|
-
|
366
|
-
rb_define_private_method(cVM, "eval_file", vm_evaluate_file, 3);
|
367
|
-
rb_define_private_method(cVM, "eval_snippet", vm_evaluate, 3);
|
368
|
-
rb_define_method(cVM, "ext_var", vm_ext_var, 2);
|
369
|
-
rb_define_method(cVM, "max_stack=", vm_set_max_stack, 1);
|
370
|
-
rb_define_method(cVM, "gc_min_objects=", vm_set_gc_min_objects, 1);
|
371
|
-
rb_define_method(cVM, "gc_growth_trigger=", vm_set_gc_growth_trigger, 1);
|
372
|
-
rb_define_method(cVM, "string_output=", vm_set_string_output, 1);
|
373
|
-
rb_define_method(cVM, "max_trace=", vm_set_max_trace, 1);
|
374
|
-
rb_define_method(cVM, "debug_ast=", vm_set_debug_ast, 1);
|
375
|
-
rb_define_method(cVM, "import_callback=", vm_set_import_callback, 1);
|
376
|
-
|
377
|
-
eEvaluationError = rb_define_class_under(mJsonnet, "EvaluationError", rb_eRuntimeError);
|
378
|
-
eUnsupportedEncodingError =
|
379
|
-
rb_define_class_under(mJsonnet, "UnsupportedEncodingError", rb_eEncodingError);
|
25
|
+
rubyjsonnet_init_helpers(mJsonnet);
|
26
|
+
rubyjsonnet_init_vm(mJsonnet);
|
380
27
|
}
|