2. Uxn Eval

Tuesday 28th July 2026

We have two stacks and some basic logic, 'all' we need now is an evaluate function that processes instructions held in the ram object and manipulates the two stacks.

eval(vector)

A main evaluate method (would be better called execute as it doesn't return? but we'll stick with the Uxn C reference naming). The vector argument specifies where in ram to start executing instructions.

fun eval(vector: Int) {

  //A vector of 0 represents a no-op, no handler ever exists at 0
  if (vector == 0) return
  
  programCounter = vector
  
  while (true) {
  
    //fetch next instruction
    val instruction: Int = ram[programCounter]
    
    //advance to next, wrap at 16bits so we never try and access an index outside of ram
    programCounter = (programCounter + 1) and 0xffff
    
    //We've added some Int extension methods for convenience:
    val opcode = instruction.opcode()
    val isKeep = instruction.isKeep()
    val isReturn = instruction.isReturn()
    val isShort = instruction.isShort()
    
    //Determine stack:
    sourceStack = if (isReturn) returnStack else workingStack
    destinationStack = if (isReturn) workingStack else returnStack
    
    sourceStack.beginInstruction(isKeep)
    
    //process opcode:
    ...
}

Int/opcode extensions

const val FLAG_SHORT = 0x20  // 2
const val FLAG_RETURN = 0x40 // r
const val FLAG_KEEP = 0x80   // k

fun Int.isShort(): Boolean = this and FLAG_SHORT != 0
fun Int.isReturn(): Boolean = this and FLAG_RETURN != 0
fun Int.isKeep(): Boolean = this and FLAG_KEEP != 0
fun Int.opcode(): Int = this and 0x1f

Process an opcode

fun eval(vector: Int) {

  ...
  
  sourceStack.beginInstruction(isKeep)
  
  when (opcode) {
    ADD -> {
        val b = sourceStack.pop(isShort)
        val a = sourceStack.pop(isShort) 
        sourceStack.push(a + b, isShort)
    }
  }
}