Commit Graph

92 Commits

Author SHA1 Message Date
Timothy Sample 0c0227d523 Add support for file descriptors 3 to 9
* geesh/shell.scm (*fd-count*) Increase to 10.
(current-3-port, current-4-port, current-5-port, current-6-port,
current-7-port, current-8-port, current-9-port): New variables.
(fd->current-port): Handle file descriptors 3 to 9.
2018-12-05 16:08:09 -05:00
Timothy Sample 5a4816dabf Add 'exec-let' support
* geesh/eval.scm (eval-sh): Handle '<sh-exec-let>'.
2018-12-05 16:08:09 -05:00
Timothy Sample d0e5c3f5ae Handle redirect errors in 'eval'
* geesh/eval.scm (eval-sh): Handle redirect errors.
2018-12-05 16:08:09 -05:00
Timothy Sample 0ae52599c4 Preserve input and error ports in substitutions
This was simply a mistake.

* geesh/shell.scm (sh:substitute-command): Leave 'current-input-port'
and 'current-error-port' alone.
* tests/shell.scm: Remove tests that check that input and error gets
ignored during substitutions.
2018-12-05 16:08:09 -05:00
Timothy Sample 085c35a833 Use 'parameterize' for redirects
Instead of saving and restoring redirects manually, if we let them all
be parameters (like 'current-input-port'), we can use 'parameterize'
and make Guile take of this for us.  As a side-effect of this change,
redirect errors get handled.

* geesh/shell.scm (save-and-set-redirect): Rename this...
(redir->parameter+port): ...to this and change the return value to be
a pair consisting of a parameter and a port.
(restore-saved-port): Remove function.
(sh:with-redirects): Use 'parameterize' to effect redirects rather
than updating them and restoring them manually.
2018-12-05 16:08:09 -05:00
Timothy Sample b92630b39d Flush ports before forking
There are two issues that arise due to output port buffers and
forking.  If we run Scheme code in a child process, we need to avoid
copying buffered output into the child process.  Otherwise, the
buffered output could be written twice.  If we run non-Scheme
code (i.e., exec), we need to flush the ports to ensure proper
sequencing of writes since the non-Scheme code will not know about the
buffered output and will write its output before the buffer gets
flushed.

* geesh/shell.scm (exec-utility): Flush all ports before forking.
(%subshell): Ditto.
2018-12-05 16:08:09 -05:00
Timothy Sample 9dbf64d740 Enable 'word-split' specification test
* tests/spec/Makefile.am (TESTS): Add 'word-split'.
* tests/spec/oil.scm: Filter out four tests from it that we cannot
support yet.
2018-12-05 16:08:09 -05:00
Timothy Sample f448a57a27 Add filtering for specification tests
* tests/spec/oil.scm: Add code to filter out specific test cases from
a test file.
2018-12-05 16:08:09 -05:00
Timothy Sample 4b7d2404f3 Fix handling of non-whitespace IFS separators
* geesh/word.scm (string-tokenize*): New function.
(split-fields): Use it to handle non-whitespace IFS separators.
* tests/word.scm: Add tests.
2018-12-05 16:08:09 -05:00
Timothy Sample 3e6d7830a9 Fix splitting nested words
* geesh/word.scm (split-fields): Move handling of list words into
'wedge-apart' so that they get handled in recursive calls.
* tests/word.scm: Add a test for this.
2018-12-05 16:08:01 -05:00
Timothy Sample 765e91eb88 Elide unquoted empty and unset variables
* geesh/word.scm (split-fields): Make an empty string yield zero
fields (an empty list).
* tests/word.scm: Update tests and add tests to make sure that quoted
empty strings are preserved.
2018-12-05 16:06:14 -05:00
Timothy Sample f84b6235db Add Oil shell specification tests
tests/spec/oil.scm: New file.
tests/spec/check-spec: New file.
tests/spec/Makefile.am: New file.
configure.ac: Add the new Makefile.
Makefile.am (check-spec): New rule for running Oil shell
specification tests.
(clean-local): New rule that tells Automake how to clean up the
specification tests.
.gitignore: Add tests/spec/oil and tests/spec/oil-link.
2018-12-05 16:06:14 -05:00
Timothy Sample eb4b8bb61b Handle '$@' and '$*' parameters
* geesh/word.scm (parameter-ref): Handle '$@' and '$*' parameters.
2018-12-05 16:06:14 -05:00
Timothy Sample e6347dc37f Handle field splitting with quoted '$@'
* geesh/word.scm (split-fields): Handle a special '<sh-at>' qword
form, so that a quoted '$@' reference can still be split.
(argument-separator): New function.
(remove-quotes): Handle the '<sh-at>' form when it should not be
split.  This requires knowing how to concatenate arguments, so add an
'ifs' parameter.
(expand-word): Pass 'ifs' to 'remove-quotes'.
2018-12-05 16:05:36 -05:00
Timothy Sample 7fe940e852 Use '$IFS' as a string when splitting words
We used to model 'IFS' as a character set, but when handling special
parameters, the order of the characters matters.  Since it is also an
environment variable, it makes sense to treat as a string (rather than
a list).

