Class: Jsonnet::VM

Inherits:
Object
  • Object
show all
Defined in:
lib/jsonnet/vm.rb,
ext/jsonnet/vm.c

Defined Under Namespace

Classes: UnsupportedOptionError

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ VM

initializes a new VM with the given configuration.

Parameters:

  • options (Hash) (defaults to: {})

    a mapping from option names to their values. It can have names of writable attributes in VM class as keys.



45
46
47
48
49
50
51
52
53
54
55
# File 'lib/jsonnet/vm.rb', line 45

def initialize(options = {})
  options.each do |key, value|
    method = "#{key}="
    if respond_to?(method)
      public_send(method, value)
    else
      raise UnsupportedOptionError.new("Jsonnet VM does not support #{key} option")
    end
  end
  self
end

Class Method Details

.evaluate(snippet, options = {}) ⇒ String

Convenient method to evaluate a Jsonnet snippet.

It implicitly instantiates a VM and then evaluate Jsonnet with the VM.

Parameters:

  • snippet (String)

    Jsonnet source string.

  • options (Hash) (defaults to: {})

    options to new or options to #evaluate

Returns:

  • (String)

See Also:



15
16
17
18
19
20
# File 'lib/jsonnet/vm.rb', line 15

def evaluate(snippet, options = {})
  snippet_check = ->(key, value) { key.to_s.match(/^filename|multi$/) }
  snippet_options = options.select(&snippet_check)
  vm_options = options.reject(&snippet_check)
  new(vm_options).evaluate(snippet, **snippet_options)
end

.evaluate_file(filename, options = {}) ⇒ String

Convenient method to evaluate a Jsonnet file.

It implicitly instantiates a VM and then evaluates Jsonnet with the VM.

Parameters:

  • filename (String)

    Jsonnet source file.

  • options (Hash) (defaults to: {})

    options to new or options to #evaluate_file

Returns:

  • (String)

See Also:



31
32
33
34
35
36
# File 'lib/jsonnet/vm.rb', line 31

def evaluate_file(filename, options = {})
  file_check = ->(key, value) { key.to_s.match(/^encoding|multi$/) }
  file_options = options.select(&file_check)
  vm_options = options.reject(&file_check)
  new(vm_options).evaluate_file(filename, **file_options)
end

Instance Method Details

#define_function(name, body = nil) { ... } ⇒ Object

Note:

Currently it cannot define keyword or optional paramters in Jsonnet. Also all the positional optional parameters of the body are interpreted as required parameters. And the body cannot have keyword, rest or keyword rest paramters.

Define a function (native extension) in the VM and let the given block handle the invocation of the function.

