ginger/vm/scope.go

59 lines
1.2 KiB
Go

package vm
import (
"errors"
)
// ErrNameNotDefined is returned from Scope.Resolve when a name could not be
// resolved within a Scope.
var ErrNameNotDefined = errors.New("not defined")
// Scope encapsulates a set of name->Value mappings.
type Scope interface {
// Resolve accepts a name and returns an Value, or returns
// ErrNameNotDefined.
Resolve(string) (Value, error)
}
// ScopeMap implements the Scope interface.
type ScopeMap map[string]Value
var _ Scope = ScopeMap{}
// Resolve uses the given name as a key into the ScopeMap map, and
// returns the Operation held there for the key, if any.
func (m ScopeMap) Resolve(name string) (Value, error) {
v, ok := m[name]
if !ok {
return Value{}, ErrNameNotDefined
}
return v, nil
}
type scopeWith struct {
Scope // parent
name string
val Value
}
// ScopeWith returns a copy of the given Scope, except that evaluating the given
// name will always return the given Value.
func ScopeWith(scope Scope, name string, val Value) Scope {
return &scopeWith{
Scope: scope,
name: name,
val: val,
}
}
func (s *scopeWith) Resolve(name string) (Value, error) {
if name == s.name {
return s.val, nil
}
return s.Scope.Resolve(name)
}