toolbox 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -31,15 +31,11 @@ class RBignumObject:
31
31
  return f"<T_BIGNUM@0x{addr:x} heap length={len(self)}>"
32
32
 
33
33
  def print_to(self, terminal):
34
- """Return formatted bignum representation."""
34
+ """Print formatted bignum representation."""
35
35
  addr = int(self.value)
36
36
  storage = "embedded" if self.is_embedded() else "heap"
37
- return terminal.print(
38
- format.metadata, '<',
39
- format.type, 'T_BIGNUM',
40
- format.metadata, f'@0x{addr:x} {storage} length={len(self)}>',
41
- format.reset
42
- )
37
+ details = f"{storage} length={len(self)}"
38
+ terminal.print_type_tag('T_BIGNUM', addr, details)
43
39
 
44
40
  def print_recursive(self, printer, depth):
45
41
  """Print this bignum (no recursion needed)."""
@@ -1,6 +1,6 @@
1
1
  import debugger
2
2
  import constants
3
- import value
3
+ import rvalue
4
4
  import rstring
5
5
 
6
6
  class RClass:
@@ -86,13 +86,13 @@ class RClass:
86
86
 
87
87
  # Strategy 2: Try modern rb_classext_struct.classpath (Ruby 3.4+)
88
88
  try:
89
- rclass = self.klass.cast(debugger.lookup_type('struct RClass').pointer())
89
+ rclass = self.klass.cast(constants.type_struct('struct RClass').pointer())
90
90
  # Try to access classext.classpath
91
91
  try:
92
92
  # Try embedded classext (RCLASS_EXT_EMBEDDED)
93
93
  rclass_size = debugger.parse_and_eval("sizeof(struct RClass)")
94
94
  classext_addr = int(self.klass) + int(rclass_size)
95
- classext_type = debugger.lookup_type('rb_classext_t')
95
+ classext_type = constants.type_struct('rb_classext_t')
96
96
  classext_ptr = debugger.create_value_from_address(classext_addr, classext_type).address
97
97
  classpath_val = classext_ptr['classpath']
98
98
  except:
@@ -103,9 +103,9 @@ class RClass:
103
103
  except:
104
104
  classpath_val = None
105
105
 
106
- if classpath_val and int(classpath_val) != 0 and not value.is_nil(classpath_val):
106
+ if classpath_val and int(classpath_val) != 0 and not rvalue.is_nil(classpath_val):
107
107
  # Decode the classpath string
108
- class_name_obj = value.interpret(classpath_val)
108
+ class_name_obj = rvalue.interpret(classpath_val)
109
109
  if hasattr(class_name_obj, 'to_str'):
110
110
  class_name = class_name_obj.to_str()
111
111
  if class_name and not class_name.startswith('<'):
@@ -14,7 +14,7 @@ data/toolbox/
14
14
  │ └── *.md # Documentation
15
15
 
16
16
  # Ruby debugging extensions (currently GDB-specific, migrating to abstraction)
17
- ├── object.py # Object inspection (rb-object-print)
17
+ ├── object.py # Object inspection (rb-print)
18
18
  ├── fiber.py # Fiber debugging (rb-fiber-scan-heap, rb-fiber-switch)
19
19
  ├── heap.py # Heap scanning (rb-heap-scan)
20
20
  ├── stack.py # Stack inspection
@@ -89,7 +89,7 @@ value_cast = value.cast(type.pointer())
89
89
  ### GDB
90
90
  ```bash
91
91
  gem install toolbox
92
- bake toolbox:gdb:install
92
+ bake -g toolbox toolbox:gdb:install
93
93
  ```
94
94
 
95
95
  This adds to `~/.gdbinit`:
@@ -101,7 +101,7 @@ source /path/to/gem/data/toolbox/init.py
101
101
  ### LLDB
102
102
  ```bash
103
103
  gem install toolbox
104
- bake toolbox:lldb:install
104
+ bake -g toolbox toolbox:lldb:install
105
105
  ```
106
106
 
107
107
  This adds to `~/.lldbinit`:
@@ -113,7 +113,7 @@ command script import /path/to/gem/data/toolbox/init.py
113
113
  ## Available Commands
114
114
 
115
115
  ### Object Inspection
116
- - `rb-object-print <expression> [--depth N]` - Print Ruby objects with recursion
116
+ - `rb-print <expression> [--depth N]` - Print Ruby objects with recursion
117
117
 
118
118
  ### Fiber Debugging
