Commit Graph

316 Commits

Author SHA1 Message Date
Qi Xiao
2defb9c53a pkg/eval: Correctly handle variable lookup error during runtime.
This fixes #1214.
2021-01-10 13:30:07 +00:00
Qi Xiao
56ceeedd21 pkg/eval: Store variable deletion information in *Ns.
This fixes #1213.
2021-01-10 00:54:02 +00:00
Qi Xiao
8d1a6b34db pkg/eval/evaltest: Support testing evaluation of multiple code pieces.
Also use this to simplify TestMultipleEval in pkg/eval.
2021-01-10 00:08:58 +00:00
Qi Xiao
402861fcfb eval/evaltest: Simplify EvalAndCollect. 2021-01-10 00:04:07 +00:00
Qi Xiao
d84e9801b5 Don't compile the arguments of special commands twice.
This fixes #1204.
2021-01-09 23:33:24 +00:00
Qi Xiao
28f86fefc6 Fix non-first uses of a module.
The implementation of useOp has not been updated correctly to accomodate the
fact that the namespaces are no longer modified in place.

This fixes #1212.
2021-01-09 23:17:26 +00:00
Qi Xiao
02d9252b5d pkg/eval: Return bool instead error from (*Evaler)'s PurelyEval* methods. 2021-01-09 16:05:04 +00:00
Qi Xiao
9991b08fe0 Fix panic in completion of non-existing namespace variable.
This fixes #1209.
2021-01-09 15:54:12 +00:00
Qi Xiao
363b712f66 pkg/eval: Eliminate in-place mutations of *Ns.
This commit replaces scopeOp, the only remaining place that mutates *Ns in
place, with nsOp, which performs copy-on-write for *Ns.

As a result, the "eval" command no longer mutates the passed namespace. The
default namespace it uses is also changed to match the default of "-source" (an
amalgamated namespace from the local and upvalue scopes), making "-source $file"
equivalent to "eval (slurp <$file)", and formally deprecated.

Another result is that (*Evaler).Eval can now guard the mutation of the global
namespace with the mutex, making it concurrency-safe to execute multiple sources
that touch the global namespace.

This fixes #1137.
2021-01-09 15:02:15 +00:00
Qi Xiao
066b48cfd2 Make all builtin functions and subnamespaces read-only.
This fixes #1211.
2021-01-09 00:41:42 +00:00
Qi Xiao
af906f1d76 pkg/eval: Change all the *Op types to return Exception instead of error.
Also change the variable name used to keep the Exception returned from "err" to
"exc".

This uncovers several error scenarios that were not returning Exception, and
would result in the absense of stack traces when such errors occur.
2021-01-09 00:25:32 +00:00
Qi Xiao
b77a052e7e pkg/eval: Make Exception an interface.
This change is a preparation step for refining all *Op types to return Exception
as the error.

Keeping Exception as a struct type will make such a change error-prone, since
a (*Exception)(nil) != error(nil), so if an *Op returns a nil *Exception, it
is not nil if the return value is stored in an error-typed variable.
2021-01-08 00:56:45 +00:00
Kurtis Rader
5564c8f754 Fix handling of unexpected errors
Doing something like the following is likely to result in too many open
files (assuming `ulimit -n` == 256) resulting in a panic:

    > fn fact [n]{ if (== $n 0) { put 1 } else { put (* $n (fact (- $n 1))) } }
    > fact 60
    panic: interface conversion: error is *os.SyscallError, not
    *eval.Exception

    goroutine 24161 [running]:
    github.com/elves/elvish/pkg/eval.(*pipelineOp).exec.func1(0x152a5a0,
    0xc000dca210, 0xc000a44e70, 0xc00057b540, 0xc001030590, 0x203000)
        github.com/elves/elvish/pkg/eval/compile_effect.go:153 +0x152
    created by github.com/elves/elvish/pkg/eval.(*pipelineOp).exec
        github.com/elves/elvish/pkg/eval/compile_effect.go:149 +0x225
    Exception: elvish exited with 2

Fixes #1208
2021-01-07 22:34:22 +00:00
Qi Xiao
9af4c83bf6 pkg/eval: Minor cleanups. 2021-01-05 16:05:34 +00:00
Qi Xiao
af0c22c47a Move pkg/eval/resolve.go to pkg/edit, and add more introspection methods on *Ns. 2021-01-05 15:43:26 +00:00
Qi Xiao
5c55e72e78 pkg/eval: Update comments about the Elvish-Go interface. 2021-01-05 05:23:28 +00:00
Qi Xiao
2033600881 pkg/eval: Clean up Port related code. 2021-01-05 05:23:17 +00:00
Qi Xiao
6e8ecc8bd5 pkg/eval: Cleanups for reducing the API surface area number of files.
- Move NewEnvListVar to pkg/eval/vars.

