Command Objects and code re-use

Something that has come up now in a couple of contexts is the re-use of the command objects.

I’m working on an alternate user interface which has a richer form of output than the current CLI. I’m not able to use some of the existing commands due to this. The same is true of someone who might want to do an alternate command system with a WinDbg style approach.

I guess I have a couple of questions:

  • Is there something that we can do to improve code re-use at this level? Are there requirements for code-level compatibility here?

  • Is there much interest in making command parsing or command output formats more flexible? (In one system that I use, we effectively have a tree of commands and can splice in new subcommands very easily, much like the Lisp Machine command line or that of a router. This way, the Objective C runtime could, for example, create a subcommand for “breakpoint set -s” for selector-based breakpoints without this having to be something global.)

  • Would it make sense for commands to be more directly implemented using the SB* APIs so that it is clear that everything that commands do can be done without using the lower level APIs?

For an example of something that is done in a command that isn’t as easily doable via SB* APIs is the use of Args::StringToAddress by various commands, notably “breakpoint set -a”. Something like that might be a nice addition to SBTarget or SBAddress perhaps?

Cheers,

  • Bruce

Something that has come up now in a couple of contexts is the re-use of the command objects.

I'm working on an alternate user interface which has a richer form of output than the current CLI. I'm not able to use some of the existing commands due to this. The same is true of someone who might want to do an alternate command system with a WinDbg style approach.

I guess I have a couple of questions:

  • Is there something that we can do to improve code re-use at this level? Are there requirements for code-level compatibility here?

We aren't guaranteeing anything about lldb_private API's, if that's what you mean. OTOH, changing the behaviors of commands in the lldb command language set should be done judiciously if at all.

  • Is there much interest in making command parsing or command output formats more flexible? (In one system that I use, we effectively have a tree of commands and can splice in new subcommands very easily, much like the Lisp Machine command line or that of a router. This way, the Objective C runtime could, for example, create a subcommand for "breakpoint set -s" for selector-based breakpoints without this having to be something global.)

Hard to say without knowing what you have in mind.

I'm a little leery about being able to dynamically insert options into commands, you'll have to be careful to keep the help from becoming incoherent. I like that the commands document themselves, so we don't have to keep some side document up to date. If you can add options dynamically, you'd have to know all the things that COULD add to commands and then query all them, and have some way of showing "this option gets added when X happens." Otherwise folks will waste time trying to find that really useful option which I saw once but can't figure out how to get back...

The command objects are fairly loosely coupled to the way the command line is parsed already. There is some unfinished business here that would make this easier, for instance although the options & arguments all have argument types that idea came in late and isn't used very throughly anywhere. I certainly wouldn't object to make this cleaner so that you could drive the command objects from multiple parsers.

Dunno about command returns. That's mostly useful to do things more properly done by the SB API's. We've resisted trying to make the command line into a light-weight programming language, and instead tried to make it present information with customizability and ease of use being paramount. So for instance, there's pretty much NO guarantee what you're going to get back from "bt" since you can customize this to your heart's content with the thread & frame formats. I think this is the most important thing for the command interaction, since folks that want to program the debugger, can do so in Python and C++.

  • Would it make sense for commands to be more directly implemented using the SB* APIs so that it is clear that everything that commands do can be done without using the lower level APIs?

We try to make the Command Object commands rely on relatively high level functions in the lldb_private namespace, and push any useful logic down into the API's. So most of the real work in the commands should be just organizing the task of the command. The Command Objects don't use the SB API's mostly because we needed a command line to run lldb as we were developing it, and we didn't want to try to cook up the SB API's that early on in development. You should be able to replace the uses of the lldb_private API's in the command object code with SB API's, certainly the intent was not to have any useful goodies hiding in command objects. OTOH, I'm not sure the perturbation of the code, and new bugs introduced, etc. would be worth whatever you would get out of this exercise.

For an example of something that is done in a command that isn't as easily doable via SB* APIs is the use of Args::StringToAddress by various commands, notably "breakpoint set -a". Something like that might be a nice addition to SBTarget or SBAddress perhaps?

StringToAddress is a bad example 'cause that's a total hack. You really should just be able to evaluate the expression and get the result, but we haven't gotten around to teaching llvm to evaluate "function_name + address" without horrendous casting. StringToAddress does:

1) Evaluate the expression, and it that works, YAY!
2) Look and see if the input string looks like NAME [+-] NUMBER and if so return <ADDRESS_OF_NAME>+NUMBER
3) Go belly up

So I'm not super excited about this one... But I'm not at all opposed to adding other things that are useful to the API's, provided we don't make them so fat as to be hard to grasp.

Jim

alternative command language. I say "alternative language" because I'm
thinking of something more involved than just adding a few extra commands,
or changing some options. I haven't nailed it down too concretely, so take
anything I say here with a grain of salt, but it would involve being able
to switch languages on the fly with a setting.

When we talk about "a richer form of output" are we talking about only the
output? Because later you mention having a tree-like structure of
commands, so it sounds like you might also be talking about a different
command syntax or structure as well.

My overall take on this is if you want to provide a command language that has the same pretty simple structure, and unformatted output, that the lldb command language does, then it would be fine to extend the CommandObjects to back more than one parser. If you're getting any more ambitious than this, you'll probably want to re-implement the command functionality (e.g. to provide more structured output, etc.) using the SB API's, and not clog up the current command line code trying to make it serve two masters. Anything that is really complex in the current command set should be pushed into the lldb_private API's and then to the SB API's if it is indeed useful. Note, we try to do this as a cleanup task whenever we come across this sort of thing. So sharing the CommandObject code won't save you all that much work. And it's likely to keep both implementations cleaner.

Jim