zclsyntax: Expression.Variables implementation using AST walk

This function is effectively the implementation of Variables for all
expressions, but unfortunately we still need to declare a wrapper around
it as a method on every single expression type.
This commit is contained in:
Martin Atkins 2017-05-24 08:05:52 -07:00
parent dabdb3d059
commit 007b38797b
2 changed files with 51 additions and 7 deletions

View File

@ -25,8 +25,6 @@ var assertExprImplExpr zcl.Expression = Expression(nil)
type LiteralValueExpr struct {
Val cty.Value
SrcRange zcl.Range
hasNoVariables
}
func (e *LiteralValueExpr) walkChildNodes(w internalWalkFunc) {
@ -41,11 +39,37 @@ func (e *LiteralValueExpr) Range() zcl.Range {
return e.SrcRange
}
// Embed this in an expression struct to get a default implementation of
// Variables that returns no variables.
type hasNoVariables struct {
func (e *LiteralValueExpr) StartRange() zcl.Range {
return e.SrcRange
}
func (e hasNoVariables) Variables() []zcl.Traversal {
return nil
func (e *LiteralValueExpr) Variables() []zcl.Traversal {
return Variables(e)
}
// ScopeTraversalExpr is an Expression that retrieves a value from the scope
// using a traversal.
type ScopeTraversalExpr struct {
Traversal zcl.Traversal
SrcRange zcl.Range
}
func (e *ScopeTraversalExpr) walkChildNodes(w internalWalkFunc) {
// Scope traversals have no child nodes
}
func (e *ScopeTraversalExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
panic("ScopeTraversalExpr.Value not yet implemented")
}
func (e *ScopeTraversalExpr) Range() zcl.Range {
return e.SrcRange
}
func (e *ScopeTraversalExpr) StartRange() zcl.Range {
return e.SrcRange
}
func (e *ScopeTraversalExpr) Variables() []zcl.Traversal {
return Variables(e)
}

View File

@ -0,0 +1,20 @@
package zclsyntax
import (
"github.com/apparentlymart/go-zcl/zcl"
)
// Variables returns all of the variables referenced within a given experssion.
//
// This is the implementation of the "Variables" method on every native
// expression.
func Variables(expr Expression) []zcl.Traversal {
var vars []zcl.Traversal
VisitAll(expr, func(n Node) zcl.Diagnostics {
if ste, ok := n.(*ScopeTraversalExpr); ok {
vars = append(vars, ste.Traversal)
}
return nil
})
return vars
}