Tactical commit: things in 'stack_ops' really didn't belong in ops; moving.
This commit is contained in:
parent
d2efc8ba78
commit
4d480798e8
10 changed files with 333 additions and 231 deletions
|
|
@ -1,5 +1,147 @@
|
|||
# State of Play
|
||||
|
||||
## 20260505
|
||||
|
||||
### The stack frame corruption(?) bug
|
||||
|
||||
I have a weird bug in `read_symbol`, which at present I'm not understanding.
|
||||
|
||||
Stack frames in `0.1.0` are [paged space objects](https://www.journeyman.cc/blog/posts-output/2026-03-23-Paged-space-objects/), like all other objects; specifically they are objects of size class 4, which is to say they have a payload size of fourteen words. The first eight arguments to the function being called (which in most cases will be all the arguments) are held directly in the frame.
|
||||
|
||||
`read_symbol` expects its arguments to be as follows (I'm numbering from zero here, although I consider that perverse and confusing, because the substrate language is C which uses numbering from zero:)
|
||||
|
||||
| Argument | Expected value | Expected type |
|
||||
| -------- | --------------- | ------------------------------------ |
|
||||
| 0 | input stream | input stream |
|
||||
| 1 | read table | store (cons, hashtable or namespace) |
|
||||
| 2 | first character | character object |
|
||||
|
||||
`read_symbol` then reads characters sequentially from the stream until it encounters a white-space character; for each character it reads, it creates a symbol object representing that character, and conses that object onto the list of the characters it has read so far. So if the user has typed
|
||||
|
||||
> xyz
|
||||
|
||||
the internal representation is now a sequence
|
||||
|
||||
```lisp
|
||||
(z y x)
|
||||
```
|
||||
|
||||
Obviously, this now has to be reversed. So `read_symbol` then calls `reverse`. But wait! Because we're still in the bootstrap layer, the version of `read_symbol` I'm talking about is written in C. So *at the time of writing* it actually calls a wrapper function called `c_reverse` which builds the Lisp stack frame for `reverse` and then calls `reverse` with that stack frame. There was an earlier version of `c_reverse` which failed to create a new stack frame, and which would account for the bug I'm seeing; but that version has been replaced and the current version does certainly create the new stack frame:
|
||||
|
||||
```c
|
||||
/**
|
||||
* @brief reverse a sequence.
|
||||
*
|
||||
* A sequence is a list or a string-like-thing. A dotted pair is not a
|
||||
* sequence.
|
||||
*
|
||||
* @param sequence a pointer to a sequence.
|
||||
* @return a sequence like the `sequence` passed, but reversed; or `nil` if
|
||||
* the argument was not a sequence.
|
||||
*/
|
||||
struct pso_pointer c_reverse( struct pso_pointer frame_pointer,
|
||||
struct pso_pointer sequence ) {
|
||||
|
||||
struct pso_pointer result = nil;
|
||||
|
||||
if ( stackp( frame_pointer ) ) {
|
||||
result = reverse( make_frame(1, frame_pointer, sequence) );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
So, I can see in the debugger that the sequence created in `read_symbol` is passed to `c_reverse` as the sequence argument; I can see it is put into the new frame as the first (index 0) argument; the new frame is directly passed into reverse. Reverse expects the argument in its stack frame to look like this:
|
||||
|
||||
| Argument | Expected value | Expected type |
|
||||
| -------- | -------------- | ------------------------------------------ |
|
||||
| 0 | sequence | sequence (cons, keyword, string or symbol) |
|
||||
|
||||
Reverse throws an exception:
|
||||
|
||||
```lisp
|
||||
<exception: ("Invalid object in sequence")>
|
||||
```
|
||||
|
||||
D'oh! And, of course, in trying to explain the bug, I've found the bug. It wasn't what I thought it was, so I was looking in the wrong place. It was this:
|
||||
|
||||
```diff
|
||||
struct pso_pointer sequence =
|
||||
fetch_arg( pointer_to_pso4( frame_pointer ), 0 );
|
||||
- for ( struct pso_pointer cursor = sequence; !c_nilp( sequence );
|
||||
+ for ( struct pso_pointer cursor = sequence; !c_nilp( cursor );
|
||||
cursor = c_cdr( cursor ) ) {
|
||||
struct pso2 *object = pointer_to_object( cursor );
|
||||
switch ( get_tag_value( cursor ) ) {
|
||||
|
||||
```
|
||||
|
||||
I was checking for `nil` on the sequence, which obviously didn't change, not on the cursor, which did. D'oh!
|
||||
|
||||
### About debuggers
|
||||
|
||||
I switched to Eclipse for this session, because Eclipse has really good, really easy to use, debugger integration. But I don't, as I said yesterday, much like Eclipse. It is too helpful; it gets in the way too much.
|
||||
|
||||
Zed, Gram, Gnome Builder and VS Codium (discussed yesterday) all claim to have debugger integration, and I'm pretty sure the debugger used in all cases is the [GNU debugger, `gdb`](https://sourceware.org/gdb/) (edited: I'm wrong. Zed, and so presumably also Gram, use [`lldb`](https://lldb.llvm.org/)). `Gdb` is an excellent debugger with a truly atrocious user interface, but fortunately there's a large range of tools which wrap more or less good user interfaces around `gdb`, of which I use (and like) ['seer'](https://github.com/epasveer/seer). However it's *much* more productive to have your debugger integrated with your editor.
|
||||
|
||||
I've tried this morning to get each of these to enter a useful debugging session. It has taken some work. Gnome Builder fails (for me) because although selecting `Run with Debugger` from the `run` menu does start both a `psse` session and a `gdb` session, and although terminating the `psse` session does show `[Inferior 1 (process 248474) exited normally]` on the GDB console, when I attempt to set a breakpoint (you don't seem to be able to set on in the GUI), I get the following:
|
||||
|
||||
```
|
||||
> break src/c/ops/eval_apply.c:784
|
||||
Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
|
||||
> n
|
||||
Cannot execute this command without a live selected thread.
|
||||
```
|
||||
|
||||
So there is something alive there, and probably with a bit of struggle I could make it work.
|
||||
|
||||
Zed and Gram are much the same, because Gram is a fork of Zed. Zed appears(?) to copy VS Codium's (and thus VS Code's) approach to interacting with `gdb`. VS Codium *appears*(?) to need some sort of JSON configuration in `launch.json`. I've tried this:
|
||||
|
||||
```json
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "PSSE Debug (gdb Attach)",
|
||||
"type": "cppdbg",
|
||||
"request": "attach",
|
||||
"program": "target/psse",
|
||||
// "args": ["-p", "-s1000", "-v1023"],
|
||||
"processId": "${command:pickProcess}",
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
It does not work, at least not in VS Codium.
|
||||
|
||||
Zed's debugger [configuration documentation](https://zed.dev/docs/debugger) is better. Using it, I was able to compose this stanza:
|
||||
|
||||
```json
|
||||
{
|
||||
"label": "PSSE Start debugger config",
|
||||
"adapter": "CodeLLDB",
|
||||
"request": "launch",
|
||||
"program": "target/psse",
|
||||
"cwd": "$ZED_WORKTREE_ROOT",
|
||||
},
|
||||
|
||||
```
|
||||
|
||||
which successfully launches a debugger session. It's easy to set breakpoints in the editor windows; it's probably as easy to find your way around variables and stack frames as it is in Eclipse or Seer, once you get used to it (I haven't yet). I haven't yet worked out how to get it to automatically rebuild before running if it needs to do so, but I expect I shall. This is usable; but I shall need to get used to it.
|
||||
|
||||
## 20260504
|
||||
|
||||
My monster, she builds!
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue