...

Source file src/cuelang.org/go/internal/core/runtime/imports.go

Documentation: cuelang.org/go/internal/core/runtime

     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  	"cuelang.org/go/cue/build"
    22  	"cuelang.org/go/cue/errors"
    23  	"cuelang.org/go/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  	// lock is used to guard imports-related maps.
    62  	// TODO: makes these per cuecontext.
    63  	lock           sync.RWMutex
    64  	imports        map[*adt.Vertex]*build.Instance
    65  	importsByPath  map[string]*adt.Vertex
    66  	importsByBuild map[*build.Instance]*adt.Vertex
    67  
    68  	nextUniqueID uint64
    69  
    70  	// These are initialized during Go package initialization time and do not
    71  	// need to be guarded.
    72  	builtinPaths map[string]PackageFunc // Full path
    73  	builtinShort map[string]string      // Commandline shorthand
    74  
    75  	typeCache sync.Map // map[reflect.Type]evaluated
    76  }
    77  
    78  func (i *index) getNextUniqueID() uint64 {
    79  	// TODO: use atomic increment instead.
    80  	i.lock.Lock()
    81  	i.nextUniqueID++
    82  	x := i.nextUniqueID
    83  	i.lock.Unlock()
    84  	return x
    85  }
    86  
    87  func newIndex() *index {
    88  	i := &index{
    89  		imports:        map[*adt.Vertex]*build.Instance{},
    90  		importsByPath:  map[string]*adt.Vertex{},
    91  		importsByBuild: map[*build.Instance]*adt.Vertex{},
    92  	}
    93  	return i
    94  }
    95  
    96  func (x *index) shortBuiltinToPath(id string) string {
    97  	if x == nil || x.builtinPaths == nil {
    98  		return ""
    99  	}
   100  	return x.builtinShort[id]
   101  }
   102  
   103  func (r *Runtime) AddInst(path string, key *adt.Vertex, p *build.Instance) {
   104  	r.index.lock.Lock()
   105  	defer r.index.lock.Unlock()
   106  
   107  	x := r.index
   108  	if key == nil {
   109  		panic("key must not be nil")
   110  	}
   111  	x.imports[key] = p
   112  	x.importsByBuild[p] = key
   113  	if path != "" {
   114  		x.importsByPath[path] = key
   115  	}
   116  }
   117  
   118  func (r *Runtime) GetInstanceFromNode(key *adt.Vertex) *build.Instance {
   119  	r.index.lock.RLock()
   120  	defer r.index.lock.RUnlock()
   121  
   122  	return r.index.imports[key]
   123  }
   124  
   125  func (r *Runtime) getNodeFromInstance(key *build.Instance) *adt.Vertex {
   126  	r.index.lock.RLock()
   127  	defer r.index.lock.RUnlock()
   128  
   129  	return r.index.importsByBuild[key]
   130  }
   131  
   132  func (r *Runtime) LoadImport(importPath string) *adt.Vertex {
   133  	r.index.lock.Lock()
   134  	defer r.index.lock.Unlock()
   135  
   136  	x := r.index
   137  
   138  	key := x.importsByPath[importPath]
   139  	if key != nil {
   140  		return key
   141  	}
   142  
   143  	if x.builtinPaths != nil {
   144  		if f := x.builtinPaths[importPath]; f != nil {
   145  			p, err := f(r)
   146  			if err != nil {
   147  				return adt.ToVertex(&adt.Bottom{Err: err})
   148  			}
   149  			inst := &build.Instance{
   150  				ImportPath: importPath,
   151  				PkgName:    path.Base(importPath),
   152  			}
   153  			x.imports[p] = inst
   154  			x.importsByPath[importPath] = p
   155  			x.importsByBuild[inst] = p
   156  			return p
   157  		}
   158  	}
   159  
   160  	return key
   161  }
   162  

View as plain text