mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-05 03:17:50 +08:00
eval: Move all variable types to eval/vartypes.
This commit is contained in:
parent
b4a49732c3
commit
0472d61747
|
@ -11,7 +11,7 @@ import (
|
|||
|
||||
func makeBuiltinNs() Ns {
|
||||
ns := Ns{
|
||||
"_": BlackholeVariable{},
|
||||
"_": vartypes.NewBlackhole(),
|
||||
"pid": vartypes.NewRoVariable(types.String(strconv.Itoa(syscall.Getpid()))),
|
||||
"ok": vartypes.NewRoVariable(OK),
|
||||
"true": vartypes.NewRoVariable(types.Bool(true)),
|
||||
|
|
|
@ -193,6 +193,6 @@ func (cp *compiler) lvaluesOne(n *parse.Indexing, msg string) (bool, LValuesOpFu
|
|||
assocers[i+1] = assocer
|
||||
}
|
||||
}
|
||||
return []vartypes.Variable{&elemVariable{variable, assocers, indicies, nil}}
|
||||
return []vartypes.Variable{vartypes.NewElem(variable, assocers, indicies)}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -240,8 +240,8 @@ func (cp *compiler) form(n *parse.Form) OpFunc {
|
|||
for i, v := range saveVars {
|
||||
// XXX(xiaq): If the variable to save is a elemVariable, save
|
||||
// the outermost variable instead.
|
||||
if elemVar, ok := v.(*elemVariable); ok {
|
||||
v = elemVar.variable
|
||||
if u := vartypes.GetUnderlyingOfElem(v); u != nil {
|
||||
v = u
|
||||
saveVars[i] = v
|
||||
}
|
||||
val := v.Get()
|
||||
|
@ -376,7 +376,7 @@ func makeAssignmentOpFunc(variablesOp, restOp LValuesOp, valuesOp ValuesOp) OpFu
|
|||
|
||||
func fixNilVariables(vs []vartypes.Variable) {
|
||||
for _, v := range vs {
|
||||
if _, isBlackhole := v.(BlackholeVariable); isBlackhole {
|
||||
if vartypes.IsBlackhole(v) {
|
||||
continue
|
||||
}
|
||||
if v.Get() == nil {
|
||||
|
|
|
@ -102,7 +102,7 @@ func (ec *Frame) ResolveVar(ns, name string) vartypes.Variable {
|
|||
return vartypes.NewRoVariable(ExternalCmd{name[:len(name)-len(FnSuffix)]})
|
||||
}
|
||||
case "E":
|
||||
return envVariable{name}
|
||||
return vartypes.NewEnv(name)
|
||||
case "shared":
|
||||
if ec.DaemonClient == nil {
|
||||
throw(ErrStoreUnconnected)
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
package eval
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/elves/elvish/eval/types"
|
||||
"github.com/elves/elvish/eval/vartypes"
|
||||
)
|
||||
|
||||
// elemVariable is a (arbitrary nested) element.
|
||||
// XXX(xiaq): This is an ephemeral "variable" and is a bad hack.
|
||||
type elemVariable struct {
|
||||
variable vartypes.Variable
|
||||
assocers []types.Assocer
|
||||
indices []types.Value
|
||||
setValue types.Value
|
||||
}
|
||||
|
||||
func (ev *elemVariable) Set(v0 types.Value) error {
|
||||
v := v0
|
||||
// Evaluate the actual new value from inside out. See comments in
|
||||
// compile_lvalue.go for how assignment of indexed variables work.
|
||||
for i := len(ev.assocers) - 1; i >= 0; i-- {
|
||||
v = ev.assocers[i].Assoc(ev.indices[i], v)
|
||||
}
|
||||
err := ev.variable.Set(v)
|
||||
// XXX(xiaq): Remember the set value for use in Get.
|
||||
ev.setValue = v0
|
||||
return err
|
||||
}
|
||||
|
||||
func (ev *elemVariable) Get() types.Value {
|
||||
// XXX(xiaq): This is only called from fixNilVariables. We don't want to
|
||||
// waste time accessing the variable, so we simply return the value that was
|
||||
// set.
|
||||
return ev.setValue
|
||||
}
|
||||
|
||||
// envVariable represents an environment variable.
|
||||
type envVariable struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func (ev envVariable) Set(val types.Value) error {
|
||||
os.Setenv(ev.name, types.ToString(val))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ev envVariable) Get() types.Value {
|
||||
return types.String(os.Getenv(ev.name))
|
||||
}
|
||||
|
||||
// ErrGetBlackhole is raised when attempting to get the value of a blackhole
|
||||
// variable.
|
||||
var ErrGetBlackhole = errors.New("cannot get blackhole variable")
|
||||
|
||||
// BlackholeVariable represents a blackhole variable. Assignments to a blackhole
|
||||
// variable will be discarded, and getting a blackhole variable always returns
|
||||
// an empty string.
|
||||
type BlackholeVariable struct{}
|
||||
|
||||
func (bv BlackholeVariable) Set(types.Value) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bv BlackholeVariable) Get() types.Value {
|
||||
// TODO: Return a special placeholder value.
|
||||
return types.String("")
|
||||
}
|
27
eval/vartypes/blackhole.go
Normal file
27
eval/vartypes/blackhole.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
package vartypes
|
||||
|
||||
import "github.com/elves/elvish/eval/types"
|
||||
|
||||
type blackhole struct{}
|
||||
|
||||
func (blackhole) Set(types.Value) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (blackhole) Get() types.Value {
|
||||
// TODO: Return a special placeholder value.
|
||||
return types.String("")
|
||||
}
|
||||
|
||||
// NewBlackhole returns a blackhole variable. Assignments to a blackhole
|
||||
// variable will be discarded, and getting a blackhole variable always returns
|
||||
// an empty string.
|
||||
func NewBlackhole() Variable {
|
||||
return blackhole{}
|
||||
}
|
||||
|
||||
// IsBlackhole returns whether the variable is a blackhole variable.
|
||||
func IsBlackhole(v Variable) bool {
|
||||
_, ok := v.(blackhole)
|
||||
return ok
|
||||
}
|
47
eval/vartypes/elem.go
Normal file
47
eval/vartypes/elem.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
package vartypes
|
||||
|
||||
import (
|
||||
"github.com/elves/elvish/eval/types"
|
||||
)
|
||||
|
||||
type elem struct {
|
||||
variable Variable
|
||||
assocers []types.Assocer
|
||||
indices []types.Value
|
||||
setValue types.Value
|
||||
}
|
||||
|
||||
func (ev *elem) Set(v0 types.Value) error {
|
||||
v := v0
|
||||
// Evaluate the actual new value from inside out. See comments in
|
||||
// compile_lvalue.go for how assignment of indexed variables work.
|
||||
for i := len(ev.assocers) - 1; i >= 0; i-- {
|
||||
v = ev.assocers[i].Assoc(ev.indices[i], v)
|
||||
}
|
||||
err := ev.variable.Set(v)
|
||||
// XXX(xiaq): Remember the set value for use in Get.
|
||||
ev.setValue = v0
|
||||
return err
|
||||
}
|
||||
|
||||
func (ev *elem) Get() types.Value {
|
||||
// XXX(xiaq): This is only called from fixNilVariables. We don't want to
|
||||
// waste time accessing the variable, so we simply return the value that was
|
||||
// set.
|
||||
return ev.setValue
|
||||
}
|
||||
|
||||
// NewEleme represents an ephemeral variable that represents arbitrary nested
|
||||
// elements.
|
||||
func NewElem(v Variable, a []types.Assocer, i []types.Value) Variable {
|
||||
return &elem{v, a, i, types.String("")}
|
||||
}
|
||||
|
||||
// GetUnderlyingOfEleme gets the underlying variable from an element variable,
|
||||
// or nil if the argument is not an element variable.
|
||||
func GetUnderlyingOfElem(v Variable) Variable {
|
||||
if ev, ok := v.(*elem); ok {
|
||||
return ev.variable
|
||||
}
|
||||
return nil
|
||||
}
|
25
eval/vartypes/env.go
Normal file
25
eval/vartypes/env.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
package vartypes
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/elves/elvish/eval/types"
|
||||
)
|
||||
|
||||
// envVariable represents an environment variable.
|
||||
type envVariable struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func (ev envVariable) Set(val types.Value) error {
|
||||
os.Setenv(ev.name, types.ToString(val))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ev envVariable) Get() types.Value {
|
||||
return types.String(os.Getenv(ev.name))
|
||||
}
|
||||
|
||||
func NewEnv(name string) Variable {
|
||||
return envVariable{name}
|
||||
}
|
|
@ -1,15 +1,14 @@
|
|||
package eval
|
||||
package vartypes
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/elves/elvish/eval/types"
|
||||
"github.com/elves/elvish/eval/vartypes"
|
||||
)
|
||||
|
||||
func TestPtrVariable(t *testing.T) {
|
||||
v := vartypes.NewPtrVariable(types.Bool(true))
|
||||
v := NewPtrVariable(types.Bool(true))
|
||||
if v.Get() != types.Bool(true) {
|
||||
t.Errorf("PtrVariable.Get doesn't return initial value")
|
||||
}
|
||||
|
@ -22,14 +21,14 @@ func TestPtrVariable(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestValidatedPtrVariable(t *testing.T) {
|
||||
v := vartypes.NewValidatedPtrVariable(types.Bool(true), vartypes.ShouldBeBool)
|
||||
v := NewValidatedPtrVariable(types.Bool(true), ShouldBeBool)
|
||||
if v.Set(types.String("233")) == nil {
|
||||
t.Errorf("ValidatedPtrVariable.Set doesn't error when setting incompatible value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoVariable(t *testing.T) {
|
||||
v := vartypes.NewRoVariable(types.String("haha"))
|
||||
v := NewRoVariable(types.String("haha"))
|
||||
if v.Get() != types.String("haha") {
|
||||
t.Errorf("RoVariable.Get doesn't return initial value")
|
||||
}
|
||||
|
@ -50,7 +49,7 @@ func TestCbVariable(t *testing.T) {
|
|||
return nil
|
||||
}
|
||||
|
||||
v := vartypes.NewCallbackVariable(set, get)
|
||||
v := NewCallbackVariable(set, get)
|
||||
if v.Get() != types.String("cb") {
|
||||
t.Errorf("cbVariable doesn't return value from callback")
|
||||
}
|
||||
|
@ -69,7 +68,7 @@ func TestRoCbVariable(t *testing.T) {
|
|||
getCalled = true
|
||||
return types.String("cb")
|
||||
}
|
||||
v := vartypes.NewRoCallbackVariable(get)
|
||||
v := NewRoCallbackVariable(get)
|
||||
if v.Get() != types.String("cb") {
|
||||
t.Errorf("roCbVariable doesn't return value from callback")
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package vartypes
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestVariable(t *testing.T) {
|
||||
// TODO
|
||||
}
|
Loading…
Reference in New Issue
Block a user