- De-export GlobPattern, GlobFlag and ExternalCmd.

- Merge editor.go and chdir.go into eval.go, value_helper.go into compile_value.go.

- Remove eval_internal_test.go and replace it with a new test for $pid.
2021-01-05 04:33:52 +00:00
Qi Xiao
75baa0b5a2 pkg/eval: Remove (*Ns).Append.
This change makes Ns immutable from the exposed API. Internally there is exactly
one place that still mutates Ns, in scopeOp; this will be addressed later.
2021-01-05 01:09:04 +00:00
Qi Xiao
a2790af67a pkg/eval: Clean up the structure and methods of Evaler and Frame.
- Make Evaler mostly thread-safe. The only remaining thread-unsafe part is the
  modules field, which is more tricky than other fields.

- Remove the state and evalerScopes type, and move their fields into Evaler.

- Expose valuePrefix via a get method, and change PortsFromFiles to take the
  prefix instead of a *Evaler. Also expose a PortsFromStdFiles.

- Make Evaler a normal field of Frame, instead of an embedded field. This makes
  access to global states more explicit.
2021-01-05 00:22:09 +00:00
Qi Xiao
0a3d7ac02e pkg/eval: Fix $args.
This fixes #1207.
2021-01-04 21:04:17 +00:00
Qi Xiao
6c764d31d5 pkg/eval: Add mutex to Evaler, and remove that of deprecationRegistry.
The Evaler keeps global states and needs to be accessed concurrently. Mutations
to global states have fairly low throughput, so it makes sense to use a single
mutex.

On the other hand, the compiler is always used on a single thread, so it does
not need any mutex protection, so there is no need to put the mutex inside
deprecationRegistry.
2021-01-04 15:55:26 +00:00
Qi Xiao
b44bbd9668 pkg/eval: Remove superfluous tests. 2021-01-04 14:36:53 +00:00
Qi Xiao
1be25a240c pkg/eval: Internal cleanups.
- Remove the Op type; it is no longer used by any code outside the eval package
  and its use within the package is limited.

- Replace (*Evaler).execOp with (*Evaler).prepareFrame.
2021-01-04 14:17:27 +00:00
Qi Xiao
01612e291b pkg/eval: Clean up closure call implementation.
- Remove reliance on scopeOp, concentrating all the scope for creating the local
  scope in (*closure).call.

- Check options at the very beginning, and include all unsupported options in the
  error.
2021-01-04 13:46:00 +00:00
Qi Xiao
685f0a2593 Fix the example in the elvdoc for -source. 2021-01-03 22:59:24 +00:00
Qi Xiao
d844d80ebb Fix format of elvdoc for -source. 2021-01-03 22:36:13 +00:00
Qi Xiao
09b8dcdf2f Handle the global namespace correctly in the -source command.
The -source command now runs with a temporary namespace that is amalgamated
from the local and up namespace of the caller -source; this means that it can
no longer mutate its caller's local scope, which is the only possible sensible
behavior anyway.

This fixes #1202.
2021-01-03 22:31:55 +00:00
Qi Xiao
086038fa0f pkg/eval: Remove (*Evaler).Close. 2021-01-03 20:55:04 +00:00
Qi Xiao
5fbeb781ff pkg/eval: Remove (*Frame).Eval. 2021-01-03 20:54:35 +00:00
Qi Xiao
d140e98f3c Fix definition of recursive functions with fn.
Also document explicitly that the function body may refer to the function being
defined.

This fixes #1206.
2021-01-03 20:44:52 +00:00
Qi Xiao
7932f58201 pkg/eval: Add a (*Evaler).Call method for calling a function.
Most of the places that need to directly call a function is in the edit package,
which need to call user-defined callbacks.

This change eliminates most call sites of NewTopFrame (including all call sites
outside the eval package). Remove the function and inline it in the remaining
few call sites.

Remove NewTopFrame means that the eval package no longer offers other packages
a way to construct Frame instances. This is intended: Frame is a relatively
low-level concept, and all code outside the eval package now uses the more
high-level Eval, Call, Check/CheckTree methods of *Evaler. The most notable
exception is packages that implement modules; they may still use Frame to access
the information kept in it, but they never construct Frame instances.

