The FFI type#

Warning

Crochet’s FFI currently assumes trusted modules, and it’ll most likely evolve into an Alien-based layer that allows a more nuanced view of security and permits safe sandboxing at a lower cost.

Native modules receive a single argument, an FFI object purposely constructed for that package alone—which ensures that the interaction between the VM and the native module are still bound to the same capabilities that the package itself is.

Though, that said, until Crochet can sandbox JavaScript code, this does not provide many guarantees.

Defining functions#

ffi.defun(name, fn)#
Arguments:
  • name (string()) – The name of the foreign function.

  • fn (((CrochetValue[]) => CrochetValue)()) – The foreign function implementation.

Defines a simple, synchronous foreign function. The return must be a Crochet value.

ffi.defmachine(name, machine)#
Arguments:
  • name (string()) – The name of the foreign function.

  • machine (((CrochetValue[]) => Generator(NativeSignal, CrochetValue, CrochetValue))()) – The foreign function implementation.

Defines a complex foreign function which can interact with the Crochet VM by yielding native signals (provided by this object). All intermediate values must be Crochet values.

Constructing Crochet data#

ffi.integer(x)#
Arguments:
  • x (bigint()) – The number.

Converts a JavaScript bigint value to a Crochet integer.

ffi.float(x)#
Arguments:
  • x (number()) – The number.

Converts a JavaScript number value to a Crochet float.

ffi.boolean(x)#
Arguments:

Converts a JavaScript boolean value to a Crochet boolean.

ffi.text(x)#
Arguments:
  • x (string()) – The text.

Converts a JavaScript string to a Crochet text value. This always yields a dynamic text.

ffi.box(x)#
Arguments:
  • x – The arbitrary value to box.

Converts any JavaScript value to an opaque Crochet box. This box can be passed around in Crochet but never opened by Crochet code. It must be paired with ffi.unbox() in order to extract and use its value.

ffi.list(x)#
Arguments:
  • x (CrochetValue[]()) – The list.

Converts a JavaScript array to a Crochet list. The items of this array must already be Crochet values.

ffi.record(x)#
Arguments:
  • x (Map(string, CrochetValue)()) – The record.

Converts a restricted JavaScript map to a Crochet record. All keys in the map must be strings, and all values must already be Crochet values.

ffi.interpolation(x)#
Arguments:
  • x (CrochetValue[]()) – The parts of the interpolation.

Converts a list of interpolation parts to a Crochet interpolation. All parts of the interpolation will be dynamic.

ffi.nothing()#

Returns the special nothing value.

ffi.true()#

Returns the special true value.

ffi.false()#

Returns the special false value.

ffi.from_plain_native(x)#

Constructs a Crochet value from a plain JavaScript value, recursively. Note that this follows the same restrictions as the constructors above—records must be maps.

Using Crochet values#

ffi.integer_to_bigint(x)#

Converts a Crochet integer to a JavaScript bigint.

ffi.float_to_number(x)#

Converts a Crochet float to a JavaScript number.

ffi.to_js_boolean(x)#

Converts a Crochet boolean to a JavaScript boolean.

ffi.text_to_string(x)#

Converts a Crochet text (any trusted text) to a JavaScript string.

ffi.list_to_array(x)#

Converts a Crochet list to a JavaScript array.

ffi.interpolation_to_parts(x)#

Converts a Crochet interpolation to a list of parts. Literal parts in the interpolation are represented as JavaScript strings in the resulting array. Everything else is represented as a Crochet value.

ffi.record_to_map(x)#

Converts a Crochet record to a JavaScript map.

ffi.unbox(x)#

Takes the value out of a Crochet box. It’s up to the caller of this function to verify that the value is indeed what they expect, type-wise.

ffi.to_plain_native(x)#

Converts an arbitrary Crochet value to a plain JavaScript value, as if by one of the destructors above. Boxed values are not handled here. And records are always converted to JavaScript maps.

Native signals#

ffi.invoke(name, args)#
Arguments:
  • name (string()) – The string representation of the command’s signature.

  • args (CrochetValue[]()) – The arguments to provide the command.

Returns a native signal that causes the VM to invoke the specified command with the native module’s package’s capabilities.

ffi.apply(fn, args)#
Arguments:
  • fn (CrochetValue()) – The Crochet delayed program to apply.

  • args (CrochetValue[]()) – The arguments to provide the delayed program with.

Returns a native signal that causes the VM to apply a delayed Crochet program (lambdas or partials) to the given arguments.

ffi.await(promise)#
Arguments:
  • promise (Promise(CrochetValue)()) – The promise to wait for.

Returns a native signal that causes the VM to wait the promise to be successfully settled before continuing the execution of the machine with its resolved value.

Operators#

ffi.intrinsic_equals(x, y)#
Arguments:
  • x (CrochetValue()) –

  • y (CrochetValue()) –

True if x and y are equal according to Crochet’s intrinsic equality algorithm.

ffi.panic(tag, message)#
Arguments:
  • tag (string()) – A special mark to add to the panic message (e.g.: an unique name to the error).

  • message (string()) – The panic message.

Stops the program with a panic message. This error cannot be caught in Crochet code.

Testing values#

ffi.is_crochet_value(x)#

True if x is a Crochet value.