aver-lang 0.15.2

VM and transpiler for Aver, a statically-typed language designed for AI-assisted development
Documentation
;; 8-bit byte ↔ two-character hex string. Both return Result<…,…>:
;; rt_byte_to_hex returns Result<String, String> (Err on out-of-range);
;; rt_byte_from_hex returns Result<Int, String> (Err on bad input).
;; The error path always carries an empty OBJ_STRING.

(func $rt_byte_to_hex (param $n i64) (result i32)
  (local $byte i32)
  (local $ptr i32)
  (local $nibble i32)

  ;; Range check: n < 0 || n > 255 → Err("")
  local.get $n
  i64.const 0
  i64.lt_s
  local.get $n
  i64.const 255
  i64.gt_s
  i32.or
  if
    ;; alloc empty OBJ_STRING (8 bytes header, no payload)
    i32.const 8
    call $rt_alloc
    local.set $ptr
    local.get $ptr
    i64.const 0   ;; OBJ_STRING (0) << 56 | byte_len 0
    i64.store

    i32.const 1   ;; WRAP_ERR
    local.get $ptr
    i32.const 1
    call $rt_wrap_i32
    return
  end

  local.get $n
  i32.wrap_i64
  local.set $byte

  ;; alloc 2-byte OBJ_STRING (8 + align8(2) = 16 bytes)
  i32.const 16
  call $rt_alloc
  local.set $ptr
  local.get $ptr
  i64.const 2   ;; OBJ_STRING (0) << 56 | byte_len 2
  i64.store

  ;; high nibble at offset 8
  local.get $byte
  i32.const 4
  i32.shr_u
  i32.const 0xF
  i32.and
  local.set $nibble
  local.get $ptr
  local.get $nibble
  i32.const 10
  i32.lt_u
  if (result i32)
    local.get $nibble
    i32.const 0x30   ;; '0'
    i32.add
  else
    local.get $nibble
    i32.const 10
    i32.sub
    i32.const 0x61   ;; 'a'
    i32.add
  end
  i32.store8 offset=8

  ;; low nibble at offset 9
  local.get $byte
  i32.const 0xF
  i32.and
  local.set $nibble
  local.get $ptr
  local.get $nibble
  i32.const 10
  i32.lt_u
  if (result i32)
    local.get $nibble
    i32.const 0x30
    i32.add
  else
    local.get $nibble
    i32.const 10
    i32.sub
    i32.const 0x61
    i32.add
  end
  i32.store8 offset=9

  i32.const 0   ;; WRAP_OK
  local.get $ptr
  i32.const 1
  call $rt_wrap_i32
)
(export "rt_byte_to_hex" (func $rt_byte_to_hex))

(func $rt_byte_from_hex (param $str i32) (result i32)
  (local $len i32)
  (local $hi i32)
  (local $lo i32)
  (local $ch i32)
  (local $value i32)
  (local $err_ptr i32)

  ;; len = header.byte_len
  local.get $str
  i64.load
  i64.const 0xFFFFFFFF
  i64.and
  i32.wrap_i64
  local.set $len

  ;; len != 2 → Err("")
  local.get $len
  i32.const 2
  i32.ne
  if
    i32.const 8
    call $rt_alloc
    local.set $err_ptr
    local.get $err_ptr
    i64.const 0
    i64.store
    i32.const 1
    local.get $err_ptr
    i32.const 1
    call $rt_wrap_i32
    return
  end

  ;; hi nibble
  local.get $str
  i32.load8_u offset=8
  local.set $ch

  local.get $ch
  i32.const 0x30   ;; '0'
  i32.ge_u
  local.get $ch
  i32.const 0x39   ;; '9'
  i32.le_u
  i32.and
  if
    local.get $ch
    i32.const 0x30
    i32.sub
    local.set $hi
  else
    local.get $ch
    i32.const 0x61   ;; 'a'
    i32.ge_u
    local.get $ch
    i32.const 0x66   ;; 'f'
    i32.le_u
    i32.and
    if
      local.get $ch
      i32.const 0x61
      i32.sub
      i32.const 10
      i32.add
      local.set $hi
    else
      local.get $ch
      i32.const 0x41   ;; 'A'
      i32.ge_u
      local.get $ch
      i32.const 0x46   ;; 'F'
      i32.le_u
      i32.and
      if
        local.get $ch
        i32.const 0x41
        i32.sub
        i32.const 10
        i32.add
        local.set $hi
      else
        ;; bad nibble → Err("")
        i32.const 8
        call $rt_alloc
        local.set $err_ptr
        local.get $err_ptr
        i64.const 0
        i64.store
        i32.const 1
        local.get $err_ptr
        i32.const 1
        call $rt_wrap_i32
        return
      end
    end
  end

  ;; lo nibble
  local.get $str
  i32.load8_u offset=9
  local.set $ch

  local.get $ch
  i32.const 0x30
  i32.ge_u
  local.get $ch
  i32.const 0x39
  i32.le_u
  i32.and
  if
    local.get $ch
    i32.const 0x30
    i32.sub
    local.set $lo
  else
    local.get $ch
    i32.const 0x61
    i32.ge_u
    local.get $ch
    i32.const 0x66
    i32.le_u
    i32.and
    if
      local.get $ch
      i32.const 0x61
      i32.sub
      i32.const 10
      i32.add
      local.set $lo
    else
      local.get $ch
      i32.const 0x41
      i32.ge_u
      local.get $ch
      i32.const 0x46
      i32.le_u
      i32.and
      if
        local.get $ch
        i32.const 0x41
        i32.sub
        i32.const 10
        i32.add
        local.set $lo
      else
        i32.const 8
        call $rt_alloc
        local.set $err_ptr
        local.get $err_ptr
        i64.const 0
        i64.store
        i32.const 1
        local.get $err_ptr
        i32.const 1
        call $rt_wrap_i32
        return
      end
    end
  end

  ;; value = (hi << 4) | lo
  local.get $hi
  i32.const 4
  i32.shl
  local.get $lo
  i32.or
  local.set $value

  ;; Wrap as Ok(value as i64), value_ptr_flag = 0
  i32.const 0   ;; WRAP_OK
  local.get $value
  i64.extend_i32_u
  i32.const 0
  call $rt_wrap
)
(export "rt_byte_from_hex" (func $rt_byte_from_hex))