Skip to content

Conversation

@jpco
Copy link
Collaborator

@jpco jpco commented Jan 8, 2026

This is an extension to #90 and fixes #80.

This PR keeps resolution of functions within eval.c, but for anything else, it calls out to the function %whatis with the term it is looking up as well as the function name if applicable. Whatever %whatis returns, es then attempts to evaluate.

%whatis is simply defined as

fn %whatis term name {
	if {~ $#name 0} {
		name = $term
	}
	if {!~ $#(fn-$term) 0} {
		result $(fn-$term)
	} {~ $term /* ./* ../*} {
		result %run $term $name
	} {
		let (searched = <={%pathsearch $term})
		result %run $searched(1) $name $searched(2 ...)
	}
}

%whatis does a redundant function lookup for the sake of users calling whatis or %whatis, but then looks for a binary and, if it finds one, returns a %run invocation with the binary as an argument. As in #90, $&run is the only part of the shell actually responsible for invoking binary child processes.

I think this is all surprisingly tidy. It makes both %whatis and %run work as hook functions like they both have always seemed like they should, it works fine with lexical functions without weirdness like $&keeplexicalbinding, and it's even some 20 fewer lines of code compared to the current behavior.

The core eval() code now looks for a function and then immediately falls
back to calling %whatis, which takes care of any logic around binary
searching and wrapping calls to binaries in %run.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Should %run be the built-in way binaries are run?

1 participant