mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-01 08:42:55 +08:00
eval: Introduce an Op type that combines effectOp and Source.
This commit is contained in:
parent
21299a200c
commit
cdd5576760
|
@ -101,7 +101,7 @@ func source(fm *Frame, fname string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return fm.Eval(op)
|
||||
return fm.EvalOp(op)
|
||||
}
|
||||
|
||||
func readFileUTF8(fname string) (string, error) {
|
||||
|
|
|
@ -314,7 +314,7 @@ func loadModule(fm *Frame, name string) (Ns, error) {
|
|||
// Load the namespace before executing. This prevent circular "use"es from
|
||||
// resulting in an infinite recursion.
|
||||
fm.Evaler.modules[name] = modGlobal
|
||||
err = newFm.Eval(op)
|
||||
err = newFm.EvalOp(op)
|
||||
if err != nil {
|
||||
// Unload the namespace.
|
||||
delete(fm.modules, name)
|
||||
|
|
|
@ -25,10 +25,10 @@ type compiler struct {
|
|||
srcMeta *Source
|
||||
}
|
||||
|
||||
func compile(b, g staticNs, n *parse.Chunk, src *Source) (op effectOp, err error) {
|
||||
func compile(b, g staticNs, n *parse.Chunk, src *Source) (op Op, err error) {
|
||||
cp := &compiler{b, []staticNs{g}, make(staticNs), 0, 0, src}
|
||||
defer util.Catch(&err)
|
||||
return cp.chunkOp(n), nil
|
||||
return Op{cp.chunkOp(n), src}, nil
|
||||
}
|
||||
|
||||
func (cp *compiler) compiling(n parse.Node) {
|
||||
|
|
21
eval/eval.go
21
eval/eval.go
|
@ -203,11 +203,11 @@ func (fm *Frame) growPorts(n int) {
|
|||
// be used to call functions with stdPorts. Make the Evaler initialize a
|
||||
// stdPorts on construction, instead of in this function, so that NewTopFrame
|
||||
// does not require the caller to supply the ports.
|
||||
func (ev *Evaler) EvalWithStdPorts(op effectOp, src *Source) error {
|
||||
func (ev *Evaler) EvalWithStdPorts(op Op) error {
|
||||
stdPorts := newStdPorts(
|
||||
os.Stdin, os.Stdout, os.Stderr, ev.state.getValuePrefix())
|
||||
defer stdPorts.close()
|
||||
return ev.Eval(op, stdPorts.ports[:], src)
|
||||
return ev.Eval(op, stdPorts.ports[:])
|
||||
}
|
||||
|
||||
// Eval sets up the Evaler with the given ports and evaluates an Op. The
|
||||
|
@ -216,7 +216,7 @@ func (ev *Evaler) EvalWithStdPorts(op effectOp, src *Source) error {
|
|||
// TODO(xiaq): This method only differs from eval in that it sets up intCh for
|
||||
// relaying interrupts and puts Elvish in the foreground afterwards. Factor out
|
||||
// those logics.
|
||||
func (ev *Evaler) Eval(op effectOp, ports []*Port, src *Source) error {
|
||||
func (ev *Evaler) Eval(op Op, ports []*Port) error {
|
||||
// Set up intCh.
|
||||
stopSigGoroutine := make(chan struct{})
|
||||
sigGoRoutineDone := make(chan struct{})
|
||||
|
@ -242,7 +242,7 @@ func (ev *Evaler) Eval(op effectOp, ports []*Port, src *Source) error {
|
|||
close(sigGoRoutineDone)
|
||||
}()
|
||||
|
||||
err := ev.eval(op, ports, src)
|
||||
err := ev.eval(op, ports)
|
||||
|
||||
close(stopSigGoroutine)
|
||||
<-sigGoRoutineDone
|
||||
|
@ -261,17 +261,14 @@ func (ev *Evaler) Eval(op effectOp, ports []*Port, src *Source) error {
|
|||
|
||||
// eval evaluates a chunk node n. The supplied name and text are used in
|
||||
// diagnostic messages.
|
||||
func (ev *Evaler) eval(op effectOp, ports []*Port, src *Source) error {
|
||||
ec := NewTopFrame(ev, src, ports)
|
||||
return ec.Eval(op)
|
||||
func (ev *Evaler) eval(op Op, ports []*Port) error {
|
||||
ec := NewTopFrame(ev, op.src, ports)
|
||||
return ec.Eval(op.inner)
|
||||
}
|
||||
|
||||
// Compile compiles Elvish code in the global scope. If the error is not nil, it
|
||||
// always has type CompilationError.
|
||||
//
|
||||
// TODO: Return a wrapper around effectOp that includes the Source passed in, so
|
||||
// that the Source struct does not need to be supplied again when calling Eval.
|
||||
func (ev *Evaler) Compile(n *parse.Chunk, src *Source) (effectOp, error) {
|
||||
func (ev *Evaler) Compile(n *parse.Chunk, src *Source) (Op, error) {
|
||||
return compile(ev.Builtin.static(), ev.Global.static(), n, src)
|
||||
}
|
||||
|
||||
|
@ -285,5 +282,5 @@ func (ev *Evaler) EvalSource(src *Source) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ev.EvalWithStdPorts(op, src)
|
||||
return ev.EvalWithStdPorts(op)
|
||||
}
|
||||
|
|
|
@ -125,7 +125,18 @@ func (fm *Frame) fork(name string) *Frame {
|
|||
}
|
||||
}
|
||||
|
||||
// Eval evaluates an op. It does so in a protected environment so that
|
||||
// EvalOp evaluates an Op. It is like Eval except that it sets fm.srcMeta
|
||||
// temporarily to op.src during the evaluation.
|
||||
func (fm *Frame) EvalOp(op Op) error {
|
||||
oldSrc := fm.srcMeta
|
||||
fm.srcMeta = op.src
|
||||
defer func() {
|
||||
fm.srcMeta = oldSrc
|
||||
}()
|
||||
return fm.Eval(op.inner)
|
||||
}
|
||||
|
||||
// Eval evaluates an effectOp. It does so in a protected environment so that
|
||||
// exceptions thrown are wrapped in an Error.
|
||||
func (fm *Frame) Eval(op effectOp) (err error) {
|
||||
defer catch(&err, fm)
|
||||
|
|
11
eval/op.go
11
eval/op.go
|
@ -2,7 +2,14 @@ package eval
|
|||
|
||||
import "github.com/elves/elvish/eval/vars"
|
||||
|
||||
// An operation on an Frame that produces a side effect.
|
||||
// Op represents an operation on a Frame. It is the result of compiling a piece
|
||||
// of source.
|
||||
type Op struct {
|
||||
inner effectOp
|
||||
src *Source
|
||||
}
|
||||
|
||||
// An operation on a Frame that produces a side effect.
|
||||
type effectOp struct {
|
||||
body opBody
|
||||
begin, end int
|
||||
|
@ -36,7 +43,7 @@ func (op valuesOp) exec(fm *Frame) ([]interface{}, error) {
|
|||
return op.body.invoke(fm)
|
||||
}
|
||||
|
||||
// An operation on an Frame that produce Variable's.
|
||||
// An operation on a Frame that produce Variable's.
|
||||
type lvaluesOp struct {
|
||||
body lvaluesOpBody
|
||||
begin, end int
|
||||
|
|
|
@ -180,7 +180,7 @@ func evalAndCollect(t *testing.T, ev *Evaler, texts []string, chsize int) ([]int
|
|||
{File: os.Stderr, Chan: BlackholeChan},
|
||||
}
|
||||
|
||||
ex = ev.eval(op, ports, src)
|
||||
ex = ev.eval(op, ports)
|
||||
close(outCh)
|
||||
<-outDone
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ func evalAndCollect(t *testing.T, ev *Evaler, texts []string, chsize int) ([]int
|
|||
return outs, bytesOut, ex
|
||||
}
|
||||
|
||||
func mustParseAndCompile(t *testing.T, ev *Evaler, src *Source) effectOp {
|
||||
func mustParseAndCompile(t *testing.T, ev *Evaler, src *Source) Op {
|
||||
n, err := parse.Parse(src.name, src.code)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse(%q) error: %s", src.code, err)
|
||||
|
|
|
@ -49,7 +49,7 @@ func script(ev *eval.Evaler, args []string, cmd, compileOnly bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
return ev.EvalWithStdPorts(op, src)
|
||||
return ev.EvalWithStdPorts(op)
|
||||
}
|
||||
|
||||
var errSourceNotUTF8 = errors.New("source is not UTF-8")
|
||||
|
|
|
@ -117,7 +117,7 @@ func evalAndCollect(ev *eval.Evaler, code string) (
|
|||
{File: outFile, Chan: outChan},
|
||||
{File: errFile, Chan: eval.BlackholeChan},
|
||||
}
|
||||
err = ev.Eval(op, ports, src)
|
||||
err = ev.Eval(op, ports)
|
||||
|
||||
outFile.Close()
|
||||
close(outChan)
|
||||
|
|
Loading…
Reference in New Issue
Block a user