Class: LexerKit::IR::JumpTable

Inherits:
Object
  • Object
show all
Defined in:
lib/lexer_kit/ir/jump_table.rb

Overview

JumpTable for SWITCH_BYTE instruction. Maps bytes to instruction offsets.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(entries:, default_offset:) ⇒ JumpTable

Returns a new instance of JumpTable.

Parameters:

  • entries (Hash<Integer, Integer>)

    byte → offset mapping

  • default_offset (Integer)

    offset for unmatched bytes



12
13
14
15
# File 'lib/lexer_kit/ir/jump_table.rb', line 12

def initialize(entries:, default_offset:)
  @entries = entries.freeze
  @default_offset = default_offset
end

Instance Attribute Details

#default_offsetObject (readonly)

Returns the value of attribute default_offset.



8
9
10
# File 'lib/lexer_kit/ir/jump_table.rb', line 8

def default_offset
  @default_offset
end

#entriesObject (readonly)

Returns the value of attribute entries.



8
9
10
# File 'lib/lexer_kit/ir/jump_table.rb', line 8

def entries
  @entries
end

Class Method Details

.from_binary(bytes) ⇒ Array(JumpTable, Integer)

Decode from binary

Parameters:

  • bytes (String)

Returns:

  • (Array(JumpTable, Integer))
    table, bytes_consumed


55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/lexer_kit/ir/jump_table.rb', line 55

def self.from_binary(bytes)
  pos = 0

  d1, d2, d3 = bytes.byteslice(pos, 3).unpack("C3")
  default_offset = (d1 << 16) | (d2 << 8) | d3
  pos += 3

  entry_count = bytes.byteslice(pos, 2).unpack1("S>")
  pos += 2

  entries = {}
  entry_count.times do
    byte, o1, o2, o3 = bytes.byteslice(pos, 4).unpack("C4")
    offset = (o1 << 16) | (o2 << 8) | o3
    entries[byte] = offset
    pos += 4
  end

  [new(entries: entries, default_offset: default_offset), pos]
end

Instance Method Details

#inspectObject



76
77
78
# File 'lib/lexer_kit/ir/jump_table.rb', line 76

def inspect
  "#<JumpTable entries=#{@entries.size} default=#{@default_offset}>"
end

#lookup(byte) ⇒ Integer

Get offset for a byte

Parameters:

  • byte (Integer)

Returns:

  • (Integer)

    instruction offset



20
21
22
# File 'lib/lexer_kit/ir/jump_table.rb', line 20

def lookup(byte)
  @entries[byte] || @default_offset
end

#to_binaryString

Encode to binary

Returns:

  • (String)


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/lexer_kit/ir/jump_table.rb', line 26

def to_binary
  parts = []

  # Default offset (u24)
  parts << [
    (@default_offset >> 16) & 0xFF,
    (@default_offset >> 8) & 0xFF,
    @default_offset & 0xFF
  ].pack("C3")

  # Entry count (u16)
  parts << [@entries.size].pack("S>")

  # Entries: [byte (u8), offset (u24)] pairs
  @entries.each do |byte, offset|
    parts << [
      byte,
      (offset >> 16) & 0xFF,
      (offset >> 8) & 0xFF,
      offset & 0xFF
    ].pack("C4")
  end

  parts.join
end

#to_native_formatHash

Convert to format suitable for C native loading Returns dense 256-entry lookup table for O(1) access

Returns:

  • (Hash)

    data for C extension



83
84
85
86
87
88
89
90
91
# File 'lib/lexer_kit/ir/jump_table.rb', line 83

def to_native_format
  # Build dense lookup table: all 256 bytes → offset
  lookup = Array.new(256, @default_offset)
  @entries.each { |byte, offset| lookup[byte] = offset }
  {
    lookup: lookup.pack("L>*"), # 256 * 4 = 1024 bytes
    default_offset: @default_offset # For EOF case
  }
end