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 }