Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Import post-processing #420

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion imports.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ type Importer interface {
Import(importedFrom, importedPath string) (contents Contents, foundAt string, err error)
}

// ImportProcessor allows to dynamically modify the result returned by the
// Importer, for example to convert other formats to a Jsonnet snippet before
// evaluating.
type ImportProcessor interface {
Process(contents Contents, foundAt string) (Contents, error)
}

// Contents is a representation of imported data. It is a simple
// string wrapper, which makes it easier to enforce the caching policy.
type Contents struct {
Expand Down Expand Up @@ -79,12 +86,14 @@ type importCache struct {
astCache map[string]ast.Node
codeCache map[string]potentialValue
importer Importer
processor ImportProcessor
}

// makeImportCache creates an importCache using an Importer.
func makeImportCache(importer Importer) *importCache {
func makeImportCache(importer Importer, processor ImportProcessor) *importCache {
return &importCache{
importer: importer,
processor: processor,
foundAtVerification: make(map[string]Contents),
astCache: make(map[string]ast.Node),
codeCache: make(map[string]potentialValue),
Expand Down Expand Up @@ -115,9 +124,19 @@ func (cache *importCache) importAST(importedFrom, importedPath string) (ast.Node
if err != nil {
return nil, "", err
}

if cachedNode, isCached := cache.astCache[foundAt]; isCached {
return cachedNode, foundAt, nil
}

if cache.processor != nil {
c, err := cache.processor.Process(contents, foundAt)
if err != nil {
return nil, "", err
}
contents = c
}

node, err := program.SnippetToAST(foundAt, contents.String())
cache.astCache[foundAt] = node
return node, foundAt, err
Expand Down
41 changes: 25 additions & 16 deletions vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ import (
// VM is the core interpreter and is the touchpoint used to parse and execute
// Jsonnet.
type VM struct {
MaxStack int
ext vmExtMap
tla vmExtMap
nativeFuncs map[string]*NativeFunction
importer Importer
ErrorFormatter ErrorFormatter
StringOutput bool
importCache *importCache
MaxStack int
ext vmExtMap
tla vmExtMap
nativeFuncs map[string]*NativeFunction
importer Importer
importProcessor ImportProcessor
ErrorFormatter ErrorFormatter
StringOutput bool
importCache *importCache
}

// External variable or top level argument provided before execution
Expand All @@ -56,20 +57,21 @@ type vmExtMap map[string]vmExt
func MakeVM() *VM {
defaultImporter := &FileImporter{}
return &VM{
MaxStack: 500,
ext: make(vmExtMap),
tla: make(vmExtMap),
nativeFuncs: make(map[string]*NativeFunction),
ErrorFormatter: &termErrorFormatter{pretty: false, maxStackTraceSize: 20},
importer: &FileImporter{},
importCache: makeImportCache(defaultImporter),
MaxStack: 500,
ext: make(vmExtMap),
tla: make(vmExtMap),
nativeFuncs: make(map[string]*NativeFunction),
ErrorFormatter: &termErrorFormatter{pretty: false, maxStackTraceSize: 20},
importer: &FileImporter{},
importProcessor: nil,
importCache: makeImportCache(defaultImporter, nil),
}
}

// Fully flush cache. This should be executed when we are no longer sure that the source files
// didn't change, for example when the importer changed.
func (vm *VM) flushCache() {
vm.importCache = makeImportCache(vm.importer)
vm.importCache = makeImportCache(vm.importer, vm.importProcessor)
}

// Flush value cache. This should be executed when calculated values may no longer be up to date,
Expand Down Expand Up @@ -110,6 +112,13 @@ func (vm *VM) Importer(i Importer) {
vm.flushCache()
}

// ImportProcessor sets the ImportProcesor to use during evaluation
// (post-processing callback)
func (vm *VM) ImportProcessor(i ImportProcessor) {
vm.importProcessor = i
vm.flushCache()
}

// NativeFunction registers a native function.
func (vm *VM) NativeFunction(f *NativeFunction) {
vm.nativeFuncs[f.Name] = f
Expand Down