@@ -20,22 +20,22 @@ type ContextMeta struct {
20
20
OriginalWorkingDir string
21
21
}
22
22
23
- type CallGraph struct {
24
- edges map [string ]addrs.Reference
23
+ type CallStack struct {
24
+ addrs map [string ]addrs.Reference
25
25
stack []string
26
26
}
27
27
28
- func NewCallGraph () * CallGraph {
29
- return & CallGraph {
30
- edges : make (map [string ]addrs.Reference ),
28
+ func NewCallStack () * CallStack {
29
+ return & CallStack {
30
+ addrs : make (map [string ]addrs.Reference ),
31
31
stack : make ([]string , 0 ),
32
32
}
33
33
}
34
34
35
- func (g * CallGraph ) Add (addr addrs.Reference ) hcl.Diagnostics {
35
+ func (g * CallStack ) Push (addr addrs.Reference ) hcl.Diagnostics {
36
36
g .stack = append (g .stack , addr .Subject .String ())
37
37
38
- if _ , exists := g .edges [addr .Subject .String ()]; exists {
38
+ if _ , exists := g .addrs [addr .Subject .String ()]; exists {
39
39
return hcl.Diagnostics {
40
40
{
41
41
Severity : hcl .DiagError ,
@@ -45,20 +45,30 @@ func (g *CallGraph) Add(addr addrs.Reference) hcl.Diagnostics {
45
45
},
46
46
}
47
47
}
48
- g .edges [addr .Subject .String ()] = addr
48
+ g .addrs [addr .Subject .String ()] = addr
49
49
return hcl.Diagnostics {}
50
50
}
51
51
52
- func (g * CallGraph ) String () string {
52
+ func (g * CallStack ) Pop () {
53
+ if g .Empty () {
54
+ panic ("cannot pop from empty call graph" )
55
+ }
56
+
57
+ addr := g .stack [len (g .stack )- 1 ]
58
+ g .stack = g .stack [:len (g .stack )- 1 ]
59
+ delete (g .addrs , addr )
60
+ }
61
+
62
+ func (g * CallStack ) String () string {
53
63
return strings .Join (g .stack , " -> " )
54
64
}
55
65
56
- func (g * CallGraph ) Empty () bool {
66
+ func (g * CallStack ) Empty () bool {
57
67
return len (g .stack ) == 0
58
68
}
59
69
60
- func (g * CallGraph ) Clear () {
61
- g .edges = make (map [string ]addrs.Reference )
70
+ func (g * CallStack ) Clear () {
71
+ g .addrs = make (map [string ]addrs.Reference )
62
72
g .stack = make ([]string , 0 )
63
73
}
64
74
@@ -67,7 +77,7 @@ type Evaluator struct {
67
77
ModulePath addrs.ModuleInstance
68
78
Config * Config
69
79
VariableValues map [string ]map [string ]cty.Value
70
- CallGraph * CallGraph
80
+ CallStack * CallStack
71
81
}
72
82
73
83
func (e * Evaluator ) EvaluateExpr (expr hcl.Expression , wantType cty.Type , keyData InstanceKeyEvalData ) (cty.Value , hcl.Diagnostics ) {
@@ -298,21 +308,16 @@ func (d *evaluationData) GetLocalValue(addr addrs.LocalValue, rng hcl.Range) (ct
298
308
return cty .DynamicVal , diags
299
309
}
300
310
301
- entry := d .Evaluator .CallGraph .Empty ()
302
311
// Build a callgraph for circular reference detection only when getting a local value.
303
- if diags := d .Evaluator .CallGraph . Add (addrs.Reference {Subject : addr , SourceRange : rng }); diags .HasErrors () {
312
+ if diags := d .Evaluator .CallStack . Push (addrs.Reference {Subject : addr , SourceRange : rng }); diags .HasErrors () {
304
313
return cty .UnknownVal (cty .DynamicPseudoType ), diags
305
314
}
306
315
307
316
// Always use EvalDataForNoInstanceKey because local values cannot use expressions
308
317
// that depend on instance keys, such as `count.*` and `each.*`.
309
318
val , diags := d .Evaluator .EvaluateExpr (config .Expr , cty .DynamicPseudoType , EvalDataForNoInstanceKey )
310
319
311
- // Since we build a callgraph for each local value,
312
- // we clear the callgraph when the local value is finally resolved.
313
- if entry {
314
- d .Evaluator .CallGraph .Clear ()
315
- }
320
+ d .Evaluator .CallStack .Pop ()
316
321
return val , diags
317
322
}
318
323
0 commit comments