Also replace (*Frame).OutputChan with (*Frame).ValueOutput, which returns a
small interface for writing to the value output that is also aware when the
reader is gone.
Using a read-only variable as the target of an `except` clause should
highlight just the var name rather than the entire `try...except...`
statement.
Resolves#1258
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.
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.
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.
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.
- 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.
- 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.
Commit 734eb95 changed most uses of `fm.ports[x].` to a public method
that makes the intent clearer. This changes a couple of uses that were
overlooked by that prior change.