github.com/google/skylark@v0.0.0-20181101142754-a5f7082aabed/skylarkstruct/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 skylarkstruct_test 6 7 import ( 8 "fmt" 9 "path/filepath" 10 "testing" 11 12 "github.com/google/skylark" 13 "github.com/google/skylark/resolve" 14 "github.com/google/skylark/skylarkstruct" 15 "github.com/google/skylark/skylarktest" 16 ) 17 18 func init() { 19 // The tests make extensive use of these not-yet-standard features. 20 resolve.AllowLambda = true 21 resolve.AllowNestedDef = true 22 resolve.AllowFloat = true 23 resolve.AllowSet = true 24 } 25 26 func Test(t *testing.T) { 27 testdata := skylarktest.DataFile("skylark/skylarkstruct", ".") 28 thread := &skylark.Thread{Load: load} 29 skylarktest.SetReporter(thread, t) 30 filename := filepath.Join(testdata, "testdata/struct.sky") 31 predeclared := skylark.StringDict{ 32 "struct": skylark.NewBuiltin("struct", skylarkstruct.Make), 33 "gensym": skylark.NewBuiltin("gensym", gensym), 34 } 35 if _, err := skylark.ExecFile(thread, filename, nil, predeclared); err != nil { 36 if err, ok := err.(*skylark.EvalError); ok { 37 t.Fatal(err.Backtrace()) 38 } 39 t.Fatal(err) 40 } 41 } 42 43 // load implements the 'load' operation as used in the evaluator tests. 44 func load(thread *skylark.Thread, module string) (skylark.StringDict, error) { 45 if module == "assert.sky" { 46 return skylarktest.LoadAssertModule() 47 } 48 return nil, fmt.Errorf("load not implemented") 49 } 50 51 // gensym is a built-in function that generates a unique symbol. 52 func gensym(thread *skylark.Thread, _ *skylark.Builtin, args skylark.Tuple, kwargs []skylark.Tuple) (skylark.Value, error) { 53 var name string 54 if err := skylark.UnpackArgs("gensym", args, kwargs, "name", &name); err != nil { 55 return nil, err 56 } 57 return &symbol{name: name}, nil 58 } 59 60 // A symbol is a distinct value that acts as a constructor of "branded" 61 // struct instances, like a class symbol in Python or a "provider" in Bazel. 62 type symbol struct{ name string } 63 64 var _ skylark.Callable = (*symbol)(nil) 65 66 func (sym *symbol) Name() string { return sym.name } 67 func (sym *symbol) String() string { return sym.name } 68 func (sym *symbol) Type() string { return "symbol" } 69 func (sym *symbol) Freeze() {} // immutable 70 func (sym *symbol) Truth() skylark.Bool { return skylark.True } 71 func (sym *symbol) Hash() (uint32, error) { return 0, fmt.Errorf("unhashable: %s", sym.Type()) } 72 73 func (sym *symbol) CallInternal(thread *skylark.Thread, args skylark.Tuple, kwargs []skylark.Tuple) (skylark.Value, error) { 74 if len(args) > 0 { 75 return nil, fmt.Errorf("%s: unexpected positional arguments", sym) 76 } 77 return skylarkstruct.FromKeywords(sym, kwargs), nil 78 }