63 lines
1.2 KiB
Go
63 lines
1.2 KiB
Go
package vm
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
// Scope encapsulates a set of name->Value mappings.
|
|
type Scope interface {
|
|
|
|
// Resolve accepts a name and returns an Value.
|
|
Resolve(string) (Value, error)
|
|
|
|
// NewScope returns a new Scope which sub-operations within this Scope
|
|
// should use for themselves.
|
|
NewScope() Scope
|
|
}
|
|
|
|
// 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{}, fmt.Errorf("%q not defined", name)
|
|
}
|
|
|
|
return v, nil
|
|
}
|
|
|
|
// NewScope returns the ScopeMap as-is.
|
|
func (m ScopeMap) NewScope() Scope {
|
|
return m
|
|
}
|
|
|
|
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)
|
|
}
|