aver-lang 0.26.0

VM and transpiler for Aver, a statically-typed language designed for AI-assisted development
Documentation

        (module
          {decls}
          {func_pad}
          (func (export "helper") (param $s (ref null $string)) (result (ref null $result))
            (local $len i32) (local $idx i32) (local $start i32)
            (local $negative i32) (local $saw_digit i32)
            (local $ch i32) (local $digit i64)
            (local $rm (ref null $mag)) (local $mlen i32)
            (local $i i32) (local $carry i64) (local $cur i64)
            (local $err (ref null $string))
            ;; normalize epilogue scratch
            (local $rs i32) (local $rlen i32) (local $lo i64) (local $hi i64)
            (local $tmpm (ref null $mag))

            (local.set $len (array.len (local.get $s)))

            ;; Empty input → Err.
            (if (i32.eqz (local.get $len))
              (then
                {err_build}
                return))

            ;; Optional single leading '+' / '-'.
            (local.set $start (i32.const 0))
            (local.set $ch (array.get_u $string (local.get $s) (i32.const 0)))
            (if (i32.eq (local.get $ch) (i32.const 0x2D))
              (then
                (local.set $negative (i32.const 1))
                (local.set $start (i32.const 1)))
              (else
                (if (i32.eq (local.get $ch) (i32.const 0x2B))
                  (then (local.set $start (i32.const 1))))))

            ;; Magnitude accumulator: ceil(len/8)+2 limbs holds any decimal
            ;; (each 32-bit limb absorbs >9 decimal digits; len/8+2 is a
            ;; safe over-estimate). 32-bit-in-i64 limbs keep mul*10+digit
            ;; exact (max limb value < 2^32, so limb*10+9 < 2^36 < 2^64).
            (local.set $mlen (i32.add (i32.div_u (local.get $len) (i32.const 8)) (i32.const 2)))
            (local.set $rm (array.new_default $mag (local.get $mlen)))

            (local.set $idx (local.get $start))
            (block $loop_done (loop $loop
              (br_if $loop_done (i32.ge_u (local.get $idx) (local.get $len)))
              (local.set $ch (array.get_u $string (local.get $s) (local.get $idx)))
              ;; Reject any non-digit byte → Err.
              (if (i32.or (i32.lt_u (local.get $ch) (i32.const 0x30))
                          (i32.gt_u (local.get $ch) (i32.const 0x39)))
                (then
                  {err_build}
                  return))
              (local.set $saw_digit (i32.const 1))
              (local.set $digit (i64.extend_i32_u (i32.sub (local.get $ch) (i32.const 0x30))))
              ;; rm = rm*10 + digit  (little-endian limb multiply-add)
              (local.set $carry (local.get $digit))
              (local.set $i (i32.const 0))
              (block $ma_done (loop $ma
                (br_if $ma_done (i32.ge_u (local.get $i) (local.get $mlen)))
                (local.set $cur (i64.add
                  (i64.mul (array.get $mag (local.get $rm) (local.get $i)) (i64.const 10))
                  (local.get $carry)))
                (array.set $mag (local.get $rm) (local.get $i) (i64.and (local.get $cur) (i64.const 0xffffffff)))
                (local.set $carry (i64.shr_u (local.get $cur) (i64.const 32)))
                (local.set $i (i32.add (local.get $i) (i32.const 1)))
                (br $ma)))
              (local.set $idx (i32.add (local.get $idx) (i32.const 1)))
              (br $loop)))

            ;; No digit consumed (empty, lone '+'/'-') → Err.
            (if (i32.eqz (local.get $saw_digit))
              (then
                {err_build}
                return))

            ;; Sign for normalize: -1 if negative else +1 (normalize maps a
            ;; zero magnitude to canonical Small(0) regardless of sign).
            (local.set $rs (if (result i32) (local.get $negative) (then (i32.const -1)) (else (i32.const 1))))

            ;; tag 1 (Ok), ok = normalized $aint, null err.
            (i32.const 1)
            {norm}
            (ref.null $string)
            (struct.new $result)))