...
 
Commits (2)
  • Samuel Newbold's avatar
    Don't assume ––init-file flag in rwshrc · f76d94db
    Samuel Newbold authored
    This makes #! less surprising and more useful
    Also
      * removing the last two non-prototyped functions
      * .test_not_empty returns true when zero strings are passed and false
      when multiple strings are passed, in addition to true when the string
      is empty, and false when it has nonzero length.
    f76d94db
  • Samuel Newbold's avatar
    s/.function_all_flags/.function/g · 6c67e00a
    Samuel Newbold authored
    Almost 4 years after prototypes were introduced, and four and a half
    months after non-prototyped functions were deprecated.
    6c67e00a
......@@ -14,15 +14,13 @@ this version of the shell, including the following.
* .while will respond to the .retest_condition exception by testing the
condition, and ending the loop if it fails, but (unlike .continue)
continuing with the following statement if it succeeds.
* All functions will require prototypes, and control flow statements such
as .for will also use a prototype for the values passed to the
argfunction rather than $1.
* Whether a function takes an argfunction will also be part of the
prototype and functions will be able to take more than one argfunction
with string arguments being associated with each argfunction. For
instance this will permit .scope to take several prototypes with an
argfunction for each prototype, and will run the argfunction for which
its arguments match the corresponding prototype.
* Control flow statements such as .for will also use a prototype for
the values passed to the argfunction rather than $1.
* Functions will be able to take more than one argfunction with string
arguments being associated with each argfunction. For instance this
will permit .scope to take several prototypes with an argfunction for
each prototype, and will run the argfunction for which its arguments
match the corresponding prototype.
* "Soons" will be replaced with "Earlies". The syntax will not
(necessarily) change, but the meaning will. Rather than & meaning to
evaluate the first time a containing statement is evaluated and && meaning
......
This diff is collapsed.
.echo $nl $nl $nl $nl
.function_all_flags fw .{argfunction} {
.function_all_flags f1 name .{argfunction} {.argfunction}
.function fw .{argfunction} {
.function f1 name .{argfunction} {.argfunction}
.whence_function f1; .echo $nl
f1 f2 {.argfunction}
.whence_function f2; .echo $nl
.rm_executable f1; .rm_executable f2}
fw {.echo hi $nl; .function_all_flags $name .{argfunction} {.argfunction}}
fw {.echo hi $nl; .function $name .{argfunction} {.argfunction}}
fw {.while .throw .false {
.function_all_flags &&name .{argfunction} {.argfunction}}}
.function_all_flags f1 name .{argfunction} {
.function &&name .{argfunction} {.argfunction}}}
.function f1 name .{argfunction} {
.echo function name $name $nl
.whence_function .argfunction {.argfunction}
.echo $nl end of function body $nl}
......@@ -62,7 +62,7 @@ fw {.mapped_argfunction $name {.for a b {
.whence_function .argfunction {.argfunction}
.echo $nl end of function body $nl}}}
fw {.mapped_argfunction {
.function_all_flags $name .{argfunction} {.argfunction}}}
.function $name .{argfunction} {.argfunction}}}
.nop $A $FIGNORE
.exit 0
......@@ -234,20 +234,9 @@ void b_fork(const Argm& argm, Error_list& exceptions) {
if (WIFEXITED(status) && WEXITSTATUS(status))
exceptions.add_error(Exception(Argm::Return_code, WEXITSTATUS(status)));}
// add argfunction to executable map with name $1
void b_function(const Argm& argm, Error_list& exceptions) {
Argm lookup(argm.subrange(1), nullptr, argm.parent_map());
Base_executable *e = executable_map.find_second(lookup);
if (is_argfunction_name(argm[1]) || dynamic_cast<Builtin*>(e))
exceptions.add_error(Exception(Argm::Illegal_function_name, argm[1]));
else {
argm.error <<"deprecated non-prototype: " <<argm.str() <<"\n";
executable_map.set(new Function(argm[1], true, *argm.argfunction()));
}}
// add argfunction to executable map with name $1 and arguments $*2
// the arguments must include all flags that can be passed to this function
void b_function_all_flags(const Argm& argm, Error_list& exceptions) {
void b_function(const Argm& argm, Error_list& exceptions) {
Argm lookup(argm.subrange(1, argm.argc()-2), nullptr, argm.parent_map());
Base_executable *e = executable_map.find_second(lookup);
if (is_argfunction_name(argm[1]) || dynamic_cast<Builtin*>(e))
......@@ -629,8 +618,8 @@ void b_test_less(const Argm& argm, Error_list& exceptions) {
// throws .false if the string is empty
void b_test_not_empty(const Argm& argm, Error_list& exceptions) {
if (!argm[1].length())
exceptions.add_error(Exception(Argm::False, " -n " + argm[1]));}
for (unsigned j = 1; j < argm.argc(); ++j) if (argm[j].length()) return;
exceptions.add_error(Exception(Argm::False, " -n "));}
// throw .false if the two strings convert to doubles and are not equal
void b_test_number_equal(const Argm& argm, Error_list& exceptions) {
......
......@@ -20,7 +20,6 @@ void b_fallback_handler(const Argm& argm, Error_list& exceptions);
void b_for(const Argm& argm, Error_list& exceptions);
void b_for_each_line(const Argm& argm, Error_list& exceptions);
void b_fork(const Argm& argm, Error_list& exceptions);
void b_function_all_flags(const Argm& argm, Error_list& exceptions);
void b_function(const Argm& argm, Error_list& exceptions);
void b_get_fallback_message(const Argm& argm, Error_list& exceptions);
void b_get_max_collectible_exceptions(const Argm& argm, Error_list& exceptions);
......
#! /bin/rwsh --init-file
.for ${.list_environment}$ {.scope $1$ (-- var val) {
.nop $val
.if .test_in $var FIGNORE {.nop}
.else {.unset $var}}}
.global nl (
)
.if .var_exists argv {.error ignored excess arguments $argv $nl}
.else {.nop}
.for &{.internal_functions}$ {.nop
.if .test_string_unequal $1 .raw_command {
.function_all_flags &&1 -- args ... {.nop
......
......@@ -82,7 +82,7 @@ void Executable_map::run_handling_exceptions(Argm& argm,
void Executable_map::unused_var_check_at_exit(void) {
Error_list exceptions;
Prototype shell_invocation(true);
Prototype shell_invocation;
shell_invocation.unused_var_check(Variable_map::global_map, exceptions);
if (exceptions.size()) global_stack.exception_handler(exceptions);}
......
......@@ -38,8 +38,7 @@ void Builtin::execute(const Argm& argm, Error_list& exceptions) const {
Variable_map locals(argm.parent_map());
prototype.arg_to_param(argm.argv(), locals, exceptions);
locals.bless_unused_vars();
if (prototype.non_prototype) std::abort();
else if (argm.argfunction() && prototype.exclude_argfunction)
if (argm.argfunction() && prototype.exclude_argfunction)
exceptions.add_error(Exception(Argm::Excess_argfunction));
else if (!argm.argfunction() && prototype.required_argfunction)
exceptions.add_error(Exception(Argm::Missing_argfunction));
......@@ -78,8 +77,7 @@ void Command_block::prototype_execute(const Argm& argm,
Error_list& exceptions) const {
Variable_map locals(argm.parent_map());
prototype.arg_to_param(argm.argv(), locals, exceptions);
if (prototype.non_prototype);
else if (argm.argfunction() && prototype.exclude_argfunction)
if (argm.argfunction() && prototype.exclude_argfunction)
exceptions.add_error(Exception(Argm::Excess_argfunction));
else if (!argm.argfunction() && prototype.required_argfunction)
exceptions.add_error(Exception(Argm::Missing_argfunction));
......@@ -129,10 +127,6 @@ Function::Function(const std::string& name_i, const Argv& parameters,
const Command_block& src) :
name_v(name_i), prototype(parameters), body(src) {}
Function::Function(const std::string& name_i, bool non_prototype_i,
const Command_block& src) :
name_v(name_i), prototype(non_prototype_i), body(src) {}
// run the given function
void Function::execute(const Argm& argm, Error_list& exceptions) const {
body.prototype_execute(argm, prototype, exceptions);}
......@@ -143,7 +137,5 @@ void Function::promote_soons(unsigned nesting) {
// convert the function to a string. except for the handling of the name this
// is the inverse of the string constructor.
std::string Function::str() const {
if (prototype.non_prototype)
return ".function " + escape(name()) + " " + body.str();
else return ".function_all_flags " + escape(name()) +
" " + prototype.str() + " " + body.str();}
return ".function " + escape(name()) + " " + prototype.str() + " " +
body.str();}
......@@ -48,13 +48,11 @@ class Function : public Named_executable {
Prototype prototype;
Function(const std::string& name_i) :
name_v(name_i), prototype(true), body() {};
name_v(name_i), prototype(), body() {};
void check_for_duplicates(const std::string& name);
public:
Command_block body;
Function(const std::string& name_i, bool non_prototype_i,
const Command_block& src);
Function(const std::string& name_i, const Argv& parameters,
const Command_block& src);
Function(const Function& src) :
......
......@@ -114,16 +114,16 @@ std::string Parameter_group::str() const {
result.append((j? " ": "") + names[j] + (elipsis == j? " ...": ""));
return result + "]";}}
Prototype::Prototype(bool non_prototype_i) :
Prototype::Prototype(void) :
bare_dash_dash(false), dash_dash_position(-1), elipsis_var(""),
flag_options(), flags(ALL), parameter_names(),
positional(), required_argc(), non_prototype(non_prototype_i),
positional(), required_argc(),
exclude_argfunction(true), required_argfunction(false) {}
Prototype::Prototype(const Argv& parameters) :
bare_dash_dash(false), dash_dash_position(-1), elipsis_var(""),
flag_options(), flags(ALL), parameter_names(),
positional(), required_argc(), non_prototype(false),
positional(), required_argc(),
exclude_argfunction(true), required_argfunction(false) {
bool has_elipsis = false;
for (auto fp = parameters.begin(); fp != parameters.end(); ++fp) {
......@@ -162,7 +162,6 @@ Prototype::Prototype(const Argv& parameters) :
void Prototype::arg_to_param(const Argv& argv, Variable_map& locals,
Error_list& exceptions) const {
if (non_prototype) return;
enum Dash_dash_type dash_dash = dash_dash_position? UNSEEN:
bare_dash_dash? BARE: BRACKET;
if (flags == SOME) locals.param("-*", ""), locals.param("-?", "");
......
......@@ -38,10 +38,9 @@ class Prototype {
std::vector<Parameter_group> positional;
unsigned required_argc;
public:
bool non_prototype;
bool exclude_argfunction;
bool required_argfunction;
Prototype(bool non_prototype);
Prototype(void);
Prototype(const Argv& parameters);
void arg_to_param(const Argv& invoking_argm, Variable_map& locals,
Error_list& exceptions) const;
......
......@@ -70,20 +70,19 @@ void internal_init(Error_list& exceptions) {
bi(".for", b_for, Argv {"--", "list", "...", ".{argfunction}"});
bi(".for_each_line", b_for_each_line, Argv {".{argfunction}"});
bi(".fork", b_fork, Argv {"--", "command", "...", "[.{argfunction}]"});
bi(".function", b_function, Argv {"--", "name", ".{argfunction}"});
bi(".function_all_flags", b_function_all_flags,
bi(".function", b_function,
Argv {"--", "name", "[prototype", "...]", ".{argfunction}"});
bi(".global", b_global, Argv {"--", "var", "value"});
bi(".if", b_if, Argv {"--", "condition", "...", ".{argfunction}"});
fn(".init", Argv {"--", "[args", "...]"},
".set_max_nesting 10\n"
" .function_all_flags .file_open_failure name stack ... {.nop\n"
" .function .file_open_failure name stack ... {.nop\n"
" .combine (init file ) $name ( does not exist\n"
"call stack ) $stack (\n)}\n"
" .function_all_flags .raw_command -- args ... {.nop $args}\n"
" .function .raw_command -- args ... {.nop $args}\n"
" .collect_errors_except .nop {.nop\n"
" .source /etc/rwshrc $args$\n"
" .for &{.internal_functions}$ {\n"
" .for &{.internal_functions}$ {.nop\n"
" .if .test_executable_exists $1 {.nop}\n"
" .else {.echo &&&1 not defined (\n)}}\n"
" .if .test_executable_exists .help {.nop\n"
......@@ -131,7 +130,7 @@ void internal_init(Error_list& exceptions) {
bi(".test_is_number", b_test_is_number, Argv {"--", "value"});
bi(".test_in", b_test_in, Argv {"--", "focus", "[list", "...]"});
bi(".test_less", b_test_less, Argv {"--", "lhs", "rhs"});
bi(".test_not_empty", b_test_not_empty, Argv {"--", "input"});
bi(".test_not_empty", b_test_not_empty, Argv {"--", "[input", "...]"});
bi(".test_number_equal", b_test_number_equal, Argv {"--", "lhs", "rhs"});
bi(".test_string_equal", b_test_string_equal,
Argv {"--", "left_string", "right_string"});
......
.echo $*0 >/tmp/lcl (
)
.set_max_nesting 20
.function_all_flags () {.nop}
.function_all_flags #! -- ignored ... {.nop $ignored}
.function_all_flags .autofunction -- cmd [args ...] [.{argfunction}] {
.for ${.list_environment}$ {.nop
.scope $1$ (-- var val) {.nop
.if .var_exists $var {.nop $val}
.else {.nop
.global $var $val
.nop $$var}}}
.function #! -- ignored ... {.nop $ignored}
.function .autofunction -- cmd [args ...] [.{argfunction}] {.nop
.if .var_exists args {.nop $args}
.else {.nop}
.nop {argfunction}
.local full_path ${.which_path $cmd $PATH}
if_only_not .test_executable_exists $full_path {.binary $full_path}
if_only_not .test_string_equal $cmd $full_path {
.function_all_flags $cmd -- [args ...] {
&&full_path $args$}}
.if .test_executable_exists $full_path {.nop}
.else {.binary $full_path}
.if .test_string_equal $cmd $full_path {.nop}
.else {.function $cmd -- [args ...] {&&full_path $args$}}
.error added $cmd to executable map $nl}
.if .test_less ${.argc $argv$} 2 {.source /etc/rwshrc-default}
.else {
.if .test_string_equal $argv$1 -to {
.global SHELL /bin/rwsh
.function () {.nop}
.scope $argv$ ([--init-file init-file] [-to] [-c command]
[-rwsh] [rwsh_binary] [script-args ...]) {.nop
.nop $rwsh_binary$ $-to$ $-c$ $script-args$ $-rwsh$
.if .var_exists --init-file {.source $init-file}
.else_if .var_exists -to {
.unset PATH
.unset ?
.global TESTABILITY (an=external var(iable))
.exec ./rwsh test_init.rwsh
.exit 0}
.else_if .test_number_equal ${.argc $argv$} 2 {
.nop .source /etc/rwshrc-default
.source $argv$1}
.else_if .test_string_equal $argv$1 -c {
.for ${.list_environment}$ {
.scope $1$ (-- var val) {
.if .var_exists $var {.nop $val}
.else {
.global $var $val
.nop $$var}}}
.source /etc/rwshrc-basic
.nop $FIGNORE
.function_all_flags .shutdown -- [args ...] {.nop $args}
.function_all_flags .return_code code cmd [add_stack ...] {
.exec ./rwsh --init-file test_init.rwsh}
.else_if .var_exists -rwsh {.source /etc/rwshrc-default}
.else_if .test_not_empty $-c$ $script-args$ {.source /etc/rwshrc-basic}
.else {.exec /etc/rwshrc-default}
.if .var_exists -c {
.function .return_code code cmd [add_stack ...] {
echo $cmd returned $code : call stack $cmd $add_stack$
.exit $code}
.collect_errors_except .nop {
.mapped_argfunction $argv$2 {$1$}
.exit 0}}
.else {
.echo unexpected command line: $argv$ (
)
.source /etc/rwshrc-default}}
.else_if .var_exists script-args {
.function .return_code code cmd [add_stack ...] {
echo $cmd returned $code : call stack $cmd $add_stack$
.exit $code}
.collect_errors_except .nop {
.source $script-args$
.exit 0}}
.else {.nop}}
This diff is collapsed.
.nop $argv$
.for ${.list_environment}$ {
.scope $1$ (-- var val) {
.if .var_exists $var {.nop $val}
.else {
.global $var $val
.nop $$var}}}
.source /etc/rwshrc-basic
#! /bin/rwsh --init-file
.source /etc/rwshrc-basic $argv$
# only the last line is actually needed, but this is the only test of these
# only the fourth is needed, but this is the only test of these builtins
.toggle_readline
.toggle_readline
.disable_readline
......@@ -29,14 +23,14 @@
# selection commands
fn sfn command {
.function_all_flags $command [-*] [file ...] {
fn $command [-*] [file ...] {
if_only .var_exists file {.selection_set s $file}
&&{.which_path $command $PATH} $-*$ @$s}}
fn fn-subcommand system command {
.function_all_flags &&{c $system - $command} -- [args ...] {
fn &&{c $system - $command} -- [args ...] {
&&{whichp $system} &&command $args$}}
fn sfn-subcommand system command {
.function_all_flags &&{c $system - $command} [-*] [file ...] {
fn &&{c $system - $command} [-*] [file ...] {
if_only .var_exists file {.selection_set s $file}
.if .test_not_empty $s {&&{whichp $system} &&command $-*$ @$s}
.else {&&{whichp $system} &&command $-*$}}}
......@@ -225,6 +219,7 @@ fn arg-diff [-?] {
&{whichp diff} $-?$ argfunction.basic-result argfunction.result.last}
.else {&{whichp diff} -u argfunction.basic-result argfunction.result.last}}
fn bless-arg {&{whichp cp} argfunction.result.last argfunction.basic-result}
fn counter {&{whichp rwsh} --init-file counter.rwsh}
# final setup and individual configuration
.source &{c $HOME /.rwshrc}
......
This diff is collapsed.
#! /bin/rwsh
.echo hello $argv$ (
)
......@@ -3,5 +3,5 @@
.global nl (
)
.for &{.internal_functions}$ {.nop
.function_all_flags $1 -- [args ...] {.echo signal triggered: $0 \( $args$ \); .combine $nl}}
.function_all_flags .shutdown -- [args ...] {.nop $args; .exit 255}
.function $1 -- [args ...] {.echo signal triggered: $0 \( $args$ \); .combine $nl}}
.function .shutdown -- [args ...] {.nop $args; .exit 255}
This diff is collapsed.
.source /etc/rwshrc-basic
.global PATH /bin:/usr/bin
.scope () {.getpid; .echo $nl}
.scope () {.getppid; .echo $nl}
.function_all_flags timings focus {
.function timings focus {
.combine $focus (: last\() ${.last_execution_time $focus} \) \
.combine (total\() ${.total_execution_time $focus} \) \
.combine (count\() ${.execution_count $focus} \) $nl}
.function_all_flags clock-watch {
.function clock-watch {
.usleep 600
/bin/true
timings timings
......
.try_catch_recursive .file_open_failure {
#! /bin/rwsh --init-file
.try_catch_recursive .file_open_failure {.nop
.source /non-existent/file/to/test/failure}
.function_all_flags .raw_command -- cmd {.echo $cmd; .echo (
.function .raw_command -- cmd {.echo $cmd; .echo (
)}
.global A \
.nop .function_all_flags .run_logic -- cmd [args ...] {
.set SHELL /bin/rwsh
.nop .function .run_logic -- cmd [args ...] {.nop
.signal_handler &{.internal_functions}$ {&&* {.argfunction}}
.mapped_argfunction {&&* {.argfunction}}
&&* {.argfunction}}
.function_all_flags .before_command -- args ... [.{argfunction}] {.nop $args}
.function_all_flags .after_command -- args ... [.{argfunction}] {.nop $args}
.function_all_flags .prompt {.echo \$}
.function_all_flags .vars {.internal_vars}
.function .before_command -- args ... [.{argfunction}] {.nop $args}
.function .after_command -- args ... [.{argfunction}] {.nop $args}
.function .prompt {.echo \$}
.function .vars {.internal_vars}
.source /etc/rwshrc-basic $argv$
.function .shutdown -- args ... {
.nop $args
.combine $nl (now terminating normally) $nl}
This diff is collapsed.
This diff is collapsed.
.function_all_flags a [-*] [-x b ...] c {
.function a [-*] [-x b ...] c {
.for &&{.list_locals}$ {.combine $1 \( $$1 \) \ }; .echo $nl}
.nop $A $FIGNORE
.whence_function a
......@@ -7,7 +7,7 @@ a -x first
a -x (fi rst) second
a -x first (sec ond) third
a -x (fi rst) (sec ond) third fourth
.function_all_flags a [-*] [-x ... b] c {
.function a [-*] [-x ... b] c {
.for &&{.list_locals}$ {.combine $1 \( $$1 \) \ }
.combine $nl
# if_only .test_not_empty $-* {c (-*: ) $-*$ $nl}
......