From 1ff2c9bbd94c9fe0e4c0fd68d51bb0d84c4e414b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20G=C3=A9lineau?= Date: Fri, 1 Dec 2023 23:39:43 -0500 Subject: [PATCH] lang: ast: Clear env in ExprVar.Graph() Fix the bug in ExprVar.Graph() described in the previous commit. --- lang/ast/structs.go | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/lang/ast/structs.go b/lang/ast/structs.go index 76827541..e014fbeb 100644 --- a/lang/ast/structs.go +++ b/lang/ast/structs.go @@ -8460,9 +8460,29 @@ func (obj *ExprVar) Unify() ([]interfaces.Invariant, error) { // to avoid duplicating production of the incoming input value from the bound // expression. func (obj *ExprVar) Graph(env map[string]interfaces.Func) (*pgraph.Graph, interfaces.Func, error) { - // Delegate to the target. - target := obj.scope.Variables[obj.Name] - graph, varFunc, err := target.Graph(env) + // Delegate to the targetExpr. + targetExpr := obj.scope.Variables[obj.Name] + if _, isParam := targetExpr.(*ExprParam); isParam { + // The variable points to a function parameter. We should be able to find + // this parameter in the environment. + targetFunc, exists := env[obj.Name] + if !exists { + return nil, nil, fmt.Errorf("param `%s` is not in the environment", obj.Name) + } + + graph, err := pgraph.NewGraph("ExprParam") + if err != nil { + return nil, nil, err + } + graph.AddVertex(targetFunc) + return graph, targetFunc, nil + } + + // The variable points to a top-level expression. The parameters which are + // visible at this use site must not be visible at the definition site, so + // we pass an empty environment. + emptyEnv := map[string]interfaces.Func{} + graph, varFunc, err := targetExpr.Graph(emptyEnv) return graph, varFunc, err } @@ -8620,21 +8640,7 @@ func (obj *ExprParam) Unify() ([]interfaces.Invariant, error) { // that fulfill the Stmt interface do not produces vertices, where as their // children might. func (obj *ExprParam) Graph(env map[string]interfaces.Func) (*pgraph.Graph, interfaces.Func, error) { - // Since ExprParam represents a function parameter, we want to receive values - // from the arguments passed to the function. The caller of ExprParam.Graph() - // should already know what those arguments are, so we can simply look up the - // argument by name in the environment. - paramFunc, exists := env[obj.Name] - if !exists { - return nil, nil, fmt.Errorf("param `%s` is not in the environment", obj.Name) - } - - graph, err := pgraph.NewGraph("ExprParam") - if err != nil { - return nil, nil, err - } - graph.AddVertex(paramFunc) - return graph, paramFunc, nil + panic("ExprParam.Graph(): should not happen, ExprVar.Graph() should handle the case where the ExprVar points to an ExprParam") } // SetValue here is a no-op, because algorithmically when this is called from