* geesh/word.scm (split-fields): Treat 'ifs' as a string instead of a
character set.
(expand-word): Get 'ifs' from the environment if available or use a
default string otherwise.
2018-12-03 20:20:56 -05:00
Timothy Sample 3fad06a756 Add function definition support
* geesh/eval.scm (eval-sh): Handle '<sh-defun>'.
2018-12-03 20:19:56 -05:00
Timothy Sample 93a5cba568 Add function call semantics
* geesh/shell.scm (exec-let): Find and use functions when appropriate.
2018-12-03 20:19:39 -05:00
Timothy Sample 58f5644d2a Add 'arguments' field to environment
* geesh/environment.scm (<environment>): Add an 'arguments' field.
(make-environment): Add an optional 'arguments' parameter.
(with-environment-arguments): New public function.
.dir-locals.el: Indent it nicely.
2018-12-03 20:19:22 -05:00
Timothy Sample f03b438009 Keep track of functions in the environment
* geesh/environment.scm (<environment>): Add a 'functions' field.
(make-environment): Initialize it to the empty list.
(environment-function-ref): New public function.
(define-environment-function!): New public function.
2018-12-03 20:18:50 -05:00
Timothy Sample e43e6a88c4 Add 'status' field to environment
Instead of using an environment variable named '?', we will use a
special environment field called 'status'.  This lets us get rid of a
lot of number-string conversions (since an environment variable has to
have a string value).

* geesh/environment.scm (<environment>): Add a 'status' field.
(make-environment): Set it to 0 by default.
* geesh/repl.scm (run-repl): Use new field in place of '?' variable.
* geesh/shell.scm (exec-utility, sh:and, sh:exec-let, sh:for, sh:not,
sh:or, sh:pipeline, sh:subshell, sh:substitute-command): Ditto.
* geesh/word.scm (parameter-ref): New function that handles both
special parameters (e.g., '?') and variables.
(parameter-ref*): Like 'var-ref*', but for 'parameter-ref'.
(word->qword): Replace 'var-ref' and 'var-ref*' with 'parameter-ref'
and 'parameter-ref*' respectively.
2018-12-03 20:17:56 -05:00
Timothy Sample 801e9c8012 Use '$?' as the return value of the REPL
* geesh/repl.scm (run-repl): Return the value of '$?' (converted to a
number).
2018-12-03 20:16:01 -05:00
Timothy Sample fb493cc5f4 Process the return value of built-ins
* geesh/shell.scm (sh:exec-let): Set the '$?' variable to the return
value of built-in utilities.
2018-12-03 20:15:40 -05:00
Timothy Sample 21b862d326 Add the 'false' utility
* geesh/built-ins/false.scm: New file.
* Makefile.am: Add it.
* geesh/built-ins.scm (*built-ins*): Define 'false'.
2018-12-03 20:15:19 -05:00
Timothy Sample 5dae68d90a Make echo return a status code
* geesh/built-ins/echo.scm (echo): Return a status a code.
2018-12-03 20:14:57 -05:00
Timothy Sample 339f59d639 Add the 'read' utility
* geesh/built-ins/read.scm: New file.
* Makefile.am: Add it.
* geesh/built-ins.scm (*built-ins*): Define 'read'.
2018-12-03 20:14:36 -05:00
Timothy Sample 2db7833d61 Add for-loop support
* geesh/eval.scm (eval-sh): Handle '<sh-for>'.
2018-12-03 20:13:23 -05:00
Timothy Sample db56b1cc0a Add for-loop semantics
* geesh/shell.scm (sh:for): New public function.
* .dir-locals.el: Indent it nicely.
2018-12-03 20:12:51 -05:00
Timothy Sample 46ae7129d5 Add boolean support
* geesh/eval.scm (eval-sh): Handle '<sh-and>', '<sh-not>', and '<sh-or>'.
2018-12-03 20:12:22 -05:00
Timothy Sample 240ca130e8 Add boolean semantics
* geesh/shell.scm (sh:and, sh:not, sh:or): New public functions.
2018-12-03 20:12:02 -05:00
Timothy Sample 211e73ca43 Add pipeline support
* geesh/eval.scm (eval-sh): Handle '<sh-pipeline>'.
2018-12-03 20:11:28 -05:00
Timothy Sample 37f4ce6ea8 Add pipeline semantics
* geesh/shell.scm (swap-and-shift-pairs): New function.
(make-pipes): New function.
(plumb): New function.
(sh:pipeline): New public function.
* tests/shell.scm: Test it.
2018-12-03 20:09:55 -05:00
Timothy Sample 553b8f2b96 Use ports for redirects
Before, we were using raw file descriptors.  This worked okay, but
there was interference caused by port buffering.  Doing everything at
the port level avoids this problem, and has the added benefit of
allowing one to use the 'current-*-port' parameters with the shell
module (in a limited way, but there is room for improvement).

