diff --git a/imports.go b/imports.go index 3cff572..a2c7151 100644 --- a/imports.go +++ b/imports.go @@ -86,7 +86,7 @@ func codeToPV(e *evaluator, filename string, code string) potentialValue { // The same thinking applies to external variables. return makeErrorThunk(err) } - return makeThunk(e.i.initialEnv, node) + return makeThunk(makeInitialEnv(filename, e.i.baseStd), node) } func (cache *ImportCache) ImportCode(codeDir, importedPath string, e *evaluator) (value, error) { diff --git a/interpreter.go b/interpreter.go index fa24ea0..b928e48 100644 --- a/interpreter.go +++ b/interpreter.go @@ -203,7 +203,9 @@ type interpreter struct { // The clean environment in which we execute imports, extVars as well // as the main program. It contains std. - initialEnv environment + //initialEnv environment + + baseStd valueObject // Keeps imports importCache *ImportCache @@ -709,7 +711,7 @@ func (i *interpreter) EvalInCleanEnv(fromWhere *TraceElement, env *environment, return val, err } -func buildStdObject(i *interpreter) (value, error) { +func buildStdObject(i *interpreter) (valueObject, error) { objVal, err := evaluateStd(i) if err != nil { return nil, err @@ -761,6 +763,14 @@ func prepareExtVars(i *interpreter, ext vmExtMap) map[ast.Identifier]potentialVa return result } +func buildObject(hide ast.ObjectFieldHide, fields map[string]value) valueObject { + fieldMap := valueSimpleObjectFieldMap{} + for name, v := range fields { + fieldMap[name] = valueSimpleObjectField{hide, &readyValue{v}} + } + return makeValueSimpleObject(bindingFrame{}, fieldMap, nil) +} + func buildInterpreter(ext vmExtMap, maxStack int, importer Importer) (*interpreter, error) { i := interpreter{ stack: makeCallStack(maxStack), @@ -772,18 +782,25 @@ func buildInterpreter(ext vmExtMap, maxStack int, importer Importer) (*interpret return nil, err } - i.initialEnv = makeEnvironment( - bindingFrame{ - "std": &readyValue{stdObj}, - }, - makeUnboundSelfBinding(), - ) + i.baseStd = stdObj i.extVars = prepareExtVars(&i, ext) return &i, nil } +func makeInitialEnv(filename string, baseStd valueObject) environment { + fileSpecific := buildObject(ast.ObjectFieldHidden, map[string]value{ + "thisFile": makeValueString(filename), + }) + return makeEnvironment( + bindingFrame{ + "std": &readyValue{makeValueExtendedObject(baseStd, fileSpecific)}, + }, + makeUnboundSelfBinding(), + ) +} + func evaluate(node ast.Node, ext vmExtMap, maxStack int, importer Importer) (string, error) { i, err := buildInterpreter(ext, maxStack, importer) if err != nil { @@ -793,7 +810,8 @@ func evaluate(node ast.Node, ext vmExtMap, maxStack int, importer Importer) (str evalTrace := &TraceElement{ loc: &evalLoc, } - result, err := i.EvalInCleanEnv(evalTrace, &i.initialEnv, node) + env := makeInitialEnv(node.Loc().FileName, i.baseStd) + result, err := i.EvalInCleanEnv(evalTrace, &env, node) if err != nil { return "", err } diff --git a/testdata/std.thisFile.golden b/testdata/std.thisFile.golden new file mode 100644 index 0000000..4338876 --- /dev/null +++ b/testdata/std.thisFile.golden @@ -0,0 +1 @@ +"testdata/std.thisFile" diff --git a/testdata/std.thisFile.jsonnet b/testdata/std.thisFile.jsonnet new file mode 100644 index 0000000..f413f6e --- /dev/null +++ b/testdata/std.thisFile.jsonnet @@ -0,0 +1 @@ +std.thisFile diff --git a/testdata/std.thisFile2.golden b/testdata/std.thisFile2.golden new file mode 100644 index 0000000..b4f15bc --- /dev/null +++ b/testdata/std.thisFile2.golden @@ -0,0 +1 @@ +"testdata/std.thisFile.jsonnet" diff --git a/testdata/std.thisFile2.jsonnet b/testdata/std.thisFile2.jsonnet new file mode 100644 index 0000000..da705e0 --- /dev/null +++ b/testdata/std.thisFile2.jsonnet @@ -0,0 +1 @@ +import "std.thisFile.jsonnet"