github.com/solo-io/cue@v0.4.7/internal/core/runtime/imports.go (about)

     1  // Copyright 2020 CUE Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package runtime
    16  
    17  import (
    18  	"path"
    19  	"sync"
    20  
    21  	"github.com/solo-io/cue/cue/build"
    22  	"github.com/solo-io/cue/cue/errors"
    23  	"github.com/solo-io/cue/internal/core/adt"
    24  )
    25  
    26  type PackageFunc func(ctx adt.Runtime) (*adt.Vertex, errors.Error)
    27  
    28  func RegisterBuiltin(importPath string, f PackageFunc) {
    29  	sharedIndex.RegisterBuiltin(importPath, f)
    30  }
    31  
    32  func (x *index) RegisterBuiltin(importPath string, f PackageFunc) {
    33  	if x.builtinPaths == nil {
    34  		x.builtinPaths = map[string]PackageFunc{}
    35  		x.builtinShort = map[string]string{}
    36  	}
    37  	x.builtinPaths[importPath] = f
    38  	base := path.Base(importPath)
    39  	if _, ok := x.builtinShort[base]; ok {
    40  		importPath = "" // Don't allow ambiguous base paths.
    41  	}
    42  	x.builtinShort[base] = importPath
    43  }
    44  
    45  var SharedRuntime = &Runtime{index: sharedIndex}
    46  
    47  // BuiltinPackagePath converts a short-form builtin package identifier to its
    48  // full path or "" if this doesn't exist.
    49  func (x *Runtime) BuiltinPackagePath(path string) string {
    50  	return x.index.shortBuiltinToPath(path)
    51  }
    52  
    53  // sharedIndex is used for indexing builtins and any other labels common to
    54  // all instances.
    55  var sharedIndex = newIndex()
    56  
    57  // index maps conversions from label names to internal codes.
    58  //
    59  // All instances belonging to the same package should share this index.
    60  type index struct {
    61  	// Change this to Instance at some point.
    62  	// From *structLit/*Vertex -> Instance
    63  	imports        map[*adt.Vertex]*build.Instance
    64  	importsByPath  map[string]*adt.Vertex
    65  	importsByBuild map[*build.Instance]*adt.Vertex
    66  	builtinPaths   map[string]PackageFunc // Full path
    67  	builtinShort   map[string]string      // Commandline shorthand
    68  
    69  	typeCache sync.Map // map[reflect.Type]evaluated
    70  }
    71  
    72  func newIndex() *index {
    73  	i := &index{
    74  		imports:        map[*adt.Vertex]*build.Instance{},
    75  		importsByPath:  map[string]*adt.Vertex{},
    76  		importsByBuild: map[*build.Instance]*adt.Vertex{},
    77  	}
    78  	return i
    79  }
    80  
    81  func (x *index) shortBuiltinToPath(id string) string {
    82  	if x == nil || x.builtinPaths == nil {
    83  		return ""
    84  	}
    85  	return x.builtinShort[id]
    86  }
    87  
    88  func (r *Runtime) AddInst(path string, key *adt.Vertex, p *build.Instance) {
    89  	x := r.index
    90  	if key == nil {
    91  		panic("key must not be nil")
    92  	}
    93  	x.imports[key] = p
    94  	x.importsByBuild[p] = key
    95  	if path != "" {
    96  		x.importsByPath[path] = key
    97  	}
    98  }
    99  
   100  func (r *Runtime) GetInstanceFromNode(key *adt.Vertex) *build.Instance {
   101  	return r.index.imports[key]
   102  }
   103  
   104  func (r *Runtime) getNodeFromInstance(key *build.Instance) *adt.Vertex {
   105  	return r.index.importsByBuild[key]
   106  }
   107  
   108  func (r *Runtime) LoadImport(importPath string) (*adt.Vertex, errors.Error) {
   109  	x := r.index
   110  
   111  	key := x.importsByPath[importPath]
   112  	if key != nil {
   113  		return key, nil
   114  	}
   115  
   116  	if x.builtinPaths != nil {
   117  		if f := x.builtinPaths[importPath]; f != nil {
   118  			p, err := f(r)
   119  			if err != nil {
   120  				return adt.ToVertex(&adt.Bottom{Err: err}), nil
   121  			}
   122  			inst := &build.Instance{
   123  				ImportPath: importPath,
   124  				PkgName:    path.Base(importPath),
   125  			}
   126  			x.imports[p] = inst
   127  			x.importsByPath[importPath] = p
   128  			x.importsByBuild[inst] = p
   129  			return p, nil
   130  		}
   131  	}
   132  
   133  	return key, nil
   134  }