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