In future, the Frame type can be changed to an interface.
2021-01-03 18:57:11 +00:00
Qi Xiao
261861888a pkg/eval: Support specifying an alternative global Ns in EvalCfg.
This feature supersedes the CompileWithGlobal method, and simplifies the only
use of that method in pkg/edit, where the default binding is evaluated using the
edit: namespace as the global Ns.
2021-01-03 17:20:56 +00:00
Qi Xiao
9323912c98 pkg/eval: De-export (*Evaler).Compile, and expose a (*Evaler).CheckTree.
The Compile method was used only by the syntax highlighting code to find
compilation errors. Since it only needs the error part but not the Op part,
provide an alternative API that only exposes the error.
2021-01-03 17:05:15 +00:00
Qi Xiao
3f6b5da2b9 pkg/shell: Print both parse and compile errors when using -compileonly -json.
The new (*Evaler).Check method allows the implementation to be simpler.

Also test the JSON format feature in an integration test instead of unit test;
this makes it unnecessary for the eval package to expose NewCompilationError.
2021-01-03 16:32:04 +00:00
Qi Xiao
7663d9a0ce pkg/eval: Replace the NoExecute option of (*Evaler).Eval with a new Check method.
This method has the property that it always tries to compile the code even if
there is a parse failure. This is the more desirable behavior when checking
code: if there is a parse failure near the end of a chunk of code, the user may
like to learn about compile errors earlier in the code.
2021-01-03 16:01:24 +00:00
Qi Xiao
2d971d2cd0 pkg/eval: De-export (*Evaler).ParseAndCompile.
All code outside the eval package now uses (*Evaler).Eval to evaluate code, and
do not need this method anymore.
2021-01-02 02:41:36 +00:00
Qi Xiao
5642dc3756 pkg/eval: Test compile-time deprecations using (*Evaler).Eval. 2021-01-02 02:39:38 +00:00
Qi Xiao
e43492ba17 pkg: Move edit.capturePort to eval.CaptureStringPort. 2021-01-02 02:39:03 +00:00
Qi Xiao
9b5dc09f14 pkg/eval: In (*Evaler).Eval, replace nil ports with placeholder ports.
This allows callers of this method to only supply the ports it is interested in
setting and leave the rest either unspecified or nil.
2021-01-02 02:22:44 +00:00
Qi Xiao
7cd2745c03 Deflake the test against "sleep" by delaying the SIGINT slightly.
The test contained a race condition: when the mock TimeAfter implementation
sends the process a SIGINT, the "sleep" function may not have entered the
"select" block, meaning that the signal will be ignored.

This commit works around this by waiting 1ms (scaled with
$ELVISH_TEST_TIME_SCALE) before sending SIGINT. The test now consistently
succeeds on my local laptop.
2021-01-02 01:49:40 +00:00
Qi Xiao
4f037aeb2a pkg/eval: Implement output capture in terms of simpler primitives.
Introduces two functions, PipePort and CapturePort, and implement output capture
in terms of them. These two functions return *Port instances, which can also be
used in (*Evaler).Eval calls.
2021-01-02 01:40:04 +00:00
Qi Xiao
dc59cbfeb4 pkg/eval: Make (*Evaler).Eval accept a Source instead of an Op.
Most callers can now call it with the source to evaluate, without having to call
ParseAndCompile first themselves.
2021-01-02 00:10:26 +00:00
Qi Xiao
5f0e4fc196 pkg/eval: Remove the bool return value of GetCompilationError.
This is done for consistency with parse.GetError.
2021-01-01 23:27:11 +00:00
Qi Xiao
e4cebea152 pkg/eval: Simplify the tests for -source by running them in a temp dir. 2020-12-29 13:46:03 +00:00
Qi Xiao
3615988408 Change signature of "exec" and "fg" on Windows to match that on Unix.
This fixes #1195.
2020-12-26 22:59:18 +00:00
Qi Xiao
3e29266ee0 pkg/eval: Remove unused (*Evaler).InstallBundled. 2020-12-26 03:26:10 +00:00
Qi Xiao
719314c029 pkg/eval: Various cleanups for qname handling code. 2020-12-25 22:31:52 +00:00
Qi Xiao
8613527450 pkg/eval: Deduplicate code for command head resolution. 2020-12-25 21:30:57 +00:00
Qi Xiao
9a6d53e012 Fix Windows build. 2020-12-25 17:58:03 +00:00