From 9340e6da4eb7f304703c4a8df038543db1fd5d2f Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Wed, 14 Jun 2017 08:54:12 -0700 Subject: [PATCH] zcl: TraverseAbs through parent scopes An EvalContext can have a parent, so it's necessary to walk up until the root is reached in case a parent scope defines the name we're looking for. --- zcl/traversal.go | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/zcl/traversal.go b/zcl/traversal.go index ad67f28..474420d 100644 --- a/zcl/traversal.go +++ b/zcl/traversal.go @@ -79,28 +79,36 @@ func (t Traversal) TraverseAbs(ctx *EvalContext) (cty.Value, Diagnostics) { } } - val, exists := ctx.Variables[name] - if !exists { - suggestions := make([]string, 0, len(ctx.Variables)) - for k := range ctx.Variables { - suggestions = append(suggestions, k) - } - suggestion := nameSuggestion(name, suggestions) - if suggestion != "" { - suggestion = fmt.Sprintf(" Did you mean %q?", suggestion) - } - - return cty.DynamicVal, Diagnostics{ - { - Severity: DiagError, - Summary: "Unknown variable", - Detail: fmt.Sprintf("There is no variable named %q.%s", name, suggestion), - Subject: &root.SrcRange, - }, + thisCtx := ctx + for thisCtx != nil { + val, exists := thisCtx.Variables[name] + if exists { + return split.Rel.TraverseRel(val) } + thisCtx = thisCtx.parent } - return split.Rel.TraverseRel(val) + suggestions := make([]string, 0, len(ctx.Variables)) + thisCtx = ctx + for thisCtx != nil { + for k := range thisCtx.Variables { + suggestions = append(suggestions, k) + } + thisCtx = thisCtx.parent + } + suggestion := nameSuggestion(name, suggestions) + if suggestion != "" { + suggestion = fmt.Sprintf(" Did you mean %q?", suggestion) + } + + return cty.DynamicVal, Diagnostics{ + { + Severity: DiagError, + Summary: "Unknown variable", + Detail: fmt.Sprintf("There is no variable named %q.%s", name, suggestion), + Subject: &root.SrcRange, + }, + } } // IsRelative returns true if the receiver is a relative traversal, or false