go.starlark.net@v0.0.0-20231101134539-556fd59b42f6/starlarkstruct/struct_test.go (about)

     1  // Copyright 2018 The Bazel Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package starlarkstruct_test
     6  
     7  import (
     8  	"fmt"
     9  	"path/filepath"
    10  	"testing"
    11  
    12  	"go.starlark.net/starlark"
    13  	"go.starlark.net/starlarkstruct"
    14  	"go.starlark.net/starlarktest"
    15  )
    16  
    17  func Test(t *testing.T) {
    18  	testdata := starlarktest.DataFile("starlarkstruct", ".")
    19  	thread := &starlark.Thread{Load: load}
    20  	starlarktest.SetReporter(thread, t)
    21  	filename := filepath.Join(testdata, "testdata/struct.star")
    22  	predeclared := starlark.StringDict{
    23  		"struct": starlark.NewBuiltin("struct", starlarkstruct.Make),
    24  		"gensym": starlark.NewBuiltin("gensym", gensym),
    25  	}
    26  	if _, err := starlark.ExecFile(thread, filename, nil, predeclared); err != nil {
    27  		if err, ok := err.(*starlark.EvalError); ok {
    28  			t.Fatal(err.Backtrace())
    29  		}
    30  		t.Fatal(err)
    31  	}
    32  }
    33  
    34  // load implements the 'load' operation as used in the evaluator tests.
    35  func load(thread *starlark.Thread, module string) (starlark.StringDict, error) {
    36  	if module == "assert.star" {
    37  		return starlarktest.LoadAssertModule()
    38  	}
    39  	return nil, fmt.Errorf("load not implemented")
    40  }
    41  
    42  // gensym is a built-in function that generates a unique symbol.
    43  func gensym(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
    44  	var name string
    45  	if err := starlark.UnpackArgs("gensym", args, kwargs, "name", &name); err != nil {
    46  		return nil, err
    47  	}
    48  	return &symbol{name: name}, nil
    49  }
    50  
    51  // A symbol is a distinct value that acts as a constructor of "branded"
    52  // struct instances, like a class symbol in Python or a "provider" in Bazel.
    53  type symbol struct{ name string }
    54  
    55  var _ starlark.Callable = (*symbol)(nil)
    56  
    57  func (sym *symbol) Name() string          { return sym.name }
    58  func (sym *symbol) String() string        { return sym.name }
    59  func (sym *symbol) Type() string          { return "symbol" }
    60  func (sym *symbol) Freeze()               {} // immutable
    61  func (sym *symbol) Truth() starlark.Bool  { return starlark.True }
    62  func (sym *symbol) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: %s", sym.Type()) }
    63  
    64  func (sym *symbol) CallInternal(thread *starlark.Thread, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
    65  	if len(args) > 0 {
    66  		return nil, fmt.Errorf("%s: unexpected positional arguments", sym)
    67  	}
    68  	return starlarkstruct.FromKeywords(sym, kwargs), nil
    69  }