...

Source file src/cuelang.org/go/cue/interpreter/wasm/extern.go

Documentation: cuelang.org/go/cue/interpreter/wasm

     1  // Copyright 2023 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 wasm
    16  
    17  import (
    18  	"fmt"
    19  
    20  	"cuelang.org/go/cue"
    21  	"cuelang.org/go/cue/ast"
    22  	"cuelang.org/go/cue/errors"
    23  	"cuelang.org/go/cue/format"
    24  	"cuelang.org/go/cue/parser"
    25  	"cuelang.org/go/cue/token"
    26  	"cuelang.org/go/internal"
    27  )
    28  
    29  // argList returns the types of a function's arguments and result
    30  // (specified as an external attribute) as a list of strings.
    31  func argList(a *internal.Attr) ([]string, error) {
    32  	sig, err := sig(a)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	f, err := parseFunc(sig)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  	return args(f), nil
    41  }
    42  
    43  // sig returns the function signature specified in an external attribute.
    44  func sig(a *internal.Attr) (string, error) {
    45  	sig, ok, err := a.Lookup(1, "sig")
    46  	if err != nil {
    47  		return "", err
    48  	}
    49  	if !ok {
    50  		return "", errors.New(`missing "sig" key`)
    51  	}
    52  	return sig, nil
    53  }
    54  
    55  func parseFunc(sig string) (*ast.Func, error) {
    56  	expr, err := parser.ParseExpr("", sig, parser.ParseFuncs)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  	f, ok := expr.(*ast.Func)
    61  	if !ok {
    62  		// TODO: once we have position information, make this
    63  		// error more user-friendly by returning the position.
    64  		return nil, errors.New("not a function")
    65  	}
    66  	for _, arg := range append(f.Args, f.Ret) {
    67  		switch arg.(type) {
    68  		case *ast.Ident, *ast.SelectorExpr:
    69  			continue
    70  		default:
    71  			// TODO: once we have position information, make this
    72  			// error more user-friendly by returning the position.
    73  			return nil, errors.Newf(token.NoPos, "expected identifier, found %T", arg)
    74  		}
    75  	}
    76  	return f, nil
    77  }
    78  
    79  func args(f *ast.Func) []string {
    80  	var args []string
    81  	for _, arg := range append(f.Args, f.Ret) {
    82  		switch v := arg.(type) {
    83  		case *ast.Ident:
    84  			args = append(args, v.Name)
    85  		case *ast.SelectorExpr:
    86  			b, _ := format.Node(v)
    87  			args = append(args, string(b))
    88  		default:
    89  			panic(fmt.Sprintf("unexpected type: %T", v))
    90  		}
    91  	}
    92  	return args
    93  }
    94  
    95  // compileStringsInScope takes a list of strings, compiles them using
    96  // the provided scope, and returns the compiled values.
    97  func compileStringsInScope(strs []string, scope cue.Value) []cue.Value {
    98  	var vals []cue.Value
    99  	for _, typ := range strs {
   100  		val := scope.Context().CompileString(typ, cue.Scope(scope))
   101  		vals = append(vals, val)
   102  	}
   103  	return vals
   104  }
   105  
   106  func splitLast[T any](x []T) ([]T, T) {
   107  	return x[:len(x)-1], x[len(x)-1]
   108  }
   109  

View as plain text