Avoid depending on stdlib variable for desugaring.

The fix is easy – we just use "$std" which the user cannot access,
because it's not a valid identifier.
This commit is contained in:
Stanisław Barzowski 2021-08-08 15:48:47 +01:00
parent 51daeb3229
commit b00b56c335
8 changed files with 10818 additions and 10472 deletions

File diff suppressed because it is too large Load Diff

View File

@ -251,7 +251,7 @@ func buildSimpleIndex(obj ast.Node, member ast.Identifier) ast.Node {
}
func buildStdCall(builtinName ast.Identifier, loc ast.LocationRange, args ...ast.Node) ast.Node {
std := &ast.Var{Id: "std"}
std := &ast.Var{Id: "$std"}
builtin := buildSimpleIndex(std, builtinName)
positional := make([]ast.CommaSeparatedExpr, len(args))
for i := range args {

View File

@ -164,5 +164,5 @@ func analyzeVisit(a ast.Node, inObject bool, vars ast.IdentifierSet) error {
// It enriches the AST with additional information about free variables in every node,
// so it is necessary to always run it before executing the AST.
func analyze(node ast.Node) error {
return analyzeVisit(node, false, ast.NewIdentifierSet("std"))
return analyzeVisit(node, false, ast.NewIdentifierSet("std", "$std"))
}

View File

@ -1183,8 +1183,16 @@ func buildStdObject(i *interpreter) (*valueObject, error) {
}
func evaluateStd(i *interpreter) (value, error) {
// We are bootstrapping std before it is properly available.
// We need "$std" for desugaring.
// So, we're creating an empty thunk (evaluating will panic).
// We will fill it manually before it's evaluated, though.
// This "std" does not have std.thisFile.
stdThunk := &cachedThunk{}
beforeStdEnv := makeEnvironment(
bindingFrame{},
bindingFrame{
"$std": stdThunk,
},
makeUnboundSelfBinding(),
)
evalLoc := ast.MakeLocationRangeMessage("During evaluation of std")
@ -1192,7 +1200,12 @@ func evaluateStd(i *interpreter) (value, error) {
node := astgen.StdAst
i.stack.setCurrentTrace(evalTrace)
defer i.stack.clearCurrentTrace()
return i.EvalInCleanEnv(&beforeStdEnv, node, false)
content, err := i.EvalInCleanEnv(&beforeStdEnv, node, false)
if err != nil {
return nil, err
}
stdThunk.content = content
return content, nil
}
func prepareExtVars(i *interpreter, ext vmExtMap, kind string) map[string]*cachedThunk {
@ -1243,9 +1256,13 @@ func makeInitialEnv(filename string, baseStd *valueObject) environment {
fileSpecific := buildObject(ast.ObjectFieldHidden, map[string]value{
"thisFile": makeValueString(filename),
})
stdThunk := readyThunk(makeValueExtendedObject(baseStd, fileSpecific))
return makeEnvironment(
bindingFrame{
"std": readyThunk(makeValueExtendedObject(baseStd, fileSpecific)),
"std": stdThunk,
"$std": stdThunk, // Unavailable to the user. To be used with desugaring.
},
makeUnboundSelfBinding(),
)

View File

@ -62,7 +62,7 @@ func lint(vm *jsonnet.VM, nodes []nodeWithLocation, errWriter *ErrorWriter) {
}
findVariables := func(node nodeWithLocation) *common.VariableInfo {
return variables.FindVariables(node.node, variables.Environment{"std": &std})
return variables.FindVariables(node.node, variables.Environment{"std": &std, "$std": &std})
}
for importedPath, rootNode := range roots {

View File

@ -0,0 +1,6 @@
[
{ },
[ ],
42,
false
]

View File

@ -0,0 +1,8 @@
// Make sure shadowing std does not cause problems for desugaring.
local std = {};
[
{ [x]: 17 for x in [] },
[ x for x in [] ],
42 % 2137,
"foo" in {},
]

View File

@ -0,0 +1,5 @@
../testdata/overriding_stdlib_desugared:2:7-15 Unused variable: std
local std = {};