github.com/emcfarlane/larking@v0.0.0-20220605172417-1704b45ee6c3/starlib/starlarkrule/attrs.go (about) 1 // Copyright 2022 Edward McFarlane. 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 starlarkrule 6 7 import ( 8 _ "embed" 9 "fmt" 10 "strings" 11 12 "github.com/emcfarlane/larking/starlib/starext" 13 "github.com/emcfarlane/larking/starlib/starlarkstruct" 14 "go.starlark.net/starlark" 15 "go.starlark.net/syntax" 16 ) 17 18 func NewAttrModule() *starlarkstruct.Module { 19 return &starlarkstruct.Module{ 20 Name: "attr", 21 Members: starlark.StringDict{ 22 "bool": starext.MakeBuiltin("attr.bool", attrBool), 23 "int": starext.MakeBuiltin("attr.int", attrInt), 24 "int_list": starext.MakeBuiltin("attr.int_list", attrIntList), 25 "label": starext.MakeBuiltin("attr.label", attrLabel), 26 //TODO:"label_keyed_string_dict": starext.MakeBuiltin("attr.label_keyed_string_dict", attrLabelKeyedStringDict), 27 "label_list": starext.MakeBuiltin("attr.label_list", attrLabelList), 28 "string": starext.MakeBuiltin("attr.string", attrString), 29 //TODO:"string_dict": starext.MakeBuiltin("attr.string_dict", attrStringDict), 30 "string_list": starext.MakeBuiltin("attr.string_list", attrStringList), 31 //TODO:"string_list_dict": starext.MakeBuiltin("attr.string_list_dict", attrStringListDict), 32 }, 33 } 34 } 35 36 type AttrType string 37 38 const ( 39 AttrTypeBool AttrType = "attr.bool" 40 AttrTypeInt AttrType = "attr.int" 41 AttrTypeIntList AttrType = "attr.int_list" 42 AttrTypeLabel AttrType = "attr.label" 43 AttrTypeLabelKeyedStringDict AttrType = "attr.label_keyed_string_dict" 44 AttrTypeLabelList AttrType = "attr.label_list" 45 AttrTypeOutput AttrType = "attr.output" 46 AttrTypeOutputList AttrType = "attr.output_list" 47 AttrTypeString AttrType = "attr.string" 48 AttrTypeStringDict AttrType = "attr.string_dict" 49 AttrTypeStringList AttrType = "attr.string_list" 50 AttrTypeStringListDict AttrType = "attr.string_list_dict" 51 AttrTypeResolver AttrType = "attr.resolver" 52 53 AttrArgsConstructor starlark.String = "attr.args" // starlarkstruct constructor 54 ) 55 56 // Attr defines attributes to a rules attributes. 57 type Attr struct { 58 Typ AttrType 59 Def starlark.Value // default 60 Doc string 61 Executable bool 62 Mandatory bool 63 AllowEmpty bool 64 AllowFiles allowedFiles // nil, bool, globlist([]string) 65 Values interface{} // []typ 66 67 // TODO: resolver 68 //Resolver starlark.Callable 69 //Ins Outs Attr 70 71 //Output bool // declare as output value 72 } 73 74 func (a *Attr) String() string { 75 var b strings.Builder 76 b.WriteString(string(a.Typ)) 77 b.WriteString("(") 78 b.WriteString("default = ") 79 b.WriteString(a.Def.String()) 80 b.WriteString(", doc = " + a.Doc) 81 b.WriteString(", executable = ") 82 b.WriteString(starlark.Bool(a.Executable).String()) 83 b.WriteString(", mandatory = ") 84 b.WriteString(starlark.Bool(a.Mandatory).String()) 85 b.WriteString(", allow_empty = ") 86 b.WriteString(starlark.Bool(a.AllowEmpty).String()) 87 b.WriteString(", allow_files = ") 88 b.WriteString(starlark.Bool(a.AllowFiles.allow).String()) 89 90 b.WriteString(", values = ") 91 switch v := a.Values.(type) { 92 case []string, []int: 93 b.WriteString(fmt.Sprintf("%v", v)) 94 case nil: 95 b.WriteString(starlark.None.String()) 96 default: 97 panic(fmt.Sprintf("unhandled values type: %T", a.Values)) 98 } 99 b.WriteString(")") 100 return b.String() 101 } 102 func (a *Attr) Type() string { return string(a.Typ) } 103 func (a *Attr) AttrType() AttrType { return a.Typ } 104 func (a *Attr) Freeze() {} // immutable 105 func (a *Attr) Truth() starlark.Bool { return true } 106 func (a *Attr) Hash() (uint32, error) { 107 var x, mult uint32 = 0x345678, 1000003 108 for _, elem := range []starlark.Value{ 109 starlark.String(a.Typ), 110 starlark.String(a.Def.String()), // TODO 111 starlark.String(a.Doc), 112 starlark.Bool(a.Executable), 113 starlark.Bool(a.Mandatory), 114 starlark.Bool(a.AllowEmpty), 115 starlark.String(fmt.Sprintf("%v", a.AllowFiles)), 116 starlark.String(fmt.Sprintf("%v", a.Values)), 117 } { 118 y, err := elem.Hash() 119 if err != nil { 120 return 0, err 121 } 122 x = x ^ y*mult 123 mult += 82520 124 } 125 return x, nil 126 } 127 128 func (a *Attr) IsValidType(value starlark.Value) bool { 129 var ok bool 130 switch a.Typ { 131 case AttrTypeBool: 132 _, ok = (value).(starlark.Bool) 133 case AttrTypeInt: 134 _, ok = (value).(starlark.Int) 135 case AttrTypeIntList: 136 _, ok = (value).(*starlark.List) 137 case AttrTypeLabel: 138 _, ok = (value).(*Label) 139 fmt.Printf("label: %T\n", value) 140 //case attrTypeLabelKeyedStringDict: 141 case AttrTypeLabelList: 142 list, lok := (value).(*starlark.List) 143 if !lok { 144 return false 145 } 146 for i, n := 0, list.Len(); i < n; i++ { 147 _, ok = (value).(*Label) 148 if !ok { 149 break 150 } 151 } 152 case AttrTypeOutput: 153 _, ok = (value).(starlark.String) 154 case AttrTypeOutputList: 155 _, ok = (value).(*starlark.List) 156 case AttrTypeString: 157 _, ok = (value).(starlark.String) 158 //case attrTypeStringDict: 159 case AttrTypeStringList: 160 _, ok = (value).(*starlark.List) 161 //case attrTypeStringListDict: 162 default: 163 panic(fmt.Sprintf("unhandled type: %s", a.Typ)) 164 } 165 return ok 166 } 167 168 func attrEqual(x, y *Attr, depth int) (bool, error) { 169 if ok := (x.Typ == y.Typ && 170 x.Def == y.Def && 171 x.Executable == y.Executable && 172 x.Mandatory == y.Mandatory && 173 x.AllowEmpty == y.AllowEmpty); !ok { 174 return ok, nil 175 } 176 177 if ok, err := starlark.EqualDepth(x.Def, y.Def, depth-1); !ok || err != nil { 178 return ok, err 179 } 180 181 switch x := x.Values.(type) { 182 case []string: 183 y, ok := y.Values.([]string) 184 if !ok { 185 return false, nil 186 } 187 if len(x) != len(y) { 188 return false, nil 189 } 190 for i, n := 0, len(x); i < n; i++ { 191 if x[i] != y[i] { 192 return false, nil 193 } 194 } 195 196 case []int: 197 y, ok := y.Values.([]int) 198 if !ok { 199 return false, nil 200 } 201 if len(x) != len(y) { 202 return false, nil 203 } 204 for i, n := 0, len(x); i < n; i++ { 205 if x[i] != y[i] { 206 return false, nil 207 } 208 } 209 case nil: 210 if ok := x == y.Values; !ok { 211 return ok, nil 212 } 213 default: 214 return false, nil 215 } 216 return true, nil 217 } 218 219 func (x *Attr) CompareSameType(op syntax.Token, y_ starlark.Value, depth int) (bool, error) { 220 y := y_.(*Attr) 221 switch op { 222 case syntax.EQL: 223 return attrEqual(x, y, depth) 224 case syntax.NEQ: 225 eq, err := attrEqual(x, y, depth) 226 return !eq, err 227 default: 228 return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type()) 229 } 230 } 231 232 // Attribute attr.bool(default=False, doc='', mandatory=False) 233 func attrBool(thread *starlark.Thread, fnname string, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 234 var ( 235 def bool 236 doc string 237 mandatory bool 238 ) 239 240 if err := starlark.UnpackArgs( 241 fnname, args, kwargs, 242 "default?", &def, "doc?", &doc, "mandatory?", &mandatory, 243 ); err != nil { 244 return nil, err 245 } 246 247 return &Attr{ 248 Typ: AttrTypeBool, 249 Def: starlark.Bool(def), 250 Doc: doc, 251 Mandatory: mandatory, 252 }, nil 253 } 254 255 // Attribute attr.int(default=0, doc='', mandatory=False, values=[]) 256 func attrInt(thread *starlark.Thread, fnname string, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 257 var ( 258 def = starlark.MakeInt(0) 259 doc string 260 mandatory bool 261 values *starlark.List 262 ) 263 264 if err := starlark.UnpackArgs( 265 fnname, args, kwargs, 266 "default?", &def, "doc?", &doc, "mandatory?", &mandatory, "values?", &values, 267 ); err != nil { 268 return nil, err 269 } 270 271 var ints []int 272 if values != nil { 273 iter := values.Iterate() 274 var x starlark.Value 275 for iter.Next(&x) { 276 i, err := starlark.AsInt32(x) 277 if err != nil { 278 return nil, err 279 } 280 ints = append(ints, i) 281 } 282 iter.Done() 283 } 284 285 return &Attr{ 286 Typ: AttrTypeInt, 287 Def: def, 288 Doc: doc, 289 Mandatory: mandatory, 290 Values: ints, 291 }, nil 292 } 293 294 // Attribute attr.int_list(mandatory=False, allow_empty=True, *, default=[], doc='') 295 func attrIntList(thread *starlark.Thread, fnname string, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 296 var ( 297 def *starlark.List 298 doc string 299 mandatory bool 300 allowEmpty bool 301 ) 302 if err := starlark.UnpackArgs( 303 fnname, args, kwargs, 304 "default?", &def, "doc?", &doc, "mandatory?", &mandatory, "allowEmpty?", &allowEmpty, 305 ); err != nil { 306 return nil, err 307 } 308 309 iter := def.Iterate() 310 var x starlark.Value 311 for iter.Next(&x) { 312 if _, err := starlark.AsInt32(x); err != nil { 313 return nil, err 314 } 315 } 316 iter.Done() 317 318 return &Attr{ 319 Typ: AttrTypeIntList, 320 Def: def, 321 Doc: doc, 322 Mandatory: mandatory, 323 AllowEmpty: allowEmpty, 324 }, nil 325 } 326 327 type allowedFiles struct { 328 allow bool 329 types []string // path.Match syntax? 330 } 331 332 func parseAllowFiles(allowFiles starlark.Value) (allowedFiles, error) { 333 switch v := allowFiles.(type) { 334 case nil: 335 return allowedFiles{allow: false}, nil 336 case starlark.Bool: 337 return allowedFiles{allow: bool(v)}, nil 338 case *starlark.List: 339 types := make([]string, v.Len()) 340 for i, n := 0, v.Len(); i < n; i++ { 341 x := v.Index(i) 342 v, ok := starlark.AsString(x) 343 if !ok { 344 return allowedFiles{}, fmt.Errorf("unexpected type: %v", x.Type()) 345 } 346 types[i] = string(v) 347 } 348 return allowedFiles{allow: true, types: types}, nil 349 default: 350 panic(fmt.Sprintf("TODO: handle allow_files type: %T", allowFiles)) 351 } 352 } 353 354 // Attribute attr.label(default=None, doc='', executable=False, allow_files=None, allow_single_file=None, mandatory=False, providers=[], allow_rules=None, cfg=None, aspects=[]) 355 func attrLabel(thread *starlark.Thread, fnname string, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 356 var ( 357 def starlark.String 358 doc string 359 executable = false 360 mandatory bool 361 values *starlark.List 362 allowFiles starlark.Value 363 364 // TODO: more types! 365 //providers 366 ) 367 368 if err := starlark.UnpackArgs( 369 fnname, args, kwargs, 370 "default?", &def, "doc?", &doc, "executable", &executable, "mandatory?", &mandatory, "values?", &values, "allow_files?", &allowFiles, 371 ); err != nil { 372 return nil, err 373 } 374 375 var vals []string 376 if values != nil { 377 iter := values.Iterate() 378 var x starlark.Value 379 for iter.Next(&x) { 380 s, ok := starlark.AsString(x) 381 if !ok { 382 return nil, fmt.Errorf("got %s, want string", x.Type()) 383 } 384 vals = append(vals, s) 385 } 386 iter.Done() 387 } 388 389 af, err := parseAllowFiles(allowFiles) 390 if err != nil { 391 return nil, err 392 } 393 394 var defValue starlark.Value = starlark.None 395 if len(def) > 0 { 396 defValue = def 397 } 398 399 return &Attr{ 400 Typ: AttrTypeLabel, 401 Def: defValue, 402 Doc: doc, 403 Mandatory: mandatory, 404 Values: vals, 405 AllowFiles: af, 406 }, nil 407 } 408 409 // attr.label_list(allow_empty=True, *, default=[], doc='', allow_files=None, providers=[], flags=[], mandatory=False, cfg=None, aspects=[]) 410 func attrLabelList(thread *starlark.Thread, fnname string, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 411 var ( 412 def *starlark.List 413 doc string 414 mandatory bool 415 allowEmpty bool = true 416 allowFiles starlark.Value 417 ) 418 if err := starlark.UnpackArgs( 419 fnname, args, kwargs, 420 "default?", &def, "doc?", &doc, "mandatory?", &mandatory, "allow_empty?", &allowEmpty, "allow_files?", &allowFiles, 421 ); err != nil { 422 return nil, err 423 } 424 425 var defValue starlark.Value = starlark.None 426 if def != nil { 427 iter := def.Iterate() 428 var x starlark.Value 429 for iter.Next(&x) { 430 if _, ok := starlark.AsString(x); !ok { 431 return nil, fmt.Errorf("got %s, want string", x.Type()) 432 } 433 } 434 iter.Done() 435 defValue = def 436 } 437 438 af, err := parseAllowFiles(allowFiles) 439 if err != nil { 440 return nil, err 441 } 442 443 return &Attr{ 444 Typ: AttrTypeLabelList, 445 Doc: doc, 446 Def: defValue, 447 Mandatory: mandatory, 448 AllowEmpty: allowEmpty, 449 AllowFiles: af, 450 }, nil 451 } 452 453 func attrString(thread *starlark.Thread, fnname string, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 454 var ( 455 def starlark.String 456 doc string 457 mandatory bool 458 values *starlark.List 459 ) 460 461 if err := starlark.UnpackArgs( 462 fnname, args, kwargs, 463 "default?", &def, "doc?", &doc, "mandatory?", &mandatory, "values?", &values, 464 ); err != nil { 465 return nil, err 466 } 467 468 var strings []string 469 if values != nil { 470 iter := values.Iterate() 471 var x starlark.Value 472 for iter.Next(&x) { 473 s, ok := starlark.AsString(x) 474 if !ok { 475 return nil, fmt.Errorf("got %s, want string", x.Type()) 476 } 477 strings = append(strings, s) 478 } 479 iter.Done() 480 } 481 482 return &Attr{ 483 Typ: AttrTypeString, 484 Def: def, 485 Doc: doc, 486 Mandatory: mandatory, 487 Values: strings, 488 }, nil 489 } 490 491 func attrStringList(thread *starlark.Thread, fnname string, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 492 var ( 493 def *starlark.List 494 doc string 495 mandatory bool 496 allowEmpty bool 497 ) 498 if err := starlark.UnpackArgs( 499 fnname, args, kwargs, 500 "default?", &def, "doc?", &doc, "mandatory?", &mandatory, "allowEmpty?", &allowEmpty, 501 ); err != nil { 502 return nil, err 503 } 504 505 // Check defaults are all strings 506 if def != nil { 507 iter := def.Iterate() 508 var x starlark.Value 509 for iter.Next(&x) { 510 if _, ok := starlark.AsString(x); !ok { 511 return nil, fmt.Errorf("got %s, want string", x.Type()) 512 } 513 } 514 iter.Done() 515 } 516 517 return &Attr{ 518 Typ: AttrTypeStringList, 519 Def: def, 520 Doc: doc, 521 Mandatory: mandatory, 522 }, nil 523 } 524 525 // Attrs -> AttrArgs 526 type Attrs struct { 527 osd starext.OrderedStringDict 528 frozen bool 529 } 530 531 func (a *Attrs) String() string { 532 buf := new(strings.Builder) 533 buf.WriteString("attrs") 534 buf.WriteByte('(') 535 for i := 0; i < a.osd.Len(); i++ { 536 k, v := a.osd.KeyIndex(i) 537 if i > 0 { 538 buf.WriteString(", ") 539 } 540 buf.WriteString(k) 541 buf.WriteString(" = ") 542 buf.WriteString(v.String()) 543 } 544 buf.WriteByte(')') 545 return buf.String() 546 } 547 func (a *Attrs) Truth() starlark.Bool { return true } // even when empty 548 func (a *Attrs) Type() string { return "attrs" } 549 func (a *Attrs) Hash() (uint32, error) { 550 // Same algorithm as struct... 551 var x, m uint32 = 8731, 9839 552 for i, n := 0, a.osd.Len(); i < n; i++ { 553 k, v := a.osd.KeyIndex(i) 554 namehash, _ := starlark.String(k).Hash() 555 x = x ^ 3*namehash 556 y, err := v.Hash() 557 if err != nil { 558 return 0, err 559 } 560 x = x ^ y*m 561 m += 7349 562 } 563 return x, nil 564 } 565 func (a *Attrs) Freeze() { 566 if a.frozen { 567 return 568 } 569 a.frozen = true 570 for i, n := 0, a.osd.Len(); i < n; i++ { 571 a.osd.Index(i).Freeze() 572 } 573 } 574 575 // checkMutable reports an error if the list should not be mutated. 576 // verb+" list" should describe the operation. 577 func (a *Attrs) checkMutable(verb string) error { 578 if a.frozen { 579 return fmt.Errorf("cannot %s frozen attrs", verb) 580 } 581 return nil 582 } 583 584 func (a *Attrs) Attr(name string) (starlark.Value, error) { 585 if v, ok := a.osd.Get(name); ok { 586 return v, nil 587 } 588 return nil, starlark.NoSuchAttrError( 589 fmt.Sprintf("attrs has no .%s attribute", name)) 590 } 591 func (a *Attrs) AttrNames() []string { return a.osd.Keys() } 592 593 func attrsEqual(x, y *Attrs, depth int) (bool, error) { 594 if x.Len() != y.Len() { 595 return false, nil 596 } 597 for i, n := 0, x.Len(); i < n; i++ { 598 x, y := x.Index(i).(*Attr), y.Index(i).(*Attr) 599 eq, err := attrEqual(x, y, depth-1) 600 if !eq || err != nil { 601 return eq, err 602 } 603 } 604 return true, nil 605 } 606 607 func (x *Attrs) CompareSameType(op syntax.Token, y_ starlark.Value, depth int) (bool, error) { 608 y := y_.(*Attrs) 609 switch op { 610 case syntax.EQL: 611 return attrsEqual(x, y, depth) 612 case syntax.NEQ: 613 eq, err := attrsEqual(x, y, depth) 614 return !eq, err 615 default: 616 return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type()) 617 } 618 } 619 func (a *Attrs) Index(i int) starlark.Value { return a.osd.Index(i) } 620 func (a *Attrs) Len() int { return a.osd.Len() } 621 622 func MakeAttrs(thread *starlark.Thread, fnname string, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 623 if err := starlark.UnpackArgs(fnname, args, nil); err != nil { 624 return nil, err 625 } 626 627 osd := starext.NewOrderedStringDict(len(kwargs)) 628 for _, kwarg := range kwargs { 629 name, _ := starlark.AsString(kwarg[0]) 630 a, ok := kwarg[1].(*Attr) 631 if !ok { 632 return nil, fmt.Errorf("unexpected attribute value type: %T", kwarg[1]) 633 } 634 osd.Insert(name, a) 635 } 636 osd.Sort() 637 638 return &Attrs{ 639 osd: *osd, 640 frozen: false, 641 }, nil 642 } 643 644 func (a *Attrs) Get(name string) (*Attr, bool) { 645 attr, ok := a.osd.Get(name) 646 if !ok { 647 return nil, ok 648 } 649 return attr.(*Attr), ok 650 } 651 652 func (a *Attrs) MakeArgs(source *Label, kwargs []starlark.Tuple) (*AttrArgs, error) { 653 attrSeen := make(map[string]bool) 654 attrArgs := starext.NewOrderedStringDict(len(kwargs)) 655 for _, kwarg := range kwargs { 656 name := string(kwarg[0].(starlark.String)) 657 value := kwarg[1] 658 659 attr, ok := a.Get(name) 660 if !ok { 661 return nil, fmt.Errorf("unexpected attribute: %s", name) 662 } 663 664 value, err := asAttrValue(source, name, attr, value) 665 if err != nil { 666 return nil, err 667 } 668 attrArgs.Insert(name, value) 669 attrSeen[name] = true 670 } 671 672 // Mandatory checks 673 for i, n := 0, a.osd.Len(); i < n; i++ { 674 name, x := a.osd.KeyIndex(i) 675 attr := x.(*Attr) 676 if !attrSeen[name] { 677 if attr.Mandatory { 678 return nil, fmt.Errorf("missing mandatory attribute: %s", name) 679 } 680 attrArgs.Insert(name, attr.Def) 681 } 682 } 683 attrArgs.Sort() 684 s := starlarkstruct.OrderedStringDictAsStruct(AttrArgsConstructor, attrArgs) 685 return &AttrArgs{ 686 attrs: a, 687 Struct: *s, 688 }, nil 689 } 690 691 func (a *Attrs) Name() string { return "attrargs" } 692 func (a *Attrs) CallInternal(thread *starlark.Thread, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { 693 if err := starlark.UnpackArgs("attrs", args, nil); err != nil { 694 return nil, err 695 } 696 source, err := ParseLabel(thread.Name) 697 if err != nil { 698 fmt.Println("Here?", err) 699 return nil, err 700 } 701 return a.MakeArgs(source, kwargs) 702 } 703 704 func asAttrValue( 705 source *Label, 706 name string, 707 attr *Attr, 708 value starlark.Value, 709 ) (starlark.Value, error) { 710 errField := func(msg string) error { 711 return fmt.Errorf( 712 "%s %s(%s): %v", msg, name, attr.Typ, value, 713 ) 714 } 715 errError := func(err error) error { 716 return fmt.Errorf( 717 "invalid %s(%s): %v: %v", 718 name, attr.Typ, value, err, 719 ) 720 } 721 toLabel := func(v starlark.Value) (*Label, error) { 722 switch v := (v).(type) { 723 case starlark.String: 724 l, err := source.Parse(string(v)) 725 if err != nil { 726 return nil, errError(err) 727 } 728 return l, nil 729 case *Label: 730 return v, nil 731 default: 732 return nil, errField("invalid") 733 } 734 } 735 736 if attr.IsValidType(value) { 737 return value, nil 738 } 739 740 switch attr.Typ { 741 case AttrTypeLabel: 742 if value == starlark.None { 743 return value, nil 744 } 745 746 l, err := toLabel(value) 747 if err != nil { 748 return nil, err 749 } 750 return l, nil 751 //case attrTypeLabelKeyedStringDict: 752 case AttrTypeLabelList: 753 if value == starlark.None { 754 return value, nil 755 } 756 757 list, ok := (value).(*starlark.List) 758 if !ok { 759 return nil, errField("type") 760 } 761 762 var elems []starlark.Value 763 for i, n := 0, list.Len(); i < n; i++ { 764 val := list.Index(i) 765 766 l, err := toLabel(val) 767 if err != nil { 768 return nil, err 769 } 770 elems = append(elems, l) 771 } 772 return starlark.NewList(elems), nil 773 default: 774 return nil, errField("undefined") 775 } 776 } 777 778 type AttrArgs struct { 779 attrs *Attrs 780 starlarkstruct.Struct 781 } 782 783 func attrArgsEqual(x, y *AttrArgs, depth int) (bool, error) { 784 if ok, err := attrsEqual(x.attrs, y.attrs, depth-1); !ok || err != nil { 785 return ok, err 786 } 787 return x.Struct.CompareSameType(syntax.EQL, &y.Struct, depth-1) 788 } 789 790 func (x *AttrArgs) CompareSameType(op syntax.Token, y_ starlark.Value, depth int) (bool, error) { 791 y := y_.(*AttrArgs) 792 switch op { 793 case syntax.EQL: 794 return attrArgsEqual(x, y, depth) 795 case syntax.NEQ: 796 eq, err := attrArgsEqual(x, y, depth) 797 return !eq, err 798 default: 799 return false, fmt.Errorf("%s %s %s not implemented", x.Type(), op, y.Type()) 800 } 801 } 802 803 func (a *AttrArgs) Attrs() *Attrs { return a.attrs } 804 805 func (a *AttrArgs) Clone() *AttrArgs { 806 osd := starext.NewOrderedStringDict(a.attrs.Len()) 807 a.ToOrderedStringDict(osd) 808 s := starlarkstruct.OrderedStringDictAsStruct(AttrArgsConstructor, osd) 809 return &AttrArgs{ 810 attrs: a.attrs, 811 Struct: *s, 812 } 813 } 814 815 var _ (starlark.Callable) = (*Attrs)(nil) 816 817 //go:embed info.star 818 var infoSrc string 819 820 var ( 821 DefaultInfo *Attrs 822 ContainerInfo *Attrs 823 ) 824 825 func init() { 826 info, err := starlark.ExecFile( 827 &starlark.Thread{Name: "internal"}, 828 "rule/info.star", 829 infoSrc, 830 starlark.StringDict{ 831 "attr": NewAttrModule(), 832 "attrs": starext.MakeBuiltin("rule.attrs", MakeAttrs), 833 }, 834 ) 835 if err != nil { 836 panic(err) 837 } 838 DefaultInfo = info["DefaultInfo"].(*Attrs) 839 ContainerInfo = info["ContainerInfo"].(*Attrs) 840 }