mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-05 03:17:50 +08:00
7932f58201
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.
107 lines
2.8 KiB
Go
107 lines
2.8 KiB
Go
package eval
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/elves/elvish/pkg/diag"
|
|
"github.com/elves/elvish/pkg/parse"
|
|
)
|
|
|
|
// compiler maintains the set of states needed when compiling a single source
|
|
// file.
|
|
type compiler struct {
|
|
// Builtin namespace.
|
|
builtin *staticNs
|
|
// Lexical namespaces.
|
|
scopes []*staticNs
|
|
// Sources of captured variables.
|
|
captures []*staticUpNs
|
|
// Destination of warning messages. This is currently only used for
|
|
// deprecation messages.
|
|
warn io.Writer
|
|
// Deprecation registry.
|
|
deprecations deprecationRegistry
|
|
// Information about the source.
|
|
srcMeta parse.Source
|
|
}
|
|
|
|
type capture struct {
|
|
name string
|
|
// If true, the captured variable is from the immediate outer level scope,
|
|
// i.e. the local scope the lambda is evaluated in. Otherwise the captured
|
|
// variable is from a more outer level, i.e. the upvalue scope the lambda is
|
|
// evaluated in.
|
|
local bool
|
|
// Index to the captured variable.
|
|
index int
|
|
}
|
|
|
|
// Op represents an operation on a Frame. It is the result of compiling a piece
|
|
// of source.
|
|
type Op struct {
|
|
Exec func(*Frame) error
|
|
Src parse.Source
|
|
}
|
|
|
|
func compile(b, g *staticNs, tree parse.Tree, w io.Writer) (op Op, err error) {
|
|
g = g.clone()
|
|
gLenInit := len(g.names)
|
|
cp := &compiler{
|
|
b, []*staticNs{g}, []*staticUpNs{new(staticUpNs)},
|
|
w, newDeprecationRegistry(), tree.Source}
|
|
defer func() {
|
|
r := recover()
|
|
if r == nil {
|
|
return
|
|
} else if e := GetCompilationError(r); e != nil {
|
|
// Save the compilation error and stop the panic.
|
|
err = e
|
|
} else {
|
|
// Resume the panic; it is not supposed to be handled here.
|
|
panic(r)
|
|
}
|
|
}()
|
|
chunkOp := cp.chunkOp(tree.Root)
|
|
scopeOp := wrapScopeOp(chunkOp, g.names[gLenInit:])
|
|
|
|
return Op{scopeOp.exec, tree.Source}, nil
|
|
}
|
|
|
|
const compilationErrorType = "compilation error"
|
|
|
|
func (cp *compiler) errorpf(r diag.Ranger, format string, args ...interface{}) {
|
|
// The panic is caught by the recover in compile above.
|
|
panic(&diag.Error{
|
|
Type: compilationErrorType,
|
|
Message: fmt.Sprintf(format, args...),
|
|
Context: *diag.NewContext(cp.srcMeta.Name, cp.srcMeta.Code, r)})
|
|
}
|
|
|
|
// GetCompilationError returns a *diag.Error if the given value is a compilation
|
|
// error. Otherwise it returns nil.
|
|
func GetCompilationError(e interface{}) *diag.Error {
|
|
if e, ok := e.(*diag.Error); ok && e.Type == compilationErrorType {
|
|
return e
|
|
}
|
|
return nil
|
|
}
|
|
func (cp *compiler) thisScope() *staticNs {
|
|
return cp.scopes[len(cp.scopes)-1]
|
|
}
|
|
|
|
func (cp *compiler) pushScope() (*staticNs, *staticUpNs) {
|
|
sc := new(staticNs)
|
|
up := new(staticUpNs)
|
|
cp.scopes = append(cp.scopes, sc)
|
|
cp.captures = append(cp.captures, up)
|
|
return sc, up
|
|
}
|
|
|
|
func (cp *compiler) popScope() {
|
|
cp.scopes[len(cp.scopes)-1] = nil
|
|
cp.scopes = cp.scopes[:len(cp.scopes)-1]
|
|
cp.captures[len(cp.captures)-1] = nil
|
|
cp.captures = cp.captures[:len(cp.captures)-1]
|
|
}
|