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

.new(*args) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'ext/jsonnet/vm.c', line 61

static VALUE
vm_s_new(int argc, const VALUE *argv, VALUE klass)
{
    struct jsonnet_vm_wrap *vm;
    VALUE self = TypedData_Make_Struct(cVM, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
    vm->vm = jsonnet_make();
    vm->import_callback = Qnil;
    vm->native_callbacks.len = 0;
    vm->native_callbacks.contexts = NULL;

    rb_obj_call_init(self, argc, argv);
    return self;
}

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



174
175
176
177
178
179
# File 'ext/jsonnet/vm.c', line 174

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



162
163
164
165
166
167
# File 'ext/jsonnet/vm.c', line 162

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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.



138
139
140
141
142
143
144
145
146
147
# File 'ext/jsonnet/callbacks.c', line 138

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



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

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



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

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



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

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)


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

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



198
199
200
201
202
203
# File 'ext/jsonnet/vm.c', line 198

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



186
187
188
189
190
191
# File 'ext/jsonnet/vm.c', line 186

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