Class: Jsonnet::VM

Inherits:
Data
  • 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



57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'ext/jsonnet/vm.c', line 57

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



170
171
172
173
174
175
# File 'ext/jsonnet/vm.c', line 170

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



158
159
160
161
162
163
# File 'ext/jsonnet/vm.c', line 158

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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)


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

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



194
195
196
197
198
199
# File 'ext/jsonnet/vm.c', line 194

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



182
183
184
185
186
187
# File 'ext/jsonnet/vm.c', line 182

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