Skip to content

Using the Moirai Kotlin API

sithys edited this page Feb 20, 2024 · 7 revisions

Execution Strategies

There are two general strategies for executing scripts.

  1. The first strategy is the clean, full topological sort strategy. It is very expensive and is unsuited for production environments.
  2. The second strategy is to store Library scripts in a cache, and then only ever execute Transient and Pure Transient scripts using the eval method.

Examples

The best place to find examples is TestUtils.kt which contains the following methods:

  1. testEval: This demonstrates the first (slower) execution strategy.
  2. testGradual: This demonstrates the second (cache aware) execution strategy.

The Public API

In the Kotlin programming language, the internal keyword is used to prevent external libraries from accessing symbols (technically in Java Bytecode it is still possible to see and invoke the missing symbols). The internal keyword is used extensively throughout the Moirai code base to prevent mutable or confusing data structures from being exposed to end users.

Moirai exposes the following public API in the Kotlin library, when imported:

  • ScriptType.kt
  • ExecutionCache.kt
  • SourceStore.kt
  • Architecture.kt
  • Errors.kt
  • CompilerFrontend.kt
  • Value.kt
  • Eval.kt

Requirements to Execute a Script

Users who are new to the Moirai Programming Language may be surprised to find out that the eval method in Eval.kt requires certain interfaces to be implemented by the user. No useful default implementations are provided.

ExecutionCache

This interface abstracts the concept of in-memory caching of semantic artifacts. Note that semantic artifact formats are defined using the internal keyword in Kotlin and are therefore unable to be serialized by end users for the purpose of storing them out-of-memory. With this cache in place, Transient Scripts are able to be executed very quickly by importing the pre-compiled symbols (for the single import) from the cache. The exact strategy is left up to the implementer, for example Least Recently Used (LRU) might produce good performance for most users.

SourceStore

This interface abstracts the concept of storing source code out-of-memory, for example on the hard disk, in a database, or to be furnished by an external web service.

Architecture

This interface is used during the total cost calculations for a script. It defines two fields:

  • defaultNodeCost: A long integer literal that is used to represent computations that have a cost of exactly one on your platform. Every AST node in the tree will have at least this cost.
  • costUpperLimit: A long integer literal that is used to represent the upper bound of the cost of a script. If the cost calculation phase of the compiler exceeds this limit, the computation will immediately be rejected.

The long integers which would be appropriate depend entirely on how Moirai is being used, and on the performance characteristics of the physical hardware where the Moirai interpreter is executing. The end user is encouraged to use statistics from actual customer traffic when determining these numbers when used in production environments.

Clone this wiki locally