59 lines
1.2 KiB
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)
|
|
}
|