* geesh/shell.scm (*fd-count*): New variable.
(fd->current-port): New function.
(install-current-ports!): New function.
(exec-utility): Use it to set up file descriptors.
(save-and-install-redirect!): Rename this...
(save-and-set-redirect): ...to this and modify the current port
parameters instead of raw file descriptors.
(restore-saved-fdes!): Rename this...
(restore-saved-port): ...to this.
(sh:with-redirects): Adjust to use the renamed functions.
(sh:substitute-command): Parameterize the current ports directly
instead of using redirects.
* tests/shell.scm: Add tests to check if port buffers cause problems.
2018-12-03 20:07:53 -05:00
Timothy Sample 00d50fe7fd Add '-n' support to echo
* geesh/built-ins/echo.scm (echo): Omit trailing newline when '-n' is
the first argument.
2018-12-03 20:07:22 -05:00
Timothy Sample a6ceb8f3f2 Add command substitution support
* geesh/eval.scm (eval-word): Parameterize 'eval-cmd-sub' so that the
word module can substitute commands.
2018-12-03 20:07:06 -05:00
Timothy Sample 6b6ca11bce Add command substitution semantics
* geesh/shell.scm (%subshell): New function factored out from 'subshell'.
(subshell): Use it.
(substitute-command): New public function.
* tests/shell.scm: Test it.
* .dir-locals.el: Indent it nicely.
2018-12-03 20:06:47 -05:00
Timothy Sample 3148f66a21 Add subshell support
* geesh/eval.scm (exps->thunk): New function.
(eval-sh): Handle '<sh-subshell>'.
2018-12-03 20:04:55 -05:00
Timothy Sample 8739cafad9 Add subshell semantics
* geesh/shell.scm (subshell): New public function.
* tests/shell.scm: Test it.
* .dir-locals.el: Indent it nicely.
2018-11-28 23:07:03 -05:00
Timothy Sample b5e77fc27b Add support for '<sh-begin>'
* geesh/eval.scm (eval-sh): Handle '<sh-begin>'.
2018-11-28 23:07:03 -05:00
Timothy Sample d171a8cd15 Add support for setting variables
* geesh/eval.scm (eval-sh): Handle '<sh-set!>' forms.
2018-11-28 23:07:03 -05:00
Timothy Sample 5384009f75 Add redirect support
* geesh/eval.scm (eval-redir): New function.
(exp->thunk): New function.
(eval-sh): Handle '<sh-with-redirects>' forms.
2018-11-28 23:07:03 -05:00
Timothy Sample e6f732ada9 Add redirect semantics
* geesh/shell.scm (save-and-install-redirect!): New function.
(restore-saved-fdes!): New function.
(with-redirects): New public function.
* tests/shell.scm: Test it.
* .dir-locals.el: Indent it nicely.
2018-11-28 23:07:03 -05:00
Timothy Sample 9b879623de Import existing variables into the REPL
* geesh/repl.scm (run-repl): Use existing environment variables for
the initial environment.
2018-11-28 23:07:03 -05:00
Timothy Sample 737ed6a1b7 Add function for reading an 'environ'
* geesh/environment.scm (environ->alist): New function.
* tests/environment.scm: Test it.
2018-11-28 23:07:03 -05:00
Timothy Sample d7d26534b2 Remove prompt-printing from the REPL
This will have to be added again later, but for now it is getting in
the way of automated testing.

* geesh/repl.scm (run-repl): Do not print prompts.
2018-11-28 23:07:03 -05:00
Timothy Sample 93b238d9fd Use parser and interpreter in the REPL
* geesh/repl.scm (run-repl): Actually read and evaluate input.
2018-11-28 23:07:03 -05:00
Timothy Sample 549d1e7867 Remove REPL unit tests
In order to test the REPL in isolation, we would have to mock out the
parser and interpreter.  This is possible, but too much work for the
benefit (at least for now).

* tests/repl.scm: Deleted.
* Makefile.am: Remove it.
2018-11-28 23:07:03 -05:00
Timothy Sample 83c5d603ee Add eval module
* geesh/eval.scm: New file.
* Makefile.am: Add it.
2018-11-28 23:07:03 -05:00
Timothy Sample e1f139b841 Add support for built-ins, starting with 'echo'
* geesh/built-ins/echo.scm: New file.
* geesh/built-ins.scm: New file.
* Makefile.scm: Add them.
* geesh/shell.scm (exec-let): Include built-ins in command search.
* tests/shell.scm: Add a test for this.
2018-11-28 23:07:03 -05:00
Timothy Sample 7cc94e88e1 Add PATH searching
* geesh/shell.scm (slashless?) New function.
(split-search-path): New function.
(find-utility): New function.
(exec-let): Use them to search PATH for a utility when appropriate.
(exec): Update doc string.
* tests/shell.scm: Test it.
2018-11-28 23:07:03 -05:00
Timothy Sample 020adfc58b Add convenience function 'var-ref*'
* geesh/environment.scm (var-ref*): New public function.
* geesh/word.scm (word->qword): Use it to simplify things.
2018-11-28 23:07:03 -05:00