Replace validated variables with eval.NewVariableFromPtr.

This commit is contained in:
Qi Xiao 2018-02-05 22:36:29 -08:00
parent cb63d94eac
commit c84c455985
15 changed files with 32 additions and 135 deletions

View File

@ -1,13 +1,15 @@
package edit
import (
"github.com/elves/elvish/eval"
"github.com/elves/elvish/eval/types"
"github.com/elves/elvish/eval/vartypes"
"github.com/xiaq/persistent/hashmap"
)
var _ = RegisterVariable("abbr", func() vartypes.Variable {
return vartypes.NewValidatedPtr(types.EmptyMap, vartypes.ShouldBeMap)
m := types.EmptyMap
return eval.NewVariableFromPtr(&m)
})
func (ed *Editor) abbr() hashmap.Map {

View File

@ -92,7 +92,7 @@ func argCompleterVariable() vartypes.Variable {
for k, v := range argCompletersData {
m = m.Assoc(k, v)
}
return vartypes.NewValidatedPtr(m, vartypes.ShouldBeMap)
return eval.NewVariableFromPtr(&m)
}
func (ed *Editor) argCompleter() hashmap.Map {

View File

@ -26,7 +26,8 @@ func (ed *Editor) afterReadLine() vector.Vector {
}
func makeListVariable() vartypes.Variable {
return vartypes.NewValidatedPtr(types.EmptyList, vartypes.ShouldBeList)
l := types.EmptyList
return eval.NewVariableFromPtr(&l)
}
func callHooks(ev *eval.Evaler, li vector.Vector, args ...interface{}) {

View File

@ -10,8 +10,6 @@ import (
"github.com/elves/elvish/edit/ui"
"github.com/elves/elvish/eval"
"github.com/elves/elvish/eval/types"
"github.com/elves/elvish/eval/vartypes"
"github.com/elves/elvish/parse"
"github.com/elves/elvish/store/storedefs"
"github.com/elves/elvish/util"
@ -177,17 +175,13 @@ func convertListsToSet(lis ...vector.Vector) map[string]struct{} {
// Variables.
var _ = RegisterVariable("loc-hidden", func() vartypes.Variable {
return vartypes.NewValidatedPtr(types.EmptyList, vartypes.ShouldBeList)
})
var _ = RegisterVariable("loc-hidden", makeListVariable)
func (ed *Editor) locHidden() vector.Vector {
return ed.variables["loc-hidden"].Get().(vector.Vector)
}
var _ = RegisterVariable("loc-pinned", func() vartypes.Variable {
return vartypes.NewValidatedPtr(types.EmptyList, vartypes.ShouldBeList)
})
var _ = RegisterVariable("loc-pinned", makeListVariable)
func (ed *Editor) locPinned() vector.Vector {
return ed.variables["loc-pinned"].Get().(vector.Vector)

View File

@ -31,9 +31,8 @@ var (
}
_ = RegisterVariable("-matcher", func() vartypes.Variable {
m := types.EmptyMap.Assoc(
"", matchPrefix)
return vartypes.NewValidatedPtr(m, vartypes.ShouldBeMap)
m := types.MakeMapFromKV("", matchPrefix)
return eval.NewVariableFromPtr(&m)
})
)

View File

@ -4,12 +4,14 @@ import (
"math"
"strconv"
"github.com/elves/elvish/eval"
"github.com/elves/elvish/eval/vartypes"
"github.com/elves/elvish/util"
)
var _ = RegisterVariable("max-height", func() vartypes.Variable {
return vartypes.NewValidatedPtr("+Inf", vartypes.ShouldBeNumber)
maxHeight := math.Inf(1)
return eval.NewVariableFromPtr(&maxHeight)
})
func (ed *Editor) maxHeight() int {

View File

@ -395,13 +395,16 @@ func NarrowRead(ec *eval.Frame, args []interface{}, opts map[string]interface{})
eval.ScanOptsToStruct(opts, &l.opts)
for it := l.opts.Bindings.Iterator(); it.HasElem(); it.Next() {
k, f := it.Elem()
k, v := it.Elem()
key := ui.ToKey(k)
maybeThrow(eval.ShouldBeFn(f))
val, ok := v.(eval.Callable)
if !ok {
throwf("should be fn")
}
if l.opts.bindingMap == nil {
l.opts.bindingMap = make(map[ui.Key]eval.Callable)
}
l.opts.bindingMap[key] = f.(eval.Callable)
l.opts.bindingMap[key] = val
}
l.source = narrowGetSource(ec, source)

View File

@ -45,8 +45,8 @@ func PromptVariable() vartypes.Variable {
out <- &ui.Styled{"> ", ui.Styles{}}
}
}
return vartypes.NewValidatedPtr(
&eval.BuiltinFn{"default prompt", prompt}, eval.ShouldBeFn)
val := eval.Callable(&eval.BuiltinFn{"default prompt", prompt})
return eval.NewVariableFromPtr(&val)
}
// Prompt extracts $edit:prompt.
@ -73,8 +73,8 @@ func RpromptVariable() vartypes.Variable {
out <- &ui.Styled{rpromptStr, ui.Styles{"inverse"}}
}
return vartypes.NewValidatedPtr(
&eval.BuiltinFn{"default rprompt", rprompt}, eval.ShouldBeFn)
val := eval.Callable(&eval.BuiltinFn{"default rprompt", rprompt})
return eval.NewVariableFromPtr(&val)
}
// Rprompt extracts $edit:rprompt.

View File

@ -66,8 +66,8 @@ func makeBindings() map[string]vartypes.Variable {
bindings := map[string]vartypes.Variable{}
// XXX This abuses the builtin registry to get a list of mode names
for mode := range builtinMaps {
bindings[mode] = vartypes.NewValidatedPtr(
BindingTable{types.EmptyMap}, shouldBeBindingTable)
table := BindingTable{types.EmptyMap}
bindings[mode] = eval.NewVariableFromPtr(&table)
}
return bindings
}

View File

@ -148,9 +148,11 @@ func (op varOp) Invoke(fm *Frame) ([]vartypes.Variable, error) {
// XXX We depend on the fact that this variable will
// immeidately be set.
if strings.HasSuffix(op.name, FnSuffix) {
variable = vartypes.NewValidatedPtr(nil, ShouldBeFn)
val := Callable(nil)
variable = NewVariableFromPtr(&val)
} else if strings.HasSuffix(op.name, NsSuffix) {
variable = vartypes.NewValidatedPtr(nil, ShouldBeNs)
val := Ns(nil)
variable = NewVariableFromPtr(&val)
} else {
variable = vartypes.NewAny(nil)
}

View File

@ -41,11 +41,11 @@ func (ns Ns) Get(k interface{}) (interface{}, bool) {
}
func (ns Ns) SetFn(name string, v Callable) {
ns[name+FnSuffix] = vartypes.NewValidatedPtr(v, ShouldBeFn)
ns[name+FnSuffix] = NewVariableFromPtr(&v)
}
func (ns Ns) SetNs(name string, subns Ns) {
ns[name+NsSuffix] = vartypes.NewValidatedPtr(subns, ShouldBeNs)
func (ns Ns) SetNs(name string, v Ns) {
ns[name+NsSuffix] = NewVariableFromPtr(&v)
}
func addrOf(a interface{}) uintptr {

View File

@ -1,24 +0,0 @@
package eval
import (
"errors"
)
var (
errShouldBeFn = errors.New("should be function")
errShouldBeNs = errors.New("should be ns")
)
func ShouldBeFn(v interface{}) error {
if _, ok := v.(Callable); !ok {
return errShouldBeFn
}
return nil
}
func ShouldBeNs(v interface{}) error {
if _, ok := v.(Ns); !ok {
return errShouldBeNs
}
return nil
}

View File

@ -1,30 +0,0 @@
package vartypes
type validatedPtr struct {
valuePtr *interface{}
validator func(interface{}) error
}
type invalidValueError struct {
inner error
}
func (err invalidValueError) Error() string {
return "invalid value: " + err.inner.Error()
}
func NewValidatedPtr(v interface{}, vld func(interface{}) error) Variable {
return validatedPtr{&v, vld}
}
func (iv validatedPtr) Set(val interface{}) error {
if err := iv.validator(val); err != nil {
return invalidValueError{err}
}
*iv.valuePtr = val
return nil
}
func (iv validatedPtr) Get() interface{} {
return *iv.valuePtr
}

View File

@ -1,45 +0,0 @@
package vartypes
import (
"errors"
"strconv"
"github.com/xiaq/persistent/hashmap"
"github.com/xiaq/persistent/vector"
)
var (
errShouldBeList = errors.New("should be list")
errShouldBeMap = errors.New("should be map")
errShouldBeBool = errors.New("should be bool")
errShouldBeNumber = errors.New("should be number")
)
func ShouldBeList(v interface{}) error {
if _, ok := v.(vector.Vector); !ok {
return errShouldBeList
}
return nil
}
func ShouldBeMap(v interface{}) error {
if _, ok := v.(hashmap.Map); !ok {
return errShouldBeMap
}
return nil
}
func ShouldBeBool(v interface{}) error {
if _, ok := v.(bool); !ok {
return errShouldBeBool
}
return nil
}
func ShouldBeNumber(v interface{}) error {
if _, ok := v.(string); !ok {
return errShouldBeNumber
}
_, err := strconv.ParseFloat(string(v.(string)), 64)
return err
}

View File

@ -18,13 +18,6 @@ func TestPtrVariable(t *testing.T) {
}
}
func TestValidatedPtrVariable(t *testing.T) {
v := NewValidatedPtr(true, ShouldBeBool)
if v.Set("233") == nil {
t.Errorf("ValidatedPtrVariable.Set doesn't error when setting incompatible value")
}
}
func TestRoVariable(t *testing.T) {
v := NewRo("haha")
if v.Get() != "haha" {