diff --git a/vm/function.go b/vm/function.go index b331d92..4c8e079 100644 --- a/vm/function.go +++ b/vm/function.go @@ -1,6 +1,7 @@ package vm import ( + "errors" "fmt" "code.betamike.com/mediocregopher/ginger/gg" @@ -79,8 +80,6 @@ func FunctionFromGraph(g *gg.Graph, scope Scope) (Function, error) { return edgeFn(Identity(val)), nil } - name := *val.Name - if val.Equal(valNameIn) { return edgeFn(FunctionFunc(func(inArg Value) Value { return inArg @@ -89,15 +88,17 @@ func FunctionFromGraph(g *gg.Graph, scope Scope) (Function, error) { edgesIn := g.ValueIns(val.Value) - if l := len(edgesIn); l == 0 { - - val, err := scope.Resolve(name) + name := *val.Name - if err != nil { + if l := len(edgesIn); l == 0 { + resolvedVal, err := scope.Resolve(name) + if errors.Is(err, ErrNameNotDefined) { + return edgeFn(Identity(val)), nil + } else if err != nil { return nil, fmt.Errorf("resolving name %q from the outer scope: %w", name, err) } - return edgeFn(Identity(val)), nil + return edgeFn(Identity(resolvedVal)), nil } else if l != 1 { return nil, fmt.Errorf("resolved name %q to %d input edges, rather than one", name, l) @@ -123,7 +124,6 @@ func FunctionFromGraph(g *gg.Graph, scope Scope) (Function, error) { return valToEdgeFn(Value{Value: ggVal}) }, func(ggEdgeVal gg.OptionalValue, inEdgeFns []edgeFn) (edgeFn, error) { - if ggEdgeVal.Equal(valNameIf.Value) { if len(inEdgeFns) != 3 { diff --git a/vm/scope.go b/vm/scope.go index b71cdc2..72067d8 100644 --- a/vm/scope.go +++ b/vm/scope.go @@ -1,13 +1,18 @@ package vm import ( - "fmt" + "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. + // Resolve accepts a name and returns an Value, or returns + // ErrNameNotDefined. Resolve(string) (Value, error) } @@ -23,7 +28,7 @@ func (m ScopeMap) Resolve(name string) (Value, error) { v, ok := m[name] if !ok { - return Value{}, fmt.Errorf("%q not defined", name) + return Value{}, ErrNameNotDefined } return v, nil diff --git a/vm/vm_test.go b/vm/vm_test.go index 318d269..4578102 100644 --- a/vm/vm_test.go +++ b/vm/vm_test.go @@ -32,10 +32,16 @@ func TestVM(t *testing.T) { in: Value{Value: gg.Number(1)}, expErr: "name !foo cannot start with a '!'", }, + { + src: `{foo = bar; !out = foo;}`, + in: Value{}, + exp: Value{Value: gg.Name("bar")}, + }, } for i, test := range tests { t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Log(test.src) val, err := EvaluateSource( bytes.NewBufferString(test.src), test.in, GlobalScope, )