Parameters:

  • name (Symbol|String)

    name of the function. Must be a valid identifier in Jsonnet.

  • body (#to_proc) (defaults to: nil)

    body of the function.

Yields:

  • calls the given block instead of body if body is nil



140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/jsonnet/vm.rb', line 140

def define_function(name, body = nil, &block)
  body = body ? body.to_proc : block
  if body.nil?
    raise ArgumentError, 'define_function requires a body argument or a block'
  end
  params = body.parameters.map.with_index do |(type, name), i|
    raise ArgumentError, "rest or keyword parameters are not allowed: #{type}" \
      unless [:req, :opt].include? type

    name || "p#{i}"
  end

  register_native_callback(name.to_sym, to_method(body), params);
end

#evaluate(jsonnet, filename: "(jsonnet)", multi: false) ⇒ String

Note:

It is recommended to encode the source string in UTF-8 because Jsonnet expects it is ASCII-compatible, the result JSON string shall be UTF-8,16,32 according to RFC 7159 thus the only intersection between the requirements is UTF-8.

Evaluates Jsonnet source.

Parameters:

  • jsonnet (String)

    Jsonnet source string. Must be encoded in an ASCII-compatible encoding.

  • filename (String) (defaults to: "(jsonnet)")

    filename of the source. Used in stacktrace.

  • multi (Boolean) (defaults to: false)

    enables multi-mode

Returns:

  • (String)

    a JSON representation of the evaluation result

Raises:



72
73
74
# File 'lib/jsonnet/vm.rb', line 72

def evaluate(jsonnet, filename: "(jsonnet)", multi: false)
  eval_snippet(jsonnet, filename, multi)
end

#evaluate_file(filename, encoding: Encoding.default_external, multi: false) ⇒ String

Note:

It is recommended to encode the source file in UTF-8 because Jsonnet expects it is ASCII-compatible, the result JSON string shall be UTF-8,16,32 according to RFC 7159 thus the only intersection between the requirements is UTF-8.

Evaluates Jsonnet file.

Parameters:

  • filename (String)

    filename of a Jsonnet source file.

  • multi (Boolean) (defaults to: false)

    enables multi-mode

Returns:

  • (String)

    a JSON representation of the evaluation result

Raises:



87
88
89
# File 'lib/jsonnet/vm.rb', line 87

def evaluate_file(filename, encoding: Encoding.default_external, multi: false)
  eval_file(filename, encoding, multi)
end

#ext_code(key, code) ⇒ Object

Binds an external variable to a code fragment.

Parameters:

  • key (String)

    name of the variable

  • code (String)

    Jsonnet expression



172
173
174
175
176
177
# File 'ext/jsonnet/vm.c', line 172

static VALUE
vm_ext_code(VALUE self, VALUE key, VALUE code)
{
    vm_bind_variable(ext_code, self, key, code);
    return Qnil;
}

#ext_var(key, val) ⇒ Object

Binds an external variable to a value.

Parameters:

  • key (String)

    name of the variable

  • val (String)

    the value



160
161
162
163
164
165
# File 'ext/jsonnet/vm.c', line 160

static VALUE
vm_ext_var(VALUE self, VALUE key, VALUE val)
{
    vm_bind_variable(ext_var, self, key, val);
    return Qnil;
}

#fmt_comment=(str) ⇒ Object



302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
# File 'ext/jsonnet/vm.c', line 302

static VALUE
vm_set_fmt_comment(VALUE self, VALUE str)
{
    const char *ptr;
    struct jsonnet_vm_wrap *vm = rubyjsonnet_obj_to_vm(self);
    StringValue(str);
    if (RSTRING_LEN(str) != 1) {
	rb_raise(rb_eArgError, "fmt_comment must have a length of 1");
    }
    ptr = RSTRING_PTR(str);
    switch (*ptr) {
	case 'h':
	case 's':
	case 'l':
	    jsonnet_fmt_comment(vm->vm, *ptr);
	    return str;
	default:
	    rb_raise(rb_eArgError, "fmt_comment only accepts 'h', 's', or 'l'");
    }
}

#fmt_indent=(val) ⇒ Object



265
266
267
268
269
270
271
# File 'ext/jsonnet/vm.c', line 265

static VALUE
vm_set_fmt_indent(VALUE self, VALUE val)
{
    struct jsonnet_vm_wrap *vm = rubyjsonnet_obj_to_vm(self);
    jsonnet_fmt_indent(vm->vm, NUM2INT(val));
    return val;
}

#fmt_max_blank_lines=(val) ⇒ Object



273
274
275
276
277
278
279
# File 'ext/jsonnet/vm.c', line 273

static VALUE
vm_set_fmt_max_blank_lines(VALUE self, VALUE val)
{
    struct jsonnet_vm_wrap *vm = rubyjsonnet_obj_to_vm(self);
    jsonnet_fmt_max_blank_lines(vm->vm, NUM2INT(val));
    return val;
}

#fmt_pad_arrays=(val) ⇒ Object



323
324
325
326
327
328
329
# File 'ext/jsonnet/vm.c', line 323

static VALUE
vm_set_fmt_pad_arrays(VALUE self, VALUE val)
{
    struct jsonnet_vm_wrap *vm = rubyjsonnet_obj_to_vm(self);
    jsonnet_fmt_pad_objects(vm->vm, RTEST(val) ? 1 : 0);
    return val;
}

#fmt_pad_objects=(val) ⇒ Object



331
332
333
334
335
336
337
# File 'ext/jsonnet/vm.c', line 331

static VALUE
vm_set_fmt_pad_objects(VALUE self, VALUE val)
{
    struct jsonnet_vm_wrap *vm = rubyjsonnet_obj_to_vm(self);
    jsonnet_fmt_pad_objects(vm->vm, RTEST(val) ? 1 : 0);
    return val;
}

#fmt_pretty_field_names=(val) ⇒ Object



339
340
341
342
343
344
345
# File 'ext/jsonnet/vm.c', line 339

static VALUE
vm_set_fmt_pretty_field_names(VALUE self, VALUE val)
{
    struct jsonnet_vm_wrap *vm = rubyjsonnet_obj_to_vm(self);
    jsonnet_fmt_pretty_field_names(vm->vm, RTEST(val) ? 1 : 0);
    return val;
}

#fmt_sort_imports=(val) ⇒ Object



347
348
349
350
351
352
353
# File 'ext/jsonnet/vm.c', line 347

static VALUE
vm_set_fmt_sort_imports(VALUE self, VALUE val)
{
    struct jsonnet_vm_wrap *vm = rubyjsonnet_obj_to_vm(self);
    jsonnet_fmt_sort_imports(vm->vm, RTEST(val) ? 1 : 0);
    return val;
}

#fmt_string=(str) ⇒ Object



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'ext/jsonnet/vm.c', line 281

static VALUE
vm_set_fmt_string(VALUE self, VALUE str)
{
    const char *ptr;
    struct jsonnet_vm_wrap *vm = rubyjsonnet_obj_to_vm(self);
    StringValue(str);
    if (RSTRING_LEN(str) != 1) {
	rb_raise(rb_eArgError, "fmt_string must have a length of 1");
    }
    ptr = RSTRING_PTR(str);
    switch (*ptr) {
	case 'd':
	case 's':
	case 'l':
	    jsonnet_fmt_string(vm->vm, *ptr);
	    return str;
	default:
	    rb_raise(rb_eArgError, "fmt_string only accepts 'd', 's', or 'l'");
    }
}

#format(jsonnet, filename: "(jsonnet)") ⇒ String

Format Jsonnet snippet.

Parameters:

  • jsonnet (String)

    Jsonnet source string. Must be encoded in ASCII-compatible encoding.

  • filename (String) (defaults to: "(jsonnet)")

    filename of the source. Used in stacktrace.

Returns:

  • (String)

    a formatted Jsonnet representation

Raises:



109
110
111
# File 'lib/jsonnet/vm.rb', line 109

def format(jsonnet, filename: "(jsonnet)")
  fmt_snippet(jsonnet, filename)
end

#format_file(filename, encoding: Encoding.default_external) ⇒ String

Format Jsonnet file.

Parameters:

  • filename (String)

    filename of a Jsonnet source file.

Returns:

  • (String)

    a formatted Jsonnet representation

Raises:

  • (FormatError)

    raised when the formatting results an error.



97
98
99
# File 'lib/jsonnet/vm.rb', line 97

def format_file(filename, encoding: Encoding.default_external)
  fmt_file(filename, encoding)
end

#gc_growth_trigger=(val) ⇒ Object



236
237
238
239
240
241
242
# File 'ext/jsonnet/vm.c', line 236

static VALUE
vm_set_gc_growth_trigger(VALUE self, VALUE val)
{
    struct jsonnet_vm_wrap *vm = rubyjsonnet_obj_to_vm(self);
    jsonnet_gc_growth_trigger(vm->vm, NUM2DBL(val));
    return Qnil;
}

#gc_min_objects=(val) ⇒ Object



228
229
230
231
232
233
234
# File 'ext/jsonnet/vm.c', line 228

static VALUE
vm_set_gc_min_objects(VALUE self, VALUE val)
{
    struct jsonnet_vm_wrap *vm = rubyjsonnet_obj_to_vm(self);
    jsonnet_gc_min_objects(vm->vm, NUM2UINT(val));
    return Qnil;
}

#handle_import {|base, rel| ... } ⇒ Object

Lets the given block handle “import” expression of Jsonnet.

Yield Parameters:

  • base (String)

    base path to resolve “rel” from.

  • rel (String)

    a relative or absolute path to the file to be imported

Yield Returns:

  • (Array<String>)

    a pair of the content of the imported file and its path.



119
120
121
122
123
124
125
# File 'lib/jsonnet/vm.rb', line 119

def handle_import(&block)
  if block.nil?
    raise ArgumentError, 'handle_import requires a block'
  end
  self.import_callback = to_method(block)
  nil
end

#import_callback=(callback) ⇒ Object

Sets a custom way to resolve “import” expression.

Parameters:

  • callback (#call)

    receives two parameters and returns two values. The first parameter “base” is a base directory to resolve “rel” from. The second parameter “rel” is an absolute or a relative path to the file to import. The first return value is the content of the imported file. The second return value is the resolved path of the imported file.



162
163
164
165
166
167
168
169
170
171
# File 'ext/jsonnet/callbacks.c', line 162

static VALUE
vm_set_import_callback(VALUE self, VALUE callback)
{
    struct jsonnet_vm_wrap *const vm = rubyjsonnet_obj_to_vm(self);

    vm->import_callback = callback;
    jsonnet_import_callback(vm->vm, import_callback_entrypoint, vm);

    return callback;
}

#jpath_add(*args) ⇒ Object

Adds library search paths



206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'ext/jsonnet/vm.c', line 206

static VALUE
vm_jpath_add_m(int argc, const VALUE *argv, VALUE self)
{
    int i;
    struct jsonnet_vm_wrap *vm = rubyjsonnet_obj_to_vm(self);

    for (i = 0; i < argc; ++i) {
	VALUE jpath = argv[i];
	FilePathValue(jpath);
	jsonnet_jpath_add(vm->vm, StringValueCStr(jpath));
    }
    return Qnil;
}

#max_stack=(val) ⇒ Object



220
221
222
223
224
225
226
# File 'ext/jsonnet/vm.c', line 220

static VALUE
vm_set_max_stack(VALUE self, VALUE val)
{
    struct jsonnet_vm_wrap *vm = rubyjsonnet_obj_to_vm(self);
    jsonnet_max_stack(vm->vm, NUM2UINT(val));
    return Qnil;
}

#max_trace=(val) ⇒ Object



257
258
259
260
261
262
263
# File 'ext/jsonnet/vm.c', line 257

static VALUE
vm_set_max_trace(VALUE self, VALUE val)
{
    struct jsonnet_vm_wrap *vm = rubyjsonnet_obj_to_vm(self);
    jsonnet_max_trace(vm->vm, NUM2UINT(val));
    return Qnil;
}

#string_output=(val) ⇒ Object

Let #evaluate and #evaluate_file return a raw String instead of JSON-encoded string if val is true

Parameters:

  • val (Boolean)


249
250
251
252
253
254
255
# File 'ext/jsonnet/vm.c', line 249

static VALUE
vm_set_string_output(VALUE self, VALUE val)
{
    struct jsonnet_vm_wrap *vm = rubyjsonnet_obj_to_vm(self);
    jsonnet_string_output(vm->vm, RTEST(val));
    return Qnil;
}

#tla_code(key, code) ⇒ Object

Binds a top-level argument to a code fragment.

Parameters:

  • key (String)

    name of the variable

  • code (String)

    Jsonnet expression



196
197
198
199
200
201
# File 'ext/jsonnet/vm.c', line 196

static VALUE
vm_tla_code(VALUE self, VALUE key, VALUE code)
{
    vm_bind_variable(tla_code, self, key, code);
    return Qnil;
}

#tla_var(key, val) ⇒ Object

Binds a top-level argument to a value.

Parameters:

  • key (String)

    name of the variable

  • val (String)

    the value



184
185
186
187
188
189
# File 'ext/jsonnet/vm.c', line 184

static VALUE
vm_tla_var(VALUE self, VALUE key, VALUE val)
{
    vm_bind_variable(tla_var, self, key, val);
    return Qnil;
}