### ----------------------------------------------------
### -- MoarVM::Bytecode
### -- Licenses: Artistic-2.0
### -- Authors: Elizabeth Mattijsen
### -- File: lib/MoarVM/Bytecode.rakumod
### ----------------------------------------------------
### -- Chunk 2 of 2
) }
    method uint16s(uint $offset is copy, uint $entries = 16) {
        my $bytecode := $!bytecode;
        my uint16 @values;
        for ^$entries {
            @values.push: $bytecode.read-uint16($offset, LE);
            $offset = $offset + 2;
        }
        @values
    }

    method uint32(uint $offset) { $!bytecode.read-uint32($offset, LE) }
    method uint32s(uint $offset is copy, uint $entries = 16) {
        my $bytecode := $!bytecode;
        my uint32 @values;
        for ^$entries {
            @values.push: $bytecode.read-uint32($offset, LE);
            $offset = $offset + 4;
        }
        @values
    }

    method str(uint $offset) {
        $!strings[$!bytecode.read-uint32($offset, LE)]
    }

    method slice(uint $offset, uint $bytes = 256) {
        $!bytecode[$offset ..^ $offset + $bytes]
    }

    method subbuf(
      uint $offset,
      uint $bytes = $!bytecode.elems - $offset
    ) {
        $!bytecode.subbuf($offset, $bytes)
    }

    method opcodes() {
        $!bytecode.subbuf(self.opcodes-offset, self.opcodes-length)
    }

    multi method hexdump(Int:D $offset, Int:D $bytes = 256) {
        dumphex($!bytecode, $offset, $bytes)
    }
    multi method hexdump(
      Buf:D $bytecode, Int:D $offset = 0; Int:D $bytes = 256
    ) {
        dumphex($bytecode, $offset, $bytes)
    }

    method rootdir() { $*EXECUTABLE.parent(3) }

    method setting(str $version = "c") {
        my $filename = "CORE.$version.setting.moarvm";
        paths(self.rootdir, :file(* eq $filename)).sort.head
    }

    method files(:$instantiate) {
        my @paths = paths(self.rootdir, :file(*.ends-with(".moarvm"))).sort;
        $instantiate
          ?? @paths.map({ self.new($_) })
          !! @paths
    }

    multi method gist(MoarVM::Bytecode:D:) {
        my str @parts = $!path ?? "File: $!path" !! "Created from a Blob";
        @parts.push: "Size: $!bytecode.elems() bytes";

        @parts.push: "Opcodes: " ~ self.opcodes-length ~ " bytes";
        @parts.push: $!strings.gist;
        @parts.push: $!frames.gist;
        if @!callsites.elems -> $elems {
            @parts.push: "Call sites: $elems";
        }

        if @!extension-ops -> @ops {
            @parts.push: "Extension Ops: @ops.elems()";
            @parts.push: "  $_.gist()" for @ops;
        }
        else {
            @parts.push: "Extension Ops: none";
        }

        if @!sc-dependencies -> @deps {
            @parts.push: "Serialization context dependencies: @deps.elems()";
            @parts.push: "  $_" for @deps;
        }
        else {
            @parts.push: "Serialization context dependencies: none";
        }

        if self.coverables.sort(*.key) -> @coverables {
            my $entries := self.annotation-data-length / 12;
            my $lines   := @coverables.map(*.value.elems).sum;
            @parts.push: "Coverable keys: @coverables.elems() from $lines lines ($entries annotations)";
            @parts.push: "  $_.key(): $_.value.elems()"
              for @coverables;
        }

        @parts.join("\n")
    }
}

#- setting ^ver ^auth ^api -----------------------------------------------------

use META::verauthapi:ver<0.0.1+>:auth<zef:lizmat> $?DISTRIBUTION,
  MoarVM::Bytecode,
  MoarVM::Op,
;

# vim: expandtab shiftwidth=4


