q0idmation // draw, rig, animate, export .q0s log inregister

runtime and qvm

home · syntax · host api

from source to effect

source → parser → compiler → qvm bytecode → qvm → host actions → host

The parser turns source into a syntax tree and reports diagnostics with line numbers. The compiler turns the tree into qvm bytecode. qvm runs the bytecode and collects host actions: jumps, commands, rig changes and so on. qvm itself has no access to files, the editor or the player. The host decides which actions it carries out; see the availability table.

The shared runtime lives in q0s-format/src/q0lang/runtime.rs and qvm in q0vm/src/lib.rs. q0editor, q0player and q0shell all run code this way.

runtime state

One runtime keeps, between the scripts it runs:

  • shared variables;
  • imported libraries;
  • event subscriptions;
  • the signatures of public and private functions;
  • the compiled bodies of defined functions, so a function from the general script can be called by later frame code.

q0player keeps one shared runtime per movie and one more per placed copy of a symbol with an object script. Switching scenes keeps the shared runtime. Each runtime caches compiled source: a script that runs on every frame is compiled once.

values

valueholds
numbera 64-bit float; there is no separate integer type
stringUTF-8 text
booltrue or false
nullnothing
identthe text of a name that was never assigned
rawan internal leftover of some errors

The rules for operators, truthiness and conversion are in syntax.

host actions

actionmade byhost
GoRun(target), GoStop(target)gorun!, gostop!editor preview, player
ShellCommandq0shell.*!shell
SceneSwitchq0scene.switch!player
RigSetPosition, RigSetValue, RigReset, RigSetPose, RigResetPoseq0rig.*!player
Physics(...)q0physics.*!player
Particles(...)q0particles.*!player
Light(...)q0light.*!player

A target is either a frame index or a label string. Actions are collected while the script runs; the host applies them in order once it ends. Writes to host names such as player.x or self.x are read back the same way, after the script.

diagnostics

Every diagnostic carries the source line it came from. A parse or compile error that makes the program meaningless stops it before it runs. A runtime error, such as a type error, ends that run with a diagnostic; actions collected before it still apply. In q0player, diagnostics are warnings: the movie still opens and plays, and the status line summarises them. q0player keeps at most 256 of them.

limits

limitvalue
instructions per run100,000
instructions per run in the editor's code analysis4,096
operand stack4,096 values
call depth128 nested calls
nested expressions64 levels
nested blocks64 levels
frame and scene jumps in one chain64
active objects with scripts in q0player4,096

A run that hits the instruction limit stops with a diagnostic; an endless while therefore cannot freeze the player. A recursive function shares the budget of the run that called it.

bytecode

qvm bytecode starts with the magic QVM\0 and a version (currently 2), followed by a constant pool, the code and a table of source lines. Encoding is deterministic: the same program always gives the same bytes. Version 1 bytecode still loads. Opcodes 41, 42 and 43 carry the physics, particle and light commands and need a qvm that knows them.

the editor

The q0lang editor window analyses the script being edited with its own small budget. It shows diagnostics, how many statements the script has, the libraries it imports, and a summary of the actions, variables and event subscriptions one run produces. The editor preview runs real frame code; see host api.

Sources: q0s-format/src/q0lang/runtime.rs, q0s-format/src/q0lang/compiler.rs, q0vm/src/lib.rs, q0player/src/lib.rs, q0player/src/objects.rs, q0editor/src/q0lang/editor.rs.