119
119
  - `rb-fiber-scan-heap [--limit N]` - Scan heap for fiber objects
@@ -125,7 +125,7 @@ command script import /path/to/gem/data/toolbox/init.py
125
125
  - `rb-heap-scan [--type TYPE] [--limit N]` - Scan Ruby heap for objects
126
126
 
127
127
  ### Stack Inspection
128
- - `rb-stack-print` - Print Ruby stack (coming soon)
128
+ - `rb-stack-trace` - Print combined Ruby/C stack trace
129
129
 
130
130
  ## Migration Status
131
131
 
@@ -151,14 +151,14 @@ command script import /path/to/gem/data/toolbox/init.py
151
151
  Test with GDB:
152
152
  ```bash
153
153
  gdb -q ruby
154
- (gdb) help rb-object-print
154
+ (gdb) help rb-print
155
155
  (gdb) help rb-fiber-scan-heap
156
156
  ```
157
157
 
158
158
  Test with LLDB (once migrated):
159
159
  ```bash
160
160
  lldb ruby
161
- (lldb) help rb-object-print
161
+ (lldb) help rb-print
162
162
  (lldb) help rb-fiber-scan-heap
163
163
  ```
164
164
 
@@ -192,7 +192,7 @@ if toolbox_dir not in sys.path:
192
192
  This allows:
193
193
  ```python
194
194
  import debugger # data/toolbox/debugger.py
195
- import object # data/toolbox/object.py
195
+ import print # data/toolbox/print.py
196
196
  import fiber # data/toolbox/fiber.py
197
197
  from debugger import gdb # data/toolbox/debugger/gdb.py
198
198
  ```
@@ -1,7 +1,7 @@
1
1
  import debugger
2
2
  import constants
3
3
  import format
4
- import value
4
+ import rvalue
5
5
  import rstring
6
6
  import rclass
7
7
 
@@ -21,7 +21,7 @@ class RException:
21
21
  self._message = None
22
22
 
23
23
  # Validate it's an object
24
- if value.is_immediate(exception_value):
24
+ if rvalue.is_immediate(exception_value):
25
25
  raise ValueError("Exception VALUE cannot be an immediate value")
26
26
 
27
27
  @property
@@ -116,7 +116,7 @@ def is_exception(val):
116
116
  Returns:
117
117
  True if the value appears to be an exception object, False otherwise
