Shell Command Type DSL
To overcome the limitations of our initial grep-based command-type database, we propose a new DSL to declare the typing of shell commands more intuitively and precisely. Our goal is to match specific command invocation patterns and assign them a type, such that variations on input/output types which depend on the configuration of the process arguments, can be captured in a clean and non-repetetive way.
The DSL is made up of two essential objectives: to define Command Patterns and Type Statements.
Command Patterns
The first aspect of the DSL is to match command invocations.
Each command pattern must be opened with the :: prefix.
Then we follow a syntax which resembles that of the SYNOPSIS section in manpages.
Example 1: Command pattern for a regular stat invocation
::stat [OPTION]... FILE...
Example 2: Command pattern for a regular find invocation
::find [START-DIR]... [EXPRESSION]
Example 3: Command pattern for invocation of version info
::find --version
(Uppercase names will be interpreted as variables, whereas all other strings are counted as literal)
Command Types
Given a Command Pattern, we can now define the Command Type for the case that the command invocation matches the pattern.
Therefore, a Command Pattern is always followed by a Command Type, given
as a collection of type assignments inside a { ... }-block.
A Command Type is a collection of type assignments, where all kinds of input/output streams — such as arguments, pipes and files — of a process can be selected.
The general syntax for a Type Statement is
SELECTOR : TYPE ;
Where TYPE is a Ladder-Type and SELECTOR can be any of:
| SELECTOR | Function |
|---|---|
>0 |
Stdin |
<1 |
Stdout |
<2 |
Stderr |
>FD |
Select input pipe on filedescriptor FD |
<FD |
Select output pipe on filedescriptor FD |
PATTERN-VARIABLE |
Select a matched sub-pattern |
$VAR |
Environment Variable |
$1 |
First Process Argument |
@FILE |
Content of a file |
Example 4: (simplified) Command type definition for the regular invocation pattern of find
::find [START-DIR]... [EXPRESSION] {
# The each of the arguments matched by START-DIR must be of type `Path`
START-DIR : Path ;
# The data written to stdout is a newline-separated sequence of paths
<1 : [ Path ~ [Char] ] ~ <SepSeq '\n' Char> ~ [Char] ;
}
A command type file may contain multiple command patterns. They will be tested in order where the first successful match will return.
Example 5: Multiple patterns in one file
::find --help { <1: Help~[Char]; }
::find -version--version { <1: VersionInfo~[Char]; }
::find [START-DIR]... [EXPRESSION] {
# The each of the arguments matched by START-DIR must be of type `Path`
START-DIR : Path ;
# The data written to stdout is a newline-separated sequence of paths
<1 : [ Path ~ [Char] ] ~ <SepSeq '\n' Char> ~ [Char] ;
}
Match Statement
Inside a block of Type Statements , any VARIABLE from the Command Pattern can be refined to match against a specific set of sub-patterns, where each case may add extra Type Statements to the resulting Process Type.
Example 6: Match inside Type-Block
::find [START-DIR]... [EXPRESSION] {
# The each of the arguments matched by START-DIR must be of type `Path`
START-DIR : Path ;
match EXPRESSION {
# In case the `-print0` option is enabled, change the output type
::-print0 {
# The data written to stdout is a null-separated sequence of paths
<1 : [ Path ~ [Char] ] ~ <SepSeq '\0' Char> ~ [Char] ;
}
# default
::{
# The data written to stdout is a newline-separated sequence of paths
<1 : [ Path ~ [Char] ] ~ <SepSeq '\n' Char> ~ [Char] ;
}
}
}
Questions
Format Strings
- -> Wrap/Unwrap to struct type
- -> need Pattern definitions for WordSegment-Level
- -> recognize [+FORMAT] (here + and VARIABLE without space) in pattern definition
Parameter Packs
- -> Wrap/Unwrap to Sequence Type
Pattern options are intricate
date has format string AND -R/-I options, which exclude each other..
- --> add "exclude " primitive ?
- --> exclusive match logic? --> add new match statements dynamically
xargs ??
- -> potential
typeof()operator to allow something like:<1 : typeof(CMD INITIAL-ARGS $>0...)