xref: /llvm-project/mlir/test/python/ir/attributes.py (revision 5d3ae5161210c068d01ffba36c8e0761e9971179)
1# RUN: %PYTHON %s | FileCheck %s
2
3import gc
4
5from mlir.ir import *
6
7
8def run(f):
9    print("\nTEST:", f.__name__)
10    f()
11    gc.collect()
12    assert Context._get_live_count() == 0
13    return f
14
15
16# CHECK-LABEL: TEST: testParsePrint
17@run
18def testParsePrint():
19    with Context() as ctx:
20        t = Attribute.parse('"hello"')
21    assert t.context is ctx
22    ctx = None
23    gc.collect()
24    # CHECK: "hello"
25    print(str(t))
26    # CHECK: StringAttr("hello")
27    print(repr(t))
28
29
30# CHECK-LABEL: TEST: testParseError
31@run
32def testParseError():
33    with Context():
34        try:
35            t = Attribute.parse("BAD_ATTR_DOES_NOT_EXIST")
36        except MLIRError as e:
37            # CHECK: testParseError: <
38            # CHECK:   Unable to parse attribute:
39            # CHECK:   error: "BAD_ATTR_DOES_NOT_EXIST":1:1: expected attribute value
40            # CHECK: >
41            print(f"testParseError: <{e}>")
42        else:
43            print("Exception not produced")
44
45
46# CHECK-LABEL: TEST: testAttrEq
47@run
48def testAttrEq():
49    with Context():
50        a1 = Attribute.parse('"attr1"')
51        a2 = Attribute.parse('"attr2"')
52        a3 = Attribute.parse('"attr1"')
53        # CHECK: a1 == a1: True
54        print("a1 == a1:", a1 == a1)
55        # CHECK: a1 == a2: False
56        print("a1 == a2:", a1 == a2)
57        # CHECK: a1 == a3: True
58        print("a1 == a3:", a1 == a3)
59        # CHECK: a1 is None: False
60        print("a1 is None:", a1 is None)
61
62
63# CHECK-LABEL: TEST: testAttrHash
64@run
65def testAttrHash():
66    with Context():
67        a1 = Attribute.parse('"attr1"')
68        a2 = Attribute.parse('"attr2"')
69        a3 = Attribute.parse('"attr1"')
70        # CHECK: hash(a1) == hash(a3): True
71        print("hash(a1) == hash(a3):", a1.__hash__() == a3.__hash__())
72
73        s = set()
74        s.add(a1)
75        s.add(a2)
76        s.add(a3)
77        # CHECK: len(s): 2
78        print("len(s): ", len(s))
79
80
81# CHECK-LABEL: TEST: testAttrCast
82@run
83def testAttrCast():
84    with Context():
85        a1 = Attribute.parse('"attr1"')
86        a2 = Attribute(a1)
87        # CHECK: a1 == a2: True
88        print("a1 == a2:", a1 == a2)
89
90
91# CHECK-LABEL: TEST: testAttrIsInstance
92@run
93def testAttrIsInstance():
94    with Context():
95        a1 = Attribute.parse("42")
96        a2 = Attribute.parse("[42]")
97        assert IntegerAttr.isinstance(a1)
98        assert not IntegerAttr.isinstance(a2)
99        assert not ArrayAttr.isinstance(a1)
100        assert ArrayAttr.isinstance(a2)
101
102
103# CHECK-LABEL: TEST: testAttrEqDoesNotRaise
104@run
105def testAttrEqDoesNotRaise():
106    with Context():
107        a1 = Attribute.parse('"attr1"')
108        not_an_attr = "foo"
109        # CHECK: False
110        print(a1 == not_an_attr)
111        # CHECK: False
112        print(a1 is None)
113        # CHECK: True
114        print(a1 is not None)
115
116
117# CHECK-LABEL: TEST: testAttrCapsule
118@run
119def testAttrCapsule():
120    with Context() as ctx:
121        a1 = Attribute.parse('"attr1"')
122    # CHECK: mlir.ir.Attribute._CAPIPtr
123    attr_capsule = a1._CAPIPtr
124    print(attr_capsule)
125    a2 = Attribute._CAPICreate(attr_capsule)
126    assert a2 == a1
127    assert a2.context is ctx
128
129
130# CHECK-LABEL: TEST: testStandardAttrCasts
131@run
132def testStandardAttrCasts():
133    with Context():
134        a1 = Attribute.parse('"attr1"')
135        astr = StringAttr(a1)
136        aself = StringAttr(astr)
137        # CHECK: StringAttr("attr1")
138        print(repr(astr))
139        try:
140            tillegal = StringAttr(Attribute.parse("1.0"))
141        except ValueError as e:
142            # CHECK: ValueError: Cannot cast attribute to StringAttr (from Attribute(1.000000e+00 : f64))
143            print("ValueError:", e)
144        else:
145            print("Exception not produced")
146
147
148# CHECK-LABEL: TEST: testAffineMapAttr
149@run
150def testAffineMapAttr():
151    with Context() as ctx:
152        d0 = AffineDimExpr.get(0)
153        d1 = AffineDimExpr.get(1)
154        c2 = AffineConstantExpr.get(2)
155        map0 = AffineMap.get(2, 3, [])
156
157        # CHECK: affine_map<(d0, d1)[s0, s1, s2] -> ()>
158        attr_built = AffineMapAttr.get(map0)
159        print(str(attr_built))
160        assert attr_built.value == map0
161        attr_parsed = Attribute.parse(str(attr_built))
162        assert attr_built == attr_parsed
163
164
165# CHECK-LABEL: TEST: testIntegerSetAttr
166@run
167def testIntegerSetAttr():
168    with Context() as ctx:
169        d0 = AffineDimExpr.get(0)
170        d1 = AffineDimExpr.get(1)
171        s0 = AffineSymbolExpr.get(0)
172        c42 = AffineConstantExpr.get(42)
173        set0 = IntegerSet.get(2, 1, [d0 - d1, s0 - c42], [True, False])
174
175        # CHECK: affine_set<(d0, d1)[s0] : (d0 - d1 == 0, s0 - 42 >= 0)>
176        attr_built = IntegerSetAttr.get(set0)
177        print(str(attr_built))
178
179        attr_parsed = Attribute.parse(str(attr_built))
180        assert attr_built == attr_parsed
181
182
183# CHECK-LABEL: TEST: testFloatAttr
184@run
185def testFloatAttr():
186    with Context(), Location.unknown():
187        fattr = FloatAttr(Attribute.parse("42.0 : f32"))
188        # CHECK: fattr value: 42.0
189        print("fattr value:", fattr.value)
190        # CHECK: fattr float: 42.0 <class 'float'>
191        print("fattr float:", float(fattr), type(float(fattr)))
192
193        # Test factory methods.
194        # CHECK: default_get: 4.200000e+01 : f32
195        print("default_get:", FloatAttr.get(F32Type.get(), 42.0))
196        # CHECK: f32_get: 4.200000e+01 : f32
197        print("f32_get:", FloatAttr.get_f32(42.0))
198        # CHECK: f64_get: 4.200000e+01 : f64
199        print("f64_get:", FloatAttr.get_f64(42.0))
200        try:
201            fattr_invalid = FloatAttr.get(IntegerType.get_signless(32), 42)
202        except MLIRError as e:
203            # CHECK: Invalid attribute:
204            # CHECK: error: unknown: expected floating point type
205            print(e)
206        else:
207            print("Exception not produced")
208
209
210# CHECK-LABEL: TEST: testIntegerAttr
211@run
212def testIntegerAttr():
213    with Context() as ctx:
214        i_attr = IntegerAttr(Attribute.parse("42"))
215        # CHECK: i_attr value: 42
216        print("i_attr value:", i_attr.value)
217        # CHECK: i_attr type: i64
218        print("i_attr type:", i_attr.type)
219        # CHECK: i_attr int: 42 <class 'int'>
220        print("i_attr int:", int(i_attr), type(int(i_attr)))
221        si_attr = IntegerAttr(Attribute.parse("-1 : si8"))
222        # CHECK: si_attr value: -1
223        print("si_attr value:", si_attr.value)
224        ui_attr = IntegerAttr(Attribute.parse("255 : ui8"))
225        # CHECK: i_attr int: -1 <class 'int'>
226        print("si_attr int:", int(si_attr), type(int(si_attr)))
227        # CHECK: ui_attr value: 255
228        print("ui_attr value:", ui_attr.value)
229        # CHECK: i_attr int: 255 <class 'int'>
230        print("ui_attr int:", int(ui_attr), type(int(ui_attr)))
231        idx_attr = IntegerAttr(Attribute.parse("-1 : index"))
232        # CHECK: idx_attr value: -1
233        print("idx_attr value:", idx_attr.value)
234        # CHECK: idx_attr int: -1 <class 'int'>
235        print("idx_attr int:", int(idx_attr), type(int(idx_attr)))
236
237        # Test factory methods.
238        # CHECK: default_get: 42 : i32
239        print("default_get:", IntegerAttr.get(IntegerType.get_signless(32), 42))
240
241
242# CHECK-LABEL: TEST: testBoolAttr
243@run
244def testBoolAttr():
245    with Context() as ctx:
246        battr = BoolAttr(Attribute.parse("true"))
247        # CHECK: iattr value: True
248        print("iattr value:", battr.value)
249        # CHECK: iattr bool: True <class 'bool'>
250        print("iattr bool:", bool(battr), type(bool(battr)))
251
252        # Test factory methods.
253        # CHECK: default_get: true
254        print("default_get:", BoolAttr.get(True))
255
256
257# CHECK-LABEL: TEST: testFlatSymbolRefAttr
258@run
259def testFlatSymbolRefAttr():
260    with Context() as ctx:
261        sattr = Attribute.parse("@symbol")
262        # CHECK: symattr value: symbol
263        print("symattr value:", sattr.value)
264
265        # Test factory methods.
266        # CHECK: default_get: @foobar
267        print("default_get:", FlatSymbolRefAttr.get("foobar"))
268
269
270# CHECK-LABEL: TEST: testSymbolRefAttr
271@run
272def testSymbolRefAttr():
273    with Context() as ctx:
274        sattr = Attribute.parse("@symbol1::@symbol2")
275        # CHECK: symattr value: ['symbol1', 'symbol2']
276        print("symattr value:", sattr.value)
277
278        # CHECK: default_get: @symbol1::@symbol2
279        print("default_get:", SymbolRefAttr.get(["symbol1", "symbol2"]))
280
281        # CHECK: default_get: @"@symbol1"::@"@symbol2"
282        print("default_get:", SymbolRefAttr.get(["@symbol1", "@symbol2"]))
283
284
285# CHECK-LABEL: TEST: testOpaqueAttr
286@run
287def testOpaqueAttr():
288    with Context() as ctx:
289        ctx.allow_unregistered_dialects = True
290        oattr = OpaqueAttr(Attribute.parse("#pytest_dummy.dummyattr<>"))
291        # CHECK: oattr value: pytest_dummy
292        print("oattr value:", oattr.dialect_namespace)
293        # CHECK: oattr value: b'dummyattr<>'
294        print("oattr value:", oattr.data)
295
296        # Test factory methods.
297        # CHECK: default_get: #foobar<123>
298        print(
299            "default_get:",
300            OpaqueAttr.get("foobar", bytes("123", "utf-8"), NoneType.get()),
301        )
302
303
304# CHECK-LABEL: TEST: testStringAttr
305@run
306def testStringAttr():
307    with Context() as ctx:
308        sattr = StringAttr(Attribute.parse('"stringattr"'))
309        # CHECK: sattr value: stringattr
310        print("sattr value:", sattr.value)
311        # CHECK: sattr value: b'stringattr'
312        print("sattr value:", sattr.value_bytes)
313
314        # Test factory methods.
315        # CHECK: default_get: "foobar"
316        print("default_get:", StringAttr.get("foobar"))
317        # CHECK: typed_get: "12345" : i32
318        print("typed_get:", StringAttr.get_typed(IntegerType.get_signless(32), "12345"))
319
320
321# CHECK-LABEL: TEST: testNamedAttr
322@run
323def testNamedAttr():
324    with Context():
325        a = Attribute.parse('"stringattr"')
326        named = a.get_named("foobar")  # Note: under the small object threshold
327        # CHECK: attr: "stringattr"
328        print("attr:", named.attr)
329        # CHECK: name: foobar
330        print("name:", named.name)
331        # CHECK: named: NamedAttribute(foobar="stringattr")
332        print("named:", named)
333
334
335# CHECK-LABEL: TEST: testDenseIntAttr
336@run
337def testDenseIntAttr():
338    with Context():
339        raw = Attribute.parse("dense<[[0,1,2],[3,4,5]]> : vector<2x3xi32>")
340        # CHECK: attr: dense<[{{\[}}0, 1, 2], [3, 4, 5]]>
341        print("attr:", raw)
342
343        a = DenseIntElementsAttr(raw)
344        assert len(a) == 6
345
346        # CHECK: 0 1 2 3 4 5
347        for value in a:
348            print(value, end=" ")
349        print()
350
351        # CHECK: i32
352        print(ShapedType(a.type).element_type)
353
354        raw = Attribute.parse("dense<[true,false,true,false]> : vector<4xi1>")
355        # CHECK: attr: dense<[true, false, true, false]>
356        print("attr:", raw)
357
358        a = DenseIntElementsAttr(raw)
359        assert len(a) == 4
360
361        # CHECK: 1 0 1 0
362        for value in a:
363            print(value, end=" ")
364        print()
365
366        # CHECK: i1
367        print(ShapedType(a.type).element_type)
368
369        shape = Attribute.parse("dense<[0, 1, 2, 3]> : vector<4xindex>")
370        # CHECK: attr: dense<[0, 1, 2, 3]>
371        print("attr:", shape)
372
373
374@run
375def testDenseArrayGetItem():
376    def print_item(attr_asm):
377        attr = Attribute.parse(attr_asm)
378        print(f"{len(attr)}: {attr[0]}, {attr[1]}")
379
380    with Context():
381        # CHECK: 2: False, True
382        print_item("array<i1: false, true>")
383        # CHECK: 2: 2, 3
384        print_item("array<i8: 2, 3>")
385        # CHECK: 2: 4, 5
386        print_item("array<i16: 4, 5>")
387        # CHECK: 2: 6, 7
388        print_item("array<i32: 6, 7>")
389        # CHECK: 2: 8, 9
390        print_item("array<i64: 8, 9>")
391        # CHECK: 2: 1.{{0+}}, 2.{{0+}}
392        print_item("array<f32: 1.0, 2.0>")
393        # CHECK: 2: 3.{{0+}}, 4.{{0+}}
394        print_item("array<f64: 3.0, 4.0>")
395
396        class MyBool:
397            def __bool__(self):
398                return True
399
400        # CHECK: myboolarray: array<i1: true>
401        print("myboolarray:", DenseBoolArrayAttr.get([MyBool()]))
402
403
404# CHECK-LABEL: TEST: testDenseArrayAttrConstruction
405@run
406def testDenseArrayAttrConstruction():
407    with Context(), Location.unknown():
408
409        def create_and_print(cls, x):
410            try:
411                darr = cls.get(x)
412                print(f"input: {x} ({type(x)}), result: {darr}")
413            except Exception as ex:
414                print(f"input: {x} ({type(x)}), error: {ex}")
415
416        # CHECK: input: [4, 2] (<class 'list'>),
417        # CHECK-SAME: result: array<i8: 4, 2>
418        create_and_print(DenseI8ArrayAttr, [4, 2])
419
420        # CHECK: input: [4, 2.0] (<class 'list'>),
421        # CHECK-SAME: error: get(): incompatible function arguments
422        create_and_print(DenseI8ArrayAttr, [4, 2.0])
423
424        # CHECK: input: [40000, 2] (<class 'list'>),
425        # CHECK-SAME: error: get(): incompatible function arguments
426        create_and_print(DenseI8ArrayAttr, [40000, 2])
427
428        # CHECK: input: range(0, 4) (<class 'range'>),
429        # CHECK-SAME: result: array<i8: 0, 1, 2, 3>
430        create_and_print(DenseI8ArrayAttr, range(4))
431
432        # CHECK: input: [IntegerAttr(4 : i64), IntegerAttr(2 : i64)] (<class 'list'>),
433        # CHECK-SAME: result: array<i8: 4, 2>
434        create_and_print(DenseI8ArrayAttr, [Attribute.parse(f"{x}") for x in [4, 2]])
435
436        # CHECK: input: [IntegerAttr(4000 : i64), IntegerAttr(2 : i64)] (<class 'list'>),
437        # CHECK-SAME: error: get(): incompatible function arguments
438        create_and_print(DenseI8ArrayAttr, [Attribute.parse(f"{x}") for x in [4000, 2]])
439
440        # CHECK: input: [IntegerAttr(4 : i64), FloatAttr(2.000000e+00 : f64)] (<class 'list'>),
441        # CHECK-SAME: error: get(): incompatible function arguments
442        create_and_print(DenseI8ArrayAttr, [Attribute.parse(f"{x}") for x in [4, 2.0]])
443
444        # CHECK: input: [IntegerAttr(4 : i8), IntegerAttr(2 : ui16)] (<class 'list'>),
445        # CHECK-SAME: result: array<i8: 4, 2>
446        create_and_print(
447            DenseI8ArrayAttr, [Attribute.parse(s) for s in ["4 : i8", "2 : ui16"]]
448        )
449
450        # CHECK: input: [FloatAttr(4.000000e+00 : f64), FloatAttr(2.000000e+00 : f64)] (<class 'list'>)
451        # CHECK-SAME: result: array<f32: 4.000000e+00, 2.000000e+00>
452        create_and_print(
453            DenseF32ArrayAttr, [Attribute.parse(f"{x}") for x in [4.0, 2.0]]
454        )
455
456        # CHECK: [BoolAttr(true), BoolAttr(false)] (<class 'list'>),
457        # CHECK-SAME: result: array<i1: true, false>
458        create_and_print(
459            DenseBoolArrayAttr, [Attribute.parse(f"{x}") for x in ["true", "false"]]
460        )
461
462
463# CHECK-LABEL: TEST: testDenseIntAttrGetItem
464@run
465def testDenseIntAttrGetItem():
466    def print_item(attr_asm):
467        attr = Attribute.parse(attr_asm)
468        dtype = ShapedType(attr.type).element_type
469        try:
470            item = attr[0]
471            print(f"{dtype}:", item)
472        except TypeError as e:
473            print(f"{dtype}:", e)
474
475    with Context():
476        # CHECK: i1: 1
477        print_item("dense<true> : tensor<i1>")
478        # CHECK: i8: 123
479        print_item("dense<123> : tensor<i8>")
480        # CHECK: i16: 123
481        print_item("dense<123> : tensor<i16>")
482        # CHECK: i32: 123
483        print_item("dense<123> : tensor<i32>")
484        # CHECK: i64: 123
485        print_item("dense<123> : tensor<i64>")
486        # CHECK: ui8: 123
487        print_item("dense<123> : tensor<ui8>")
488        # CHECK: ui16: 123
489        print_item("dense<123> : tensor<ui16>")
490        # CHECK: ui32: 123
491        print_item("dense<123> : tensor<ui32>")
492        # CHECK: ui64: 123
493        print_item("dense<123> : tensor<ui64>")
494        # CHECK: si8: -123
495        print_item("dense<-123> : tensor<si8>")
496        # CHECK: si16: -123
497        print_item("dense<-123> : tensor<si16>")
498        # CHECK: si32: -123
499        print_item("dense<-123> : tensor<si32>")
500        # CHECK: si64: -123
501        print_item("dense<-123> : tensor<si64>")
502
503        # CHECK: i7: Unsupported integer type
504        print_item("dense<123> : tensor<i7>")
505
506
507# CHECK-LABEL: TEST: testDenseFPAttr
508@run
509def testDenseFPAttr():
510    with Context():
511        raw = Attribute.parse("dense<[0.0, 1.0, 2.0, 3.0]> : vector<4xf32>")
512        # CHECK: attr: dense<[0.000000e+00, 1.000000e+00, 2.000000e+00, 3.000000e+00]>
513
514        print("attr:", raw)
515
516        a = DenseFPElementsAttr(raw)
517        assert len(a) == 4
518
519        # CHECK: 0.0 1.0 2.0 3.0
520        for value in a:
521            print(value, end=" ")
522        print()
523
524        # CHECK: f32
525        print(ShapedType(a.type).element_type)
526
527
528# CHECK-LABEL: TEST: testDictAttr
529@run
530def testDictAttr():
531    with Context():
532        dict_attr = {
533            "stringattr": StringAttr.get("string"),
534            "integerattr": IntegerAttr.get(IntegerType.get_signless(32), 42),
535        }
536
537        a = DictAttr.get(dict_attr)
538
539        # CHECK: attr: {integerattr = 42 : i32, stringattr = "string"}
540        print("attr:", a)
541
542        assert len(a) == 2
543
544        # CHECK: integerattr: IntegerAttr(42 : i32)
545        print("integerattr:", repr(a["integerattr"]))
546
547        # CHECK: stringattr: StringAttr("string")
548        print("stringattr:", repr(a["stringattr"]))
549
550        # CHECK: True
551        print("stringattr" in a)
552
553        # CHECK: False
554        print("not_in_dict" in a)
555
556        # Check that exceptions are raised as expected.
557        try:
558            _ = a["does_not_exist"]
559        except KeyError:
560            pass
561        else:
562            assert False, "Exception not produced"
563
564        try:
565            _ = a[42]
566        except IndexError:
567            pass
568        else:
569            assert False, "expected IndexError on accessing an out-of-bounds attribute"
570
571        # CHECK: empty: {}
572        print("empty: ", DictAttr.get())
573
574
575# CHECK-LABEL: TEST: testTypeAttr
576@run
577def testTypeAttr():
578    with Context():
579        raw = Attribute.parse("vector<4xf32>")
580        # CHECK: attr: vector<4xf32>
581        print("attr:", raw)
582        type_attr = TypeAttr(raw)
583        # CHECK: f32
584        print(ShapedType(type_attr.value).element_type)
585
586
587# CHECK-LABEL: TEST: testArrayAttr
588@run
589def testArrayAttr():
590    with Context():
591        arr = Attribute.parse("[42, true, vector<4xf32>]")
592    # CHECK: arr: [42, true, vector<4xf32>]
593    print("arr:", arr)
594    # CHECK: - IntegerAttr(42 : i64)
595    # CHECK: - BoolAttr(true)
596    # CHECK: - TypeAttr(vector<4xf32>)
597    for attr in arr:
598        print("- ", repr(attr))
599
600    with Context():
601        intAttr = Attribute.parse("42")
602        vecAttr = Attribute.parse("vector<4xf32>")
603        boolAttr = BoolAttr.get(True)
604        raw = ArrayAttr.get([vecAttr, boolAttr, intAttr])
605    # CHECK: attr: [vector<4xf32>, true, 42]
606    print("raw attr:", raw)
607    # CHECK: - TypeAttr(vector<4xf32>)
608    # CHECK: - BoolAttr(true
609    # CHECK: - IntegerAttr(42 : i64)
610    arr = raw
611    for attr in arr:
612        print("- ", repr(attr))
613    # CHECK: attr[0]: TypeAttr(vector<4xf32>)
614    print("attr[0]:", repr(arr[0]))
615    # CHECK: attr[1]: BoolAttr(true)
616    print("attr[1]:", repr(arr[1]))
617    # CHECK: attr[2]: IntegerAttr(42 : i64)
618    print("attr[2]:", repr(arr[2]))
619    try:
620        print("attr[3]:", arr[3])
621    except IndexError as e:
622        # CHECK: Error: ArrayAttribute index out of range
623        print("Error: ", e)
624    with Context():
625        try:
626            ArrayAttr.get([None])
627        except RuntimeError as e:
628            # CHECK: Error: Invalid attribute (None?) when attempting to create an ArrayAttribute
629            print("Error: ", e)
630        try:
631            ArrayAttr.get([42])
632        except RuntimeError as e:
633            # CHECK: Error: Invalid attribute when attempting to create an ArrayAttribute
634            print("Error: ", e)
635
636    with Context():
637        array = ArrayAttr.get([StringAttr.get("a"), StringAttr.get("b")])
638        array = array + [StringAttr.get("c")]
639        # CHECK: concat: ["a", "b", "c"]
640        print("concat: ", array)
641
642
643# CHECK-LABEL: TEST: testStridedLayoutAttr
644@run
645def testStridedLayoutAttr():
646    with Context():
647        attr = StridedLayoutAttr.get(42, [5, 7, 13])
648        # CHECK: strided<[5, 7, 13], offset: 42>
649        print(attr)
650        # CHECK: 42
651        print(attr.offset)
652        # CHECK: 3
653        print(len(attr.strides))
654        # CHECK: 5
655        print(attr.strides[0])
656        # CHECK: 7
657        print(attr.strides[1])
658        # CHECK: 13
659        print(attr.strides[2])
660
661        attr = StridedLayoutAttr.get_fully_dynamic(3)
662        dynamic = ShapedType.get_dynamic_stride_or_offset()
663        # CHECK: strided<[?, ?, ?], offset: ?>
664        print(attr)
665        # CHECK: offset is dynamic: True
666        print(f"offset is dynamic: {attr.offset == dynamic}")
667        # CHECK: rank: 3
668        print(f"rank: {len(attr.strides)}")
669        # CHECK: strides are dynamic: [True, True, True]
670        print(f"strides are dynamic: {[s == dynamic for s in attr.strides]}")
671
672
673# CHECK-LABEL: TEST: testConcreteTypesRoundTrip
674@run
675def testConcreteTypesRoundTrip():
676    with Context(), Location.unknown():
677
678        def print_item(attr):
679            print(repr(attr.type))
680
681        # CHECK: F32Type(f32)
682        print_item(Attribute.parse("42.0 : f32"))
683        # CHECK: F32Type(f32)
684        print_item(FloatAttr.get_f32(42.0))
685        # CHECK: IntegerType(i64)
686        print_item(IntegerAttr.get(IntegerType.get_signless(64), 42))
687
688        def print_container_item(attr_asm):
689            attr = DenseElementsAttr(Attribute.parse(attr_asm))
690            print(repr(attr.type))
691            print(repr(attr.type.element_type))
692
693        # CHECK: RankedTensorType(tensor<i16>)
694        # CHECK: IntegerType(i16)
695        print_container_item("dense<123> : tensor<i16>")
696
697        # CHECK: RankedTensorType(tensor<f64>)
698        # CHECK: F64Type(f64)
699        print_container_item("dense<1.0> : tensor<f64>")
700
701        raw = Attribute.parse("vector<4xf32>")
702        # CHECK: attr: vector<4xf32>
703        print("attr:", raw)
704        type_attr = TypeAttr(raw)
705
706        # CHECK: VectorType(vector<4xf32>)
707        print(repr(type_attr.value))
708        # CHECK: F32Type(f32)
709        print(repr(type_attr.value.element_type))
710
711
712# CHECK-LABEL: TEST: testConcreteAttributesRoundTrip
713@run
714def testConcreteAttributesRoundTrip():
715    with Context(), Location.unknown():
716        # CHECK: FloatAttr(4.200000e+01 : f32)
717        print(repr(Attribute.parse("42.0 : f32")))
718
719        assert IntegerAttr.static_typeid is not None
720