118
118
  """
119
- if not value.is_object(val):
119
+ if not rvalue.is_object(val):
120
120
  return False
121
121
 
122
122
  try:
@@ -32,15 +32,10 @@ class RFloatImmediate:
32
32
  return f"<T_FLOAT> {self.float_value()}"
33
33
 
34
34
  def print_to(self, terminal):
35
- """Return formatted float representation."""
36
- tag = terminal.print(
37
- format.metadata, '<',
38
- format.type, 'T_FLOAT',
39
- format.metadata, '>',
40
- format.reset
41
- )
42
- num_val = terminal.print(format.number, str(self.float_value()), format.reset)
43
- return f"{tag} {num_val}"
35
+ """Print formatted float representation."""
36
+ terminal.print_type_tag('T_FLOAT')
37
+ terminal.print(' ', end='')
38
+ terminal.print(format.number, str(self.float_value()), format.reset, end='')
44
39
 
45
40
  def print_recursive(self, printer, depth):
46
41
  """Print this float (no recursion needed)."""
@@ -59,16 +54,11 @@ class RFloatObject:
59
54
  return f"<T_FLOAT@0x{addr:x}> {self.float_value()}"
60
55
 
61
56
  def print_to(self, terminal):
62
- """Return formatted float representation."""
57
+ """Print formatted float representation."""
63
58
  addr = int(self.value.address)
64
- tag = terminal.print(
65
- format.metadata, '<',
66
- format.type, 'T_FLOAT',
67
- format.metadata, f'@0x{addr:x}>',
68
- format.reset
69
- )
70
- num_val = terminal.print(format.number, str(self.float_value()), format.reset)
71
- return f"{tag} {num_val}"
59
+ terminal.print_type_tag('T_FLOAT', addr)
60
+ terminal.print(' ', end='')
61
+ terminal.print(format.number, str(self.float_value()), format.reset, end='')
72
62
 
73
63
  def print_recursive(self, printer, depth):
74
64
  """Print this float (no recursion needed)."""
@@ -51,12 +51,8 @@ class RHashSTTable(RHashBase):
51
51
  def print_to(self, terminal):
52
52
  """Print this hash with formatting."""
53
53
  addr = int(self.value)
54
- return terminal.print(
55
- format.metadata, '<',
56
- format.type, 'T_HASH',
57
- format.metadata, f'@0x{addr:x} ST-Table entries={self.size()}>',
58
- format.reset
59
- )
54
+ details = f"ST-Table entries={self.size()}"
55
+ terminal.print_type_tag('T_HASH', addr, details)
60
56
 
61
57
  def print_recursive(self, printer, depth):
62
58
  """Print this hash recursively."""
@@ -121,12 +117,8 @@ class RHashARTable(RHashBase):
121
117
  def print_to(self, terminal):
122
118
  """Print this hash with formatting."""
123
119
  addr = int(self.value)
124
- return terminal.print(
125
- format.metadata, '<',
126
- format.type, 'T_HASH',
127
- format.metadata, f'@0x{addr:x} AR-Table size={self.size()} bound={self.bound()}>',
128
- format.reset
129
- )
120
+ details = f"AR-Table size={self.size()} bound={self.bound()}"
121
+ terminal.print_type_tag('T_HASH', addr, details)
130
122
 
131
123
  def print_recursive(self, printer, depth):
132
124
  """Print this hash recursively."""
@@ -71,15 +71,11 @@ class RStringBase:
71
71
  addr = int(self.value)
72
72
  storage = "embedded" if self._is_embedded() else "heap"
73
73
  content = self.to_str()
74
- tag = terminal.print(
75
- format.metadata, '<',
76
- format.type, 'T_STRING',
77
- format.metadata, f'@0x{addr:x} {storage} length={self.length()}>',
78
- format.reset
79
- )
74
+ details = f"{storage} length={self.length()}"
75
+ terminal.print_type_tag('T_STRING', addr, details)
76
+ terminal.print(' ', end='')
80
77
  # Use repr() to properly escape quotes, newlines, etc.
81
- string_val = terminal.print(format.string, repr(content), format.reset)
82
- return f"{tag} {string_val}"
78
+ terminal.print(format.string, repr(content), format.reset, end='')
83
79
 
84
80
  def print_recursive(self, printer, depth):
85
81
  """Print this string (no recursion needed for strings)."""
@@ -60,14 +60,10 @@ class RStructEmbedded(RStructBase):
60
60
  return f"<T_STRUCT@0x{addr:x} embedded length={len(self)}>"
61
61
 
62
62
  def print_to(self, terminal):
63
- """Return formatted struct representation."""
63
+ """Print formatted struct representation."""
64
64
  addr = int(self.value)
65
- return terminal.print(
66
- format.metadata, '<',
67
- format.type, 'T_STRUCT',
68
- format.metadata, f'@0x{addr:x} embedded length={len(self)}>',
69
- format.reset
70
- )
65
+ details = f"embedded length={len(self)}"
66
+ terminal.print_type_tag('T_STRUCT', addr, details)
71
67
 
72
68
  def print_recursive(self, printer, depth):
73
69
  """Print this struct recursively."""
@@ -101,14 +97,10 @@ class RStructHeap(RStructBase):
101
97
  return f"<T_STRUCT@0x{addr:x} heap length={len(self)}>"
102
98
 
103
99
  def print_to(self, terminal):
104
- """Return formatted struct representation."""
100
+ """Print formatted struct representation."""
105
101
  addr = int(self.value)
106
- return terminal.print(
107
- format.metadata, '<',
108
- format.type, 'T_STRUCT',
109
- format.metadata, f'@0x{addr:x} heap length={len(self)}>',
110
- format.reset
111
- )
102
+ details = f"heap length={len(self)}"
103
+ terminal.print_type_tag('T_STRUCT', addr, details)
112
104
 
113
105
  def print_recursive(self, printer, depth):
114
106
  """Print this struct recursively."""
@@ -138,25 +138,13 @@ class RSymbolImmediate:
138
138
 
139
139
  def print_to(self, terminal):
140
140
  """Return formatted symbol representation."""
141
+ terminal.print_type_tag('T_SYMBOL')
142
+ terminal.print(' ', end='')
141
143
  name = self.to_str()
142
144
  if name:
143
- tag = terminal.print(
144
- format.metadata, '<',
145
- format.type, 'T_SYMBOL',
146
- format.metadata, '>',
147
- format.reset
148
- )
149
- symbol_val = terminal.print(format.symbol, f':{name}', format.reset)
150
- return f"{tag} {symbol_val}"
145
+ terminal.print(format.symbol, f':{name}', format.reset, end='')
151
146
  else:
152
- tag = terminal.print(
153
- format.metadata, '<',
154
- format.type, 'T_SYMBOL',
155
- format.metadata, '>',
156
- format.reset
157
- )
158
- symbol_val = terminal.print(format.symbol, f':id_0x{self.id():x}', format.reset)
159
- return f"{tag} {symbol_val}"
147
+ terminal.print(format.symbol, f':id_0x{self.id():x}', format.reset, end='')
160
148
 
161
149
  def print_recursive(self, printer, depth):
162
150
  """Print this symbol (no recursion needed)."""
@@ -208,28 +196,16 @@ class RSymbolObject:
208
196
  return f"<T_SYMBOL@0x{addr:x}> :<Symbol:0x{int(fstr_val):x}>"
209
197
 
210
198
  def print_to(self, terminal):
211
- """Return formatted symbol representation."""
199
+ """Print formatted symbol representation."""
212
200
  name = self.to_str()
213
201
  addr = int(self.value)
202
+ terminal.print_type_tag('T_SYMBOL', addr)
203
+ terminal.print(' ', end='')
214
204
  if name:
215
- tag = terminal.print(
216
- format.metadata, '<',
217
- format.type, 'T_SYMBOL',
218
- format.metadata, f'@0x{addr:x}>',
219
- format.reset
220
- )
221
- symbol_val = terminal.print(format.symbol, f':{name}', format.reset)
222
- return f"{tag} {symbol_val}"
205
+ terminal.print(format.symbol, f':{name}', format.reset, end='')
223
206
  else:
224
207
  fstr_val = self.fstr()
225
- tag = terminal.print(
226
- format.metadata, '<',
227
- format.type, 'T_SYMBOL',
228
- format.metadata, f'@0x{addr:x}>',
229
- format.reset
230
- )
231
- symbol_val = terminal.print(format.symbol, f':<Symbol:0x{int(fstr_val):x}>', format.reset)
232
- return f"{tag} {symbol_val}"
208
+ terminal.print(format.symbol, f':<Symbol:0x{int(fstr_val):x}>', format.reset, end='')
233
209
 
234
210
  def print_recursive(self, printer, depth):
235
211
  """Print this symbol (no recursion needed)."""
@@ -1,7 +1,8 @@
1
- import debugger
1
+ import sys
2
2
  import constants
3
3
  import format
4
4
 
5
+
5
6
  import rbasic
6
7
  import rfloat
7
8
  import rsymbol
@@ -35,19 +36,19 @@ class RImmediate:
35
36
  def print_to(self, terminal):
36
37
  """Print this value with formatting to the given terminal."""
37
38
  if self.val_int == 0:
38
- return terminal.print(format.metadata, '<', format.type, 'T_FALSE', format.metadata, '>', format.reset)
39
+ terminal.print_type_tag('T_FALSE')
39
40
  elif self.val_int == 0x04 or self.val_int == 0x08:
40
- return terminal.print(format.metadata, '<', format.type, 'T_NIL', format.metadata, '>', format.reset)
41
+ terminal.print_type_tag('T_NIL')
41
42
  elif self.val_int == 0x14:
42
- return terminal.print(format.metadata, '<', format.type, 'T_TRUE', format.metadata, '>', format.reset)
43
+ terminal.print_type_tag('T_TRUE')
43
44
  elif (self.val_int & 0x01) != 0:
44
45
  # Fixnum - shift right to get actual value
45
- tag = terminal.print(format.metadata, '<', format.type, 'T_FIXNUM', format.metadata, '>', format.reset)
46
- num = terminal.print(format.number, str(self.val_int >> 1), format.reset)
47
- return f"{tag} {num}"
46
+ terminal.print_type_tag('T_FIXNUM')
47
+ terminal.print(' ', end='')
48
+ terminal.print(format.number, str(self.val_int >> 1), format.reset, end='')
48
49
  else:
49
50
  # Unknown immediate
50
- return f"<Immediate:0x{self.val_int:x}>"
51
+ terminal.print_type_tag('Immediate', self.val_int)
51
52
 
52
53
  def print_recursive(self, printer, depth):
53
54
  """Print this immediate value (no recursion needed)."""
@@ -138,7 +139,6 @@ def interpret(value):
138
139
  Returns:
139
140
  An instance of the appropriate type class (never None)
140
141
  """
141
- import sys
142
142
  val_int = int(value)
143
143
 
144
144
  # Check for immediate flonum (must be before fixnum check)