1# Copyright 2019 Google LLC 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""Tests for module_ir.""" 16 17from __future__ import print_function 18 19import collections 20import pkgutil 21import unittest 22 23from compiler.front_end import module_ir 24from compiler.front_end import parser 25from compiler.front_end import tokenizer 26from compiler.util import ir_data 27from compiler.util import ir_data_fields 28from compiler.util import ir_data_utils 29from compiler.util import test_util 30 31_TESTDATA_PATH = "testdata.golden" 32_MINIMAL_SOURCE = pkgutil.get_data( 33 _TESTDATA_PATH, "span_se_log_file_status.emb").decode(encoding="UTF-8") 34_MINIMAL_SAMPLE = parser.parse_module( 35 tokenizer.tokenize(_MINIMAL_SOURCE, "")[0]).parse_tree 36_MINIMAL_SAMPLE_IR = ir_data_utils.IrDataSerializer.from_json(ir_data.Module, 37 pkgutil.get_data(_TESTDATA_PATH, "span_se_log_file_status.ir.txt").decode( 38 encoding="UTF-8") 39) 40 41# _TEST_CASES contains test cases, separated by '===', that ensure that specific 42# results show up in the IR for .embs. 43# 44# Each test case is of the form: 45# 46# name 47# --- 48# .emb text 49# --- 50# (incomplete) IR text format 51# 52# For each test case, the .emb is parsed into a parse tree, which is fed into 53# module_ir.build_ir(), which should successfully return an IR. The generated 54# IR is then compared against the incomplete IR in the test case to ensure that 55# the generated IR is a strict superset of the test case IR -- that is, it is OK 56# if the generated IR contains fields that are not in the test case, but not if 57# the test case contains fields that are not in the generated IR, and not if the 58# test case contains fields whose values differ from the generated IR. 59# 60# Additionally, for each test case, a pass is executed to ensure that the source 61# code location for each node in the IR is strictly contained within the source 62# location for its parent node. 63_TEST_CASES = r""" 64prelude 65--- 66external UInt: 67 [fixed_size: false] 68 [byte_order_dependent: true] 69 70external Byte: 71 [size: 1] 72 [byte_order_dependent: false] 73--- 74{ 75 "type": [ 76 { 77 "external": {}, 78 "name": { "name": { "text": "UInt" } }, 79 "attribute": [ 80 { 81 "name": { "text": "fixed_size" }, 82 "value": { "expression": { "boolean_constant": { "value": false } } } 83 }, 84 { 85 "name": { "text": "byte_order_dependent" }, 86 "value": { "expression": { "boolean_constant": { "value": true } } } 87 } 88 ] 89 }, 90 { 91 "external": {}, 92 "name": { "name": { "text": "Byte" } }, 93 "attribute": [ 94 { 95 "name": { "text": "size" }, 96 "value": { "expression": { "constant": { "value": "1" } } } 97 }, 98 { 99 "name": { "text": "byte_order_dependent" }, 100 "value": { "expression": { "boolean_constant": { "value": false } } } 101 } 102 ] 103 } 104 ] 105} 106 107=== 108numbers 109--- 110bits Foo: 111 0000000000 [+0_000_000_003] UInt decimal 112 0b00000100 [+0b0000_0111] UInt binary 113 0b00000000_00001000 [+0b0_00001011] UInt binary2 114 0b_0_00001100 [+0b_00001111] UInt binary3 115 0x00000010 [+0x0000_0013] UInt hex 116 0x00000000_00000014 [+0x0_00000017] UInt hex2 117 0x_0_00000018 [+0x_0000001b] UInt hex3 118--- 119{ 120 "type": [ 121 { 122 "structure": { 123 "field": [ 124 { 125 "name": { "name": { "text": "decimal" } }, 126 "location": { 127 "start": { "constant": { "value": "0" } }, 128 "size": { "constant": { "value": "3" } } 129 } 130 }, 131 { 132 "name": { "name": { "text": "binary" } }, 133 "location": { 134 "start": { "constant": { "value": "4" } }, 135 "size": { "constant": { "value": "7" } 136 } 137 } 138 }, 139 { 140 "name": { "name": { "text": "binary2" } }, 141 "location": { 142 "start": { "constant": { "value": "8" } }, 143 "size": { "constant": { "value": "11" } } 144 } 145 }, 146 { 147 "name": { "name": { "text": "binary3" } }, 148 "location": { 149 "start": { "constant": { "value": "12" } }, 150 "size": { "constant": { "value": "15" } } 151 } 152 }, 153 { 154 "name": { "name": { "text": "hex" } }, 155 "location": { 156 "start": { "constant": { "value": "16" } }, 157 "size": { "constant": { "value": "19" } } 158 } 159 }, 160 { 161 "name": { "name": { "text": "hex2" } }, 162 "location": { 163 "start": { "constant": { "value": "20" } }, 164 "size": { "constant": { "value": "23" } } 165 } 166 }, 167 { 168 "name": { "name": { "text": "hex3" } }, 169 "location": { 170 "start": { "constant": { "value": "24" } }, 171 "size": { "constant": { "value": "27" } } 172 } 173 } 174 ] 175 } 176 } 177 ] 178} 179 180=== 181enum 182--- 183enum Kind: 184 WIDGET = 0 185 SPROCKET = 1 186 GEEGAW = 2 # Comment. 187 MAX32 = 4294967295 188 MAX64 = 9223372036854775807 189--- 190{ 191 "type": [ 192 { 193 "enumeration": { 194 "value": [ 195 { 196 "name": { "name": { "text": "WIDGET" } }, 197 "value": { "constant": { "value": "0" } } 198 }, 199 { 200 "name": { "name": { "text": "SPROCKET" } }, 201 "value": { "constant": { "value": "1" } } 202 }, 203 { 204 "name": { "name": { "text": "GEEGAW" } }, 205 "value": { "constant": { "value": "2" } } 206 }, 207 { 208 "name": { "name": { "text": "MAX32" } }, 209 "value": { "constant": { "value": "4294967295" } } 210 }, 211 { 212 "name": { "name": { "text": "MAX64" } }, 213 "value": { "constant": { "value": "9223372036854775807" } } 214 } 215 ] 216 }, 217 "name": { "name": { "text": "Kind" } } 218 } 219 ] 220} 221 222=== 223struct attribute 224--- 225struct Foo: 226 [size: 10] 227 0 [+0] UInt field 228--- 229{ 230 "type": [ 231 { 232 "structure": { 233 "field": [ { "name": { "name": { "text": "field" } } } ] 234 }, 235 "name": { "name": { "text": "Foo" } }, 236 "attribute": [ 237 { 238 "name": { "text": "size" }, 239 "value": { "expression": { "constant": { "value": "10" } } }, 240 "is_default": false 241 } 242 ] 243 } 244 ] 245} 246 247=== 248$default attribute 249--- 250[$default byte_order: "LittleEndian"] 251--- 252{ 253 "attribute": [ 254 { 255 "name": { "text": "byte_order" }, 256 "value": { "string_constant": { "text": "LittleEndian" } }, 257 "is_default": true 258 } 259 ] 260} 261 262=== 263abbreviations 264--- 265struct Foo: 266 0 [+1] UInt size (s) 267--- 268{ 269 "type": [ 270 { 271 "structure": { 272 "field": [ 273 { 274 "name": { "name": { "text": "size" } }, 275 "abbreviation": { "text": "s" } 276 } 277 ] 278 } 279 } 280 ] 281} 282 283=== 284expressions 285--- 286struct Foo: 287 0+1 [+2*3] UInt plus_times 288 4-5 [+(6)] UInt minus_paren 289 nn [+7*(8+9)] UInt name_complex 290 10+11+12 [+13*14*15] UInt associativity 291 16+17*18 [+19*20-21] UInt precedence 292 -(+1) [+0-(-10)] UInt unary_plus_minus 293 1 + + 2 [+3 - -4 - 5] UInt unary_plus_minus_2 294--- 295{ 296 "type": [ 297 { 298 "structure": { 299 "field": [ 300 { 301 "name": { "name": { "text": "plus_times" } }, 302 "location": { 303 "start": { 304 "function": { 305 "function": "ADDITION", 306 "function_name": { "text": "+" }, 307 "args": [ 308 { "constant": { "value": "0" } }, 309 { "constant": { "value": "1" } } 310 ] 311 } 312 }, 313 "size": { 314 "function": { 315 "function": "MULTIPLICATION", 316 "function_name": { "text": "*" }, 317 "args": [ 318 { "constant": { "value": "2" } }, 319 { "constant": { "value": "3" } } 320 ] 321 } 322 } 323 } 324 }, 325 { 326 "name": { "name": { "text": "minus_paren" } }, 327 "location": { 328 "start": { 329 "function": { 330 "function": "SUBTRACTION", 331 "args": [ 332 { "constant": { "value": "4" } }, 333 { "constant": { "value": "5" } } 334 ] 335 } 336 }, 337 "size": { "constant": { "value": "6" } } 338 } 339 }, 340 { 341 "name": { "name": { "text": "name_complex" } }, 342 "location": { 343 "start": { 344 "field_reference": { 345 "path": [ { "source_name": [ { "text": "nn" } ] } ] 346 } 347 }, 348 "size": { 349 "function": { 350 "function": "MULTIPLICATION", 351 "args": [ 352 { "constant": { "value": "7" } }, 353 { 354 "function": { 355 "function": "ADDITION", 356 "args": [ 357 { "constant": { "value": "8" } }, 358 { "constant": { "value": "9" } } 359 ] 360 } 361 } 362 ] 363 } 364 } 365 } 366 }, 367 { 368 "name": { "name": { "text": "associativity" } }, 369 "location": { 370 "start": { 371 "function": { 372 "function": "ADDITION", 373 "args": [ 374 { 375 "function": { 376 "function": "ADDITION", 377 "args": [ 378 { "constant": { "value": "10" } }, 379 { "constant": { "value": "11" } } 380 ] 381 } 382 }, 383 { "constant": { "value": "12" } } 384 ] 385 } 386 }, 387 "size": { 388 "function": { 389 "function": "MULTIPLICATION", 390 "args": [ 391 { 392 "function": { 393 "function": "MULTIPLICATION", 394 "args": [ 395 { "constant": { "value": "13" } }, 396 { "constant": { "value": "14" } } 397 ] 398 } 399 }, 400 { "constant": { "value": "15" } } 401 ] 402 } 403 } 404 } 405 }, 406 { 407 "name": { "name": { "text": "precedence" } }, 408 "location": { 409 "start": { 410 "function": { 411 "function": "ADDITION", 412 "args": [ 413 { "constant": { "value": "16" } }, 414 { 415 "function": { 416 "function": "MULTIPLICATION", 417 "args": [ 418 { "constant": { "value": "17" } }, 419 { "constant": { "value": "18" } } 420 ] 421 } 422 } 423 ] 424 } 425 }, 426 "size": { 427 "function": { 428 "function": "SUBTRACTION", 429 "args": [ 430 { 431 "function": { 432 "function": "MULTIPLICATION", 433 "args": [ 434 { "constant": { "value": "19" } }, 435 { "constant": { "value": "20" } } 436 ] 437 } 438 }, 439 { "constant": { "value": "21" } } 440 ] 441 } 442 } 443 } 444 }, 445 { 446 "name": { "name": { "text": "unary_plus_minus" } }, 447 "location": { 448 "start": { 449 "function": { 450 "function": "SUBTRACTION", 451 "function_name": { 452 "text": "-", 453 "source_location": { 454 "start": { "line": 8, "column": 3 }, 455 "end": { "line": 8, "column": 4 } 456 } 457 }, 458 "args": [ 459 { 460 "constant": { 461 "value": "0", 462 "source_location": { 463 "start": { "line": 8, "column": 3 }, 464 "end": { "line": 8, "column": 3 } 465 } 466 }, 467 "source_location": { 468 "start": { "line": 8, "column": 3 }, 469 "end": { "line": 8, "column": 3 } 470 } 471 }, 472 { 473 "function": { 474 "function": "ADDITION", 475 "function_name": { 476 "text": "+", 477 "source_location": { 478 "start": { "line": 8, "column": 5 }, 479 "end": { "line": 8, "column": 6 } 480 } 481 }, 482 "args": [ 483 { 484 "constant": { "value": "0" }, 485 "source_location": { 486 "start": { "line": 8, "column": 5 }, 487 "end": { "line": 8, "column": 5 } 488 } 489 }, 490 { 491 "constant": { "value": "1" }, 492 "source_location": { 493 "start": { "line": 8, "column": 6 }, 494 "end": { "line": 8, "column": 7 } 495 } 496 } 497 ] 498 }, 499 "source_location": { 500 "start": { "line": 8, "column": 4 }, 501 "end": { "line": 8, "column": 8 } 502 } 503 } 504 ] 505 } 506 }, 507 "size": { 508 "function": { 509 "function": "SUBTRACTION", 510 "function_name": { 511 "text": "-", 512 "source_location": { 513 "start": { "line": 8, "column": 12 }, 514 "end": { "line": 8, "column": 13 } 515 } 516 }, 517 "args": [ 518 { 519 "constant": { 520 "value": "0", 521 "source_location": { 522 "start": { "line": 8, "column": 11 }, 523 "end": { "line": 8, "column": 12 } 524 } 525 }, 526 "source_location": { 527 "start": { "line": 8, "column": 11 }, 528 "end": { "line": 8, "column": 12 } 529 } 530 }, 531 { 532 "function": { 533 "function": "SUBTRACTION", 534 "function_name": { 535 "text": "-", 536 "source_location": { 537 "start": { "line": 8, "column": 14 }, 538 "end": { "line": 8, "column": 15 } 539 } 540 }, 541 "args": [ 542 { 543 "constant": { "value": "0" }, 544 "source_location": { 545 "start": { "line": 8, "column": 14 }, 546 "end": { "line": 8, "column": 14 } 547 } 548 }, 549 { 550 "constant": { "value": "10" }, 551 "source_location": { 552 "start": { "line": 8, "column": 15 }, 553 "end": { "line": 8, "column": 17 } 554 } 555 } 556 ] 557 }, 558 "source_location": { 559 "start": { "line": 8, "column": 13 }, 560 "end": { "line": 8, "column": 18 } 561 } 562 } 563 ] 564 } 565 } 566 } 567 }, 568 { 569 "name": { "name": { "text": "unary_plus_minus_2" } }, 570 "location": { 571 "start": { 572 "function": { 573 "function": "ADDITION", 574 "args": [ 575 { "constant": { "value": "1" } }, 576 { 577 "function": { 578 "function": "ADDITION", 579 "args": [ 580 { "constant": { "value": "0" } }, 581 { "constant": { "value": "2" } } 582 ] 583 } 584 } 585 ] 586 } 587 }, 588 "size": { 589 "function": { 590 "function": "SUBTRACTION", 591 "args": [ 592 { 593 "function": { 594 "function": "SUBTRACTION", 595 "args": [ 596 { "constant": { "value": "3" } }, 597 { 598 "function": { 599 "function": "SUBTRACTION", 600 "args": [ 601 { "constant": { "value": "0" } }, 602 { "constant": { "value": "4" } } 603 ] 604 } 605 } 606 ] 607 } 608 }, 609 { "constant": { "value": "5" } } 610 ] 611 } 612 } 613 } 614 } 615 ] 616 } 617 } 618 ] 619} 620 621=== 622auto array size 623--- 624struct TenElementArray: 625 0 [+10] Byte[] bytes 626--- 627{ 628 "type": [ 629 { 630 "structure": { 631 "field": [ 632 { 633 "type": { 634 "array_type": { 635 "base_type": { 636 "atomic_type": { 637 "reference": { "source_name": [ { "text": "Byte" } ] } 638 } 639 }, 640 "automatic": { 641 "source_location": { 642 "start": { "line": 3, "column": 16 }, 643 "end": { "line": 3, "column": 18 } 644 } 645 } 646 } 647 }, 648 "name": { "name": { "text": "bytes" } } 649 } 650 ] 651 } 652 } 653 ] 654} 655 656=== 657start [+size] ranges 658--- 659struct Foo: 660 0 [ + 1 ] UInt zero_plus_one 661 s [+2] UInt s_plus_two 662 s [+t] Byte[t] s_plus_t 663--- 664{ 665 "type": [ 666 { 667 "structure": { 668 "field": [ 669 { 670 "name": { "name": { "text": "zero_plus_one" } }, 671 "location": { 672 "start": { 673 "constant": { "value": "0" }, 674 "source_location": { 675 "start": { "line": 3, "column": 3 }, 676 "end": { "line": 3, "column": 4 } 677 } 678 }, 679 "size": { 680 "constant": { "value": "1" }, 681 "source_location": { 682 "start": { "line": 3, "column": 9 }, 683 "end": { "line": 3, "column": 10 } 684 } 685 } 686 } 687 }, 688 { 689 "name": { "name": { "text": "s_plus_two" } }, 690 "location": { 691 "start": { 692 "field_reference": { 693 "path": [ { "source_name": [ { "text": "s" } ] } ] 694 } 695 }, 696 "size": { "constant": { "value": "2" } } 697 } 698 }, 699 { 700 "name": { "name": { "text": "s_plus_t" } }, 701 "location": { 702 "start": { 703 "field_reference": { 704 "path": [ { "source_name": [ { "text": "s" } ] } ] 705 } 706 }, 707 "size": { 708 "field_reference": { 709 "path": [ { "source_name": [ { "text": "t" } ] } ] 710 } 711 } 712 } 713 } 714 ] 715 } 716 } 717 ] 718} 719 720=== 721Using Enum.VALUEs in expressions 722--- 723struct Foo: 724 0 [+0+Number.FOUR] UInt length_four 725 Number.FOUR [+8] UInt start_four 726 8 [+3*Number.FOUR] UInt end_four 727 12 [+16] Byte[Number.FOUR] array_size_four 728 729enum Number: 730 FOUR = 4 731 EIGHT = FOUR + Number.FOUR 732 SIXTEEN = Number.FOUR * FOUR 733 INVALID = Number.NaN.FOUR 734--- 735{ 736 "type": [ 737 { 738 "structure": { 739 "field": [ 740 { 741 "name": { "name": { "text": "length_four" } }, 742 "location": { 743 "size": { 744 "function": { 745 "function": "ADDITION", 746 "args": [ 747 { "constant": { "value": "0" } }, 748 { 749 "constant_reference": { 750 "source_name": [ 751 { "text": "Number" }, 752 { "text": "FOUR" } 753 ] 754 } 755 } 756 ] 757 } 758 } 759 } 760 }, 761 { 762 "name": { "name": { "text": "start_four" } }, 763 "location": { 764 "start": { 765 "constant_reference": { 766 "source_name": [ 767 { "text": "Number" }, 768 { "text": "FOUR" } 769 ] 770 } 771 } 772 } 773 }, 774 { 775 "name": { "name": { "text": "end_four" } }, 776 "location": { 777 "size": { 778 "function": { 779 "function": "MULTIPLICATION", 780 "args": [ 781 { "constant": { "value": "3" } }, 782 { 783 "constant_reference": { 784 "source_name": [ 785 { "text": "Number" }, 786 { "text": "FOUR" } 787 ] 788 } 789 } 790 ] 791 } 792 } 793 } 794 }, 795 { 796 "type": { 797 "array_type": { 798 "element_count": { 799 "constant_reference": { 800 "source_name": [ 801 { "text": "Number" }, 802 { "text": "FOUR" } 803 ] 804 } 805 } 806 } 807 }, 808 "name": { "name": { "text": "array_size_four" } } 809 } 810 ] 811 } 812 }, 813 { 814 "enumeration": { 815 "value": [ 816 { 817 "name": { "name": { "text": "FOUR" } }, 818 "value": { "constant": { "value": "4" } } 819 }, 820 { 821 "name": { "name": { "text": "EIGHT" } }, 822 "value": { 823 "function": { 824 "function": "ADDITION", 825 "args": [ 826 { 827 "constant_reference": { 828 "source_name": [ { "text": "FOUR" } ] 829 } 830 }, 831 { 832 "constant_reference": { 833 "source_name": [ 834 { "text": "Number" }, 835 { "text": "FOUR" } 836 ] 837 } 838 } 839 ] 840 } 841 } 842 }, 843 { 844 "name": { "name": { "text": "SIXTEEN" } }, 845 "value": { 846 "function": { 847 "function": "MULTIPLICATION", 848 "args": [ 849 { 850 "constant_reference": { 851 "source_name": [ 852 { "text": "Number" }, 853 { "text": "FOUR" } 854 ] 855 } 856 }, 857 { 858 "constant_reference": { 859 "source_name": [ { "text": "FOUR" } ] 860 } 861 } 862 ] 863 } 864 } 865 }, 866 { 867 "name": { "name": { "text": "INVALID" } }, 868 "value": { 869 "constant_reference": { 870 "source_name": [ 871 { "text": "Number" }, 872 { "text": "NaN" }, 873 { "text": "FOUR" } 874 ] 875 } 876 } 877 } 878 ] 879 } 880 } 881 ] 882} 883 884=== 885Using Type.constants in expressions 886--- 887struct Foo: 888 0 [+Bar.four] UInt length_four 889--- 890{ 891 "type": [ 892 { 893 "structure": { 894 "field": [ 895 { 896 "name": { "name": { "text": "length_four" } }, 897 "location": { 898 "size": { 899 "constant_reference": { 900 "source_name": [ { "text": "Bar" }, { "text": "four" } ] 901 } 902 } 903 } 904 } 905 ] 906 } 907 } 908 ] 909} 910 911=== 912using Type.Subtype 913--- 914struct Foo: 915 0 [+0] Bar.Baz bar_baz 916--- 917{ 918 "type": [ 919 { 920 "structure": { 921 "field": [ 922 { 923 "type": { 924 "atomic_type": { 925 "reference": { 926 "source_name": [ { "text": "Bar" }, { "text": "Baz" } ] 927 } 928 } 929 }, 930 "name": { "name": { "text": "bar_baz" } } 931 } 932 ] 933 } 934 } 935 ] 936} 937 938=== 939module.Type 940--- 941struct Foo: 942 0 [+0] bar.Baz bar_baz 943--- 944{ 945 "type": [ 946 { 947 "structure": { 948 "field": [ 949 { 950 "type": { 951 "atomic_type": { 952 "reference": { 953 "source_name": [ { "text": "bar" }, { "text": "Baz" } ] 954 } 955 } 956 }, 957 "name": { "name": { "text": "bar_baz" } } 958 } 959 ] 960 } 961 } 962 ] 963} 964 965=== 966module.Type.ENUM_VALUE 967--- 968struct Foo: 969 bar.Baz.QUX [+0] UInt i 970--- 971{ 972 "type": [ 973 { 974 "structure": { 975 "field": [ 976 { 977 "name": { "name": { "text": "i" } }, 978 "location": { 979 "start": { 980 "constant_reference": { 981 "source_name": [ 982 { "text": "bar" }, 983 { "text": "Baz" }, 984 { "text": "QUX" } 985 ] 986 } 987 } 988 } 989 } 990 ] 991 } 992 } 993 ] 994} 995 996=== 997field attributes 998--- 999struct Foo: 1000 0 [+1] UInt field [fixed_size: true] 1001 [size: 1] 1002 1 [+2] UInt field2 1003--- 1004{ 1005 "type": [ 1006 { 1007 "structure": { 1008 "field": [ 1009 { 1010 "name": { 1011 "name": { 1012 "text": "field" 1013 } 1014 }, 1015 "attribute": [ 1016 { 1017 "name": { 1018 "text": "fixed_size" 1019 }, 1020 "value": { 1021 "expression": { 1022 "boolean_constant": { 1023 "value": true 1024 } 1025 } 1026 } 1027 }, 1028 { 1029 "name": { 1030 "text": "size" 1031 }, 1032 "value": { 1033 "expression": { 1034 "constant": { 1035 "value": "1" 1036 } 1037 } 1038 } 1039 } 1040 ] 1041 }, 1042 { 1043 "name": { 1044 "name": { 1045 "text": "field2" 1046 } 1047 } 1048 } 1049 ] 1050 }, 1051 "name": { 1052 "name": { 1053 "text": "Foo" 1054 } 1055 } 1056 } 1057 ] 1058} 1059 1060=== 1061enum attribute 1062--- 1063enum Foo: 1064 [fixed_size: false] 1065 NAME = 1 1066--- 1067{ 1068 "type": [ 1069 { 1070 "enumeration": { 1071 "value": [ { "name": { "name": { "text": "NAME" } } } ] 1072 }, 1073 "name": { "name": { "text": "Foo" } }, 1074 "attribute": [ 1075 { 1076 "name": { "text": "fixed_size" }, 1077 "value": { 1078 "expression": { "boolean_constant": { "value": false } } 1079 } 1080 } 1081 ] 1082 } 1083 ] 1084} 1085 1086=== 1087string attribute 1088--- 1089[abc: "abc"] 1090[bs: "abc\\"] 1091[bsbs: "abc\\\\"] 1092[nl: "abc\nd"] 1093[q: "abc\"d"] 1094[qq: "abc\"\""] 1095--- 1096{ 1097 "attribute": [ 1098 { 1099 "name": { "text": "abc" }, 1100 "value": { "string_constant": { "text": "abc" } } 1101 }, 1102 { 1103 "name": { "text": "bs" }, 1104 "value": { "string_constant": { "text": "abc\\" } } 1105 }, 1106 { 1107 "name": { "text": "bsbs" }, 1108 "value": { "string_constant": { "text": "abc\\\\" } } 1109 }, 1110 { 1111 "name": { "text": "nl" }, 1112 "value": { "string_constant": { "text": "abc\nd" } } 1113 }, 1114 { 1115 "name": { "text": "q" }, 1116 "value": { "string_constant": { "text": "abc\"d" } } 1117 }, 1118 { 1119 "name": { "text": "qq" }, 1120 "value": { "string_constant": { "text": "abc\"\"" } } 1121 } 1122 ] 1123} 1124 1125=== 1126back-end-specific attribute 1127--- 1128[(cpp) namespace: "a::b::c"] 1129--- 1130{ 1131 "attribute": [ 1132 { 1133 "name": { "text": "namespace" }, 1134 "value": { "string_constant": { "text": "a::b::c" } }, 1135 "back_end": { "text": "cpp" } 1136 } 1137 ] 1138} 1139 1140=== 1141documentation 1142--- 1143-- module doc 1144-- 1145-- module doc 2 1146struct Foo: 1147 -- foo doc 1148 -- foo doc 2 1149 0 [+1] UInt bar -- bar inline doc 1150 -- bar continued doc 1151 -- bar continued doc 2 1152enum Baz: 1153 -- baz doc 1154 -- baz doc 2 1155 QUX = 1 -- qux inline doc 1156 -- qux continued doc 1157 -- qux continued doc 2 1158--- 1159{ 1160 "type": [ 1161 { 1162 "structure": { 1163 "field": [ 1164 { 1165 "name": { 1166 "name": { 1167 "text": "bar" 1168 } 1169 }, 1170 "documentation": [ 1171 { 1172 "text": "bar inline doc" 1173 }, 1174 { 1175 "text": "bar continued doc" 1176 }, 1177 { 1178 "text": "bar continued doc 2" 1179 } 1180 ] 1181 } 1182 ] 1183 }, 1184 "name": { 1185 "name": { 1186 "text": "Foo" 1187 } 1188 }, 1189 "documentation": [ 1190 { 1191 "text": "foo doc" 1192 }, 1193 { 1194 "text": "foo doc 2" 1195 } 1196 ] 1197 }, 1198 { 1199 "enumeration": { 1200 "value": [ 1201 { 1202 "name": { 1203 "name": { 1204 "text": "QUX" 1205 } 1206 }, 1207 "documentation": [ 1208 { 1209 "text": "qux inline doc" 1210 }, 1211 { 1212 "text": "qux continued doc" 1213 }, 1214 { 1215 "text": "qux continued doc 2" 1216 } 1217 ] 1218 } 1219 ] 1220 }, 1221 "name": { 1222 "name": { 1223 "text": "Baz" 1224 } 1225 }, 1226 "documentation": [ 1227 { 1228 "text": "baz doc" 1229 }, 1230 { 1231 "text": "baz doc 2" 1232 } 1233 ] 1234 } 1235 ], 1236 "documentation": [ 1237 { 1238 "text": "module doc" 1239 }, 1240 { 1241 "text": "" 1242 }, 1243 { 1244 "text": "module doc 2" 1245 } 1246 ] 1247} 1248 1249=== 1250inline enum 1251--- 1252struct Foo: 1253 0 [+1] enum baz_qux_gibble (bqg): 1254 [q: 5] 1255 BAR = 1 1256 FOO = 2 1257bits Bar: 1258 0 [+1] enum baz_qux_gibble (bqg): 1259 [q: 5] 1260 BAR = 1 1261 FOO = 2 1262--- 1263{ 1264 "type": [ 1265 { 1266 "structure": { 1267 "field": [ 1268 { 1269 "type": { 1270 "atomic_type": { 1271 "reference": { 1272 "source_name": [ { "text": "BazQuxGibble" } ], 1273 "is_local_name": true 1274 } 1275 } 1276 }, 1277 "name": { "name": { "text": "baz_qux_gibble" } }, 1278 "abbreviation": { "text": "bqg" }, 1279 "attribute": [ 1280 { 1281 "name": { "text": "q" }, 1282 "value": { "expression": { "constant": { "value": "5" } } } 1283 } 1284 ] 1285 } 1286 ] 1287 }, 1288 "name": { "name": { "text": "Foo" } }, 1289 "subtype": [ 1290 { 1291 "enumeration": { 1292 "value": [ 1293 { 1294 "name": { "name": { "text": "BAR" } }, 1295 "value": { "constant": { "value": "1" } } 1296 }, 1297 { 1298 "name": { "name": { "text": "FOO" } }, 1299 "value": { "constant": { "value": "2" } } 1300 } 1301 ] 1302 }, 1303 "name": { "name": { "text": "BazQuxGibble" } } 1304 } 1305 ] 1306 }, 1307 { 1308 "structure": { 1309 "field": [ 1310 { 1311 "type": { 1312 "atomic_type": { 1313 "reference": { 1314 "source_name": [ { "text": "BazQuxGibble" } ], 1315 "is_local_name": true 1316 } 1317 } 1318 }, 1319 "name": { "name": { "text": "baz_qux_gibble" } }, 1320 "abbreviation": { "text": "bqg" }, 1321 "attribute": [ 1322 { 1323 "name": { "text": "q" }, 1324 "value": { "expression": { "constant": { "value": "5" } } } 1325 } 1326 ] 1327 } 1328 ] 1329 }, 1330 "name": { "name": { "text": "Bar" } }, 1331 "subtype": [ 1332 { 1333 "enumeration": { 1334 "value": [ 1335 { 1336 "name": { "name": { "text": "BAR" } }, 1337 "value": { "constant": { "value": "1" } } 1338 }, 1339 { 1340 "name": { "name": { "text": "FOO" } }, 1341 "value": { "constant": { "value": "2" } } 1342 } 1343 ] 1344 }, 1345 "name": { "name": { "text": "BazQuxGibble" } } 1346 } 1347 ] 1348 } 1349 ] 1350} 1351 1352=== 1353inline struct 1354--- 1355struct Foo: 1356 0 [+1] struct baz_qux_gibble (bqg): 1357 [q: 5] 1358 0 [+1] UInt bar 1359 1 [+1] UInt foo 1360--- 1361{ 1362 "type": [ 1363 { 1364 "structure": { 1365 "field": [ 1366 { 1367 "type": { 1368 "atomic_type": { 1369 "reference": { 1370 "source_name": [ { "text": "BazQuxGibble" } ], 1371 "is_local_name": true 1372 } 1373 } 1374 }, 1375 "name": { "name": { "text": "baz_qux_gibble" } }, 1376 "abbreviation": { "text": "bqg" }, 1377 "attribute": [ 1378 { 1379 "name": { "text": "q" }, 1380 "value": { "expression": { "constant": { "value": "5" } } } 1381 } 1382 ] 1383 } 1384 ] 1385 }, 1386 "name": { "name": { "text": "Foo" } }, 1387 "subtype": [ 1388 { 1389 "structure": { 1390 "field": [ 1391 { 1392 "type": { 1393 "atomic_type": { 1394 "reference": { "source_name": [ { "text": "UInt" } ] } 1395 } 1396 }, 1397 "name": { "name": { "text": "bar" } } 1398 }, 1399 { 1400 "type": { 1401 "atomic_type": { 1402 "reference": { "source_name": [ { "text": "UInt" } ] } 1403 } 1404 }, 1405 "name": { "name": { "text": "foo" } } 1406 } 1407 ] 1408 }, 1409 "name": { "name": { "text": "BazQuxGibble" } } 1410 } 1411 ] 1412 } 1413 ] 1414} 1415 1416=== 1417inline bits 1418--- 1419struct Foo: 1420 0 [+1] bits baz_qux_gibble (bqg): 1421 [q: 5] 1422 0 [+1] UInt bar 1423 1 [+1] UInt foo 1424bits Bar: 1425 0 [+8] bits baz_qux_gibble (bqg): 1426 [q: 5] 1427 0 [+1] UInt bar 1428 1 [+1] UInt foo 1429--- 1430{ 1431 "type": [ 1432 { 1433 "structure": { 1434 "field": [ 1435 { 1436 "type": { 1437 "atomic_type": { 1438 "reference": { 1439 "source_name": [ 1440 { 1441 "text": "BazQuxGibble" 1442 } 1443 ] 1444 } 1445 } 1446 }, 1447 "name": { 1448 "name": { 1449 "text": "baz_qux_gibble" 1450 } 1451 }, 1452 "abbreviation": { 1453 "text": "bqg" 1454 }, 1455 "attribute": [ 1456 { 1457 "name": { 1458 "text": "q" 1459 }, 1460 "value": { 1461 "expression": { 1462 "constant": { 1463 "value": "5" 1464 } 1465 } 1466 } 1467 } 1468 ] 1469 } 1470 ] 1471 }, 1472 "name": { 1473 "name": { 1474 "text": "Foo" 1475 } 1476 }, 1477 "subtype": [ 1478 { 1479 "structure": { 1480 "field": [ 1481 { 1482 "type": { 1483 "atomic_type": { 1484 "reference": { 1485 "source_name": [ 1486 { 1487 "text": "UInt" 1488 } 1489 ] 1490 } 1491 } 1492 }, 1493 "name": { 1494 "name": { 1495 "text": "bar" 1496 } 1497 } 1498 }, 1499 { 1500 "type": { 1501 "atomic_type": { 1502 "reference": { 1503 "source_name": [ 1504 { 1505 "text": "UInt" 1506 } 1507 ] 1508 } 1509 } 1510 }, 1511 "name": { 1512 "name": { 1513 "text": "foo" 1514 } 1515 } 1516 } 1517 ] 1518 }, 1519 "name": { 1520 "name": { 1521 "text": "BazQuxGibble" 1522 } 1523 } 1524 } 1525 ] 1526 }, 1527 { 1528 "structure": { 1529 "field": [ 1530 { 1531 "type": { 1532 "atomic_type": { 1533 "reference": { 1534 "source_name": [ 1535 { 1536 "text": "BazQuxGibble" 1537 } 1538 ] 1539 } 1540 } 1541 }, 1542 "name": { 1543 "name": { 1544 "text": "baz_qux_gibble" 1545 } 1546 }, 1547 "abbreviation": { 1548 "text": "bqg" 1549 }, 1550 "attribute": [ 1551 { 1552 "name": { 1553 "text": "q" 1554 }, 1555 "value": { 1556 "expression": { 1557 "constant": { 1558 "value": "5" 1559 } 1560 } 1561 } 1562 } 1563 ] 1564 } 1565 ] 1566 }, 1567 "name": { 1568 "name": { 1569 "text": "Bar" 1570 } 1571 }, 1572 "subtype": [ 1573 { 1574 "structure": { 1575 "field": [ 1576 { 1577 "type": { 1578 "atomic_type": { 1579 "reference": { 1580 "source_name": [ 1581 { 1582 "text": "UInt" 1583 } 1584 ] 1585 } 1586 } 1587 }, 1588 "name": { 1589 "name": { 1590 "text": "bar" 1591 } 1592 } 1593 }, 1594 { 1595 "type": { 1596 "atomic_type": { 1597 "reference": { 1598 "source_name": [ 1599 { 1600 "text": "UInt" 1601 } 1602 ] 1603 } 1604 } 1605 }, 1606 "name": { 1607 "name": { 1608 "text": "foo" 1609 } 1610 } 1611 } 1612 ] 1613 }, 1614 "name": { 1615 "name": { 1616 "text": "BazQuxGibble" 1617 } 1618 } 1619 } 1620 ] 1621 } 1622 ] 1623} 1624 1625=== 1626subfield 1627--- 1628struct Foo: 1629 foo.bar [+1] UInt x 1630--- 1631{ 1632 "type": [ 1633 { 1634 "structure": { 1635 "field": [ 1636 { 1637 "name": { 1638 "name": { 1639 "text": "x" 1640 } 1641 }, 1642 "location": { 1643 "start": { 1644 "field_reference": { 1645 "path": [ 1646 { 1647 "source_name": [ 1648 { 1649 "text": "foo" 1650 } 1651 ] 1652 }, 1653 { 1654 "source_name": [ 1655 { 1656 "text": "bar" 1657 } 1658 ] 1659 } 1660 ] 1661 } 1662 } 1663 } 1664 } 1665 ] 1666 }, 1667 "name": { 1668 "name": { 1669 "text": "Foo" 1670 } 1671 } 1672 } 1673 ] 1674} 1675 1676=== 1677anonymous bits 1678--- 1679struct Foo: 1680 0 [+1] bits: 1681 31 [+1] enum high_bit: 1682 OFF = 0 1683 ON = 1 1684 0 [+1] Flag low_bit 1685 if false: 1686 16 [+1] UInt mid_high 1687 15 [+1] UInt mid_low 1688--- 1689{ 1690 "type": [ 1691 { 1692 "structure": { 1693 "field": [ 1694 { 1695 "name": { 1696 "is_anonymous": true 1697 }, 1698 "location": { 1699 "start": { 1700 "constant": { 1701 "value": "0" 1702 } 1703 }, 1704 "size": { 1705 "constant": { 1706 "value": "1" 1707 } 1708 } 1709 } 1710 } 1711 ] 1712 }, 1713 "name": { 1714 "name": { 1715 "text": "Foo" 1716 } 1717 }, 1718 "subtype": [ 1719 { 1720 "structure": { 1721 "field": [ 1722 { 1723 "name": { 1724 "name": { 1725 "text": "high_bit" 1726 } 1727 } 1728 }, 1729 { 1730 "name": { 1731 "name": { 1732 "text": "low_bit" 1733 } 1734 } 1735 }, 1736 { 1737 "name": { 1738 "name": { 1739 "text": "mid_high" 1740 } 1741 }, 1742 "existence_condition": { 1743 "boolean_constant": { 1744 "value": false 1745 } 1746 } 1747 }, 1748 { 1749 "name": { 1750 "name": { 1751 "text": "mid_low" 1752 } 1753 }, 1754 "existence_condition": { 1755 "boolean_constant": { 1756 "value": false 1757 } 1758 } 1759 } 1760 ] 1761 }, 1762 "name": { "is_anonymous": true } 1763 }, 1764 { 1765 "enumeration": { 1766 "value": [ 1767 { 1768 "name": { "name": { "text": "OFF" } }, 1769 "value": { "constant": { "value": "0" } } 1770 }, 1771 { 1772 "name": { "name": { "text": "ON" } }, 1773 "value": { "constant": { "value": "1" } } 1774 } 1775 ] 1776 }, 1777 "name": { "name": { "text": "HighBit" } } 1778 } 1779 ] 1780 } 1781 ] 1782} 1783 1784=== 1785explicit type size 1786--- 1787struct Foo: 1788 0 [+1] Bar:8 bar 1789--- 1790{ 1791 "type": [ 1792 { 1793 "structure": { 1794 "field": [ 1795 { "type": { "size_in_bits": { "constant": { "value": "8" } } } } 1796 ] 1797 }, 1798 "name": { "name": { "text": "Foo" } } 1799 } 1800 ] 1801} 1802 1803=== 1804import 1805--- 1806import "xyz.emb" as yqf 1807--- 1808{ 1809 "foreign_import": [ 1810 { "file_name": { "text": "" }, "local_name": { "text": "" } }, 1811 { "file_name": { "text": "xyz.emb" }, "local_name": { "text": "yqf" } } 1812 ] 1813} 1814 1815=== 1816empty file 1817--- 1818--- 1819{ 1820 "foreign_import": [ 1821 { 1822 "file_name": { 1823 "text": "", 1824 "source_location": { 1825 "start": { "line": 1, "column": 1 }, 1826 "end": { "line": 1, "column": 1 } 1827 } 1828 }, 1829 "local_name": { 1830 "text": "", 1831 "source_location": { 1832 "start": { "line": 1, "column": 1 }, 1833 "end": { "line": 1, "column": 1 } 1834 } 1835 }, 1836 "source_location": { 1837 "start": { "line": 1, "column": 1 }, 1838 "end": { "line": 1, "column": 1 } 1839 } 1840 } 1841 ], 1842 "source_location": { 1843 "start": { "line": 1, "column": 1 }, 1844 "end": { "line": 1, "column": 1 } 1845 } 1846} 1847 1848=== 1849existence_condition on unconditional field 1850--- 1851struct Foo: 1852 0 [+1] UInt bar 1853--- 1854{ 1855 "type": [ 1856 { 1857 "structure": { 1858 "field": [ 1859 { 1860 "name": { "name": { "text": "bar" } }, 1861 "existence_condition": { "boolean_constant": { "value": true } } 1862 } 1863 ] 1864 } 1865 } 1866 ] 1867} 1868 1869=== 1870conditional struct fields 1871--- 1872struct Foo: 1873 if true == false: 1874 0 [+1] UInt bar 1875 1 [+1] bits: 1876 0 [+1] UInt xx 1877 1 [+1] UInt yy 1878 2 [+1] enum baz: 1879 XX = 1 1880 YY = 2 1881--- 1882{ 1883 "type": [ 1884 { 1885 "structure": { 1886 "field": [ 1887 { 1888 "name": { "name": { "text": "bar" } }, 1889 "existence_condition": { 1890 "function": { 1891 "function": "EQUALITY", 1892 "args": [ 1893 { "boolean_constant": { "value": true } }, 1894 { "boolean_constant": { "value": false } } 1895 ] 1896 } 1897 } 1898 }, 1899 { 1900 "existence_condition": { 1901 "function": { 1902 "function": "EQUALITY", 1903 "args": [ 1904 { "boolean_constant": { "value": true } }, 1905 { "boolean_constant": { "value": false } } 1906 ] 1907 } 1908 } 1909 }, 1910 { 1911 "name": { "name": { "text": "baz" } }, 1912 "existence_condition": { 1913 "function": { 1914 "function": "EQUALITY", 1915 "args": [ 1916 { "boolean_constant": { "value": true } }, 1917 { "boolean_constant": { "value": false } } 1918 ] 1919 } 1920 } 1921 } 1922 ] 1923 }, 1924 "subtype": [ 1925 { 1926 "structure": { 1927 "field": [ 1928 { 1929 "name": { "name": { "text": "xx" } }, 1930 "existence_condition": { "boolean_constant": { "value": true } } 1931 } 1932 ] 1933 } 1934 } 1935 ] 1936 } 1937 ] 1938} 1939 1940=== 1941negative condition 1942--- 1943struct Foo: 1944 if true != false: 1945 0 [+1] UInt bar 1946--- 1947{ 1948 "type": [ 1949 { 1950 "structure": { 1951 "field": [ 1952 { 1953 "name": { "name": { "text": "bar" } }, 1954 "existence_condition": { 1955 "function": { 1956 "function": "INEQUALITY", 1957 "args": [ 1958 { "boolean_constant": { "value": true } }, 1959 { "boolean_constant": { "value": false } } 1960 ] 1961 } 1962 } 1963 } 1964 ] 1965 } 1966 } 1967 ] 1968} 1969 1970=== 1971conditional bits fields 1972--- 1973bits Foo: 1974 if true == false: 1975 0 [+1] UInt bar 1976 1 [+1] enum baz: 1977 XX = 1 1978 YY = 2 1979--- 1980{ 1981 "type": [ 1982 { 1983 "structure": { 1984 "field": [ 1985 { 1986 "name": { "name": { "text": "bar" } }, 1987 "existence_condition": { 1988 "function": { 1989 "function": "EQUALITY", 1990 "args": [ 1991 { "boolean_constant": { "value": true } }, 1992 { "boolean_constant": { "value": false } } 1993 ] 1994 } 1995 } 1996 }, 1997 { 1998 "name": { "name": { "text": "baz" } }, 1999 "existence_condition": { 2000 "function": { 2001 "function": "EQUALITY", 2002 "args": [ 2003 { "boolean_constant": { "value": true } }, 2004 { "boolean_constant": { "value": false } } 2005 ] 2006 } 2007 } 2008 } 2009 ] 2010 } 2011 } 2012 ] 2013} 2014 2015=== 2016conditional with logical and 2017--- 2018struct Foo: 2019 if true && false: 2020 0 [+1] UInt bar 2021--- 2022{ 2023 "type": [ 2024 { 2025 "structure": { 2026 "field": [ 2027 { 2028 "name": { 2029 "name": { 2030 "text": "bar" 2031 } 2032 }, 2033 "existence_condition": { 2034 "function": { 2035 "function": "AND", 2036 "args": [ 2037 { 2038 "boolean_constant": { 2039 "value": true 2040 } 2041 }, 2042 { 2043 "boolean_constant": { 2044 "value": false 2045 } 2046 } 2047 ] 2048 } 2049 } 2050 } 2051 ] 2052 } 2053 } 2054 ] 2055} 2056 2057=== 2058conditional with logical or 2059--- 2060struct Foo: 2061 if true || false: 2062 0 [+1] UInt bar 2063--- 2064{ 2065 "type": [ 2066 { 2067 "structure": { 2068 "field": [ 2069 { 2070 "name": { 2071 "name": { 2072 "text": "bar" 2073 } 2074 }, 2075 "existence_condition": { 2076 "function": { 2077 "function": "OR", 2078 "args": [ 2079 { 2080 "boolean_constant": { 2081 "value": true 2082 } 2083 }, 2084 { 2085 "boolean_constant": { 2086 "value": false 2087 } 2088 } 2089 ] 2090 } 2091 } 2092 } 2093 ] 2094 } 2095 } 2096 ] 2097} 2098 2099=== 2100conditional with multiple logical ands 2101--- 2102struct Foo: 2103 if true && false && true: 2104 0 [+1] UInt bar 2105--- 2106{ 2107 "type": [ 2108 { 2109 "structure": { 2110 "field": [ 2111 { 2112 "name": { 2113 "name": { 2114 "text": "bar" 2115 } 2116 }, 2117 "existence_condition": { 2118 "function": { 2119 "function": "AND", 2120 "args": [ 2121 { 2122 "function": { 2123 "function": "AND", 2124 "args": [ 2125 { 2126 "boolean_constant": { 2127 "value": true 2128 } 2129 }, 2130 { 2131 "boolean_constant": { 2132 "value": false 2133 } 2134 } 2135 ] 2136 } 2137 }, 2138 { 2139 "boolean_constant": { 2140 "value": true 2141 } 2142 } 2143 ] 2144 } 2145 } 2146 } 2147 ] 2148 } 2149 } 2150 ] 2151} 2152 2153=== 2154conditional with multiple logical ors 2155--- 2156struct Foo: 2157 if true || false || true: 2158 0 [+1] UInt bar 2159--- 2160{ 2161 "type": [ 2162 { 2163 "structure": { 2164 "field": [ 2165 { 2166 "name": { 2167 "name": { 2168 "text": "bar" 2169 } 2170 }, 2171 "existence_condition": { 2172 "function": { 2173 "function": "OR", 2174 "args": [ 2175 { 2176 "function": { 2177 "function": "OR", 2178 "args": [ 2179 { 2180 "boolean_constant": { 2181 "value": true 2182 } 2183 }, 2184 { 2185 "boolean_constant": { 2186 "value": false 2187 } 2188 } 2189 ] 2190 } 2191 }, 2192 { 2193 "boolean_constant": { 2194 "value": true 2195 } 2196 } 2197 ] 2198 } 2199 } 2200 } 2201 ] 2202 } 2203 } 2204 ] 2205} 2206 2207=== 2208conditional with comparisons and logical or 2209--- 2210struct Foo: 2211 if 5 == 6 || 6 == 6: 2212 0 [+1] UInt bar 2213--- 2214{ 2215 "type": [ 2216 { 2217 "structure": { 2218 "field": [ 2219 { 2220 "name": { 2221 "name": { 2222 "text": "bar" 2223 } 2224 }, 2225 "existence_condition": { 2226 "function": { 2227 "function": "OR", 2228 "args": [ 2229 { 2230 "function": { 2231 "function": "EQUALITY", 2232 "args": [ 2233 { 2234 "constant": { 2235 "value": "5" 2236 } 2237 }, 2238 { 2239 "constant": { 2240 "value": "6" 2241 } 2242 } 2243 ] 2244 } 2245 }, 2246 { 2247 "function": { 2248 "function": "EQUALITY", 2249 "args": [ 2250 { 2251 "constant": { 2252 "value": "6" 2253 } 2254 }, 2255 { 2256 "constant": { 2257 "value": "6" 2258 } 2259 } 2260 ] 2261 } 2262 } 2263 ] 2264 } 2265 } 2266 } 2267 ] 2268 } 2269 } 2270 ] 2271} 2272 2273=== 2274conditional with or-of-ands 2275--- 2276struct Foo: 2277 if true || (false && true): 2278 0 [+1] UInt bar 2279--- 2280{ 2281 "type": [ 2282 { 2283 "structure": { 2284 "field": [ 2285 { 2286 "name": { 2287 "name": { 2288 "text": "bar" 2289 } 2290 }, 2291 "existence_condition": { 2292 "function": { 2293 "function": "OR", 2294 "args": [ 2295 { 2296 "boolean_constant": { 2297 "value": true 2298 } 2299 }, 2300 { 2301 "function": { 2302 "function": "AND", 2303 "args": [ 2304 { 2305 "boolean_constant": { 2306 "value": false 2307 } 2308 }, 2309 { 2310 "boolean_constant": { 2311 "value": true 2312 } 2313 } 2314 ] 2315 } 2316 } 2317 ] 2318 } 2319 } 2320 } 2321 ] 2322 } 2323 } 2324 ] 2325} 2326 2327=== 2328less-than comparison 2329--- 2330struct Foo: 2331 if 1 < 2: 2332 0 [+1] UInt bar 2333--- 2334{ 2335 "type": [ 2336 { 2337 "structure": { 2338 "field": [ 2339 { 2340 "name": { 2341 "name": { 2342 "text": "bar" 2343 } 2344 }, 2345 "existence_condition": { 2346 "function": { 2347 "function": "LESS", 2348 "args": [ 2349 { 2350 "constant": { 2351 "value": "1" 2352 } 2353 }, 2354 { 2355 "constant": { 2356 "value": "2" 2357 } 2358 } 2359 ] 2360 } 2361 } 2362 } 2363 ] 2364 } 2365 } 2366 ] 2367} 2368 2369=== 2370less-than-or-equal comparison 2371--- 2372struct Foo: 2373 if 1 <= 2: 2374 0 [+1] UInt bar 2375--- 2376{ 2377 "type": [ 2378 { 2379 "structure": { 2380 "field": [ 2381 { 2382 "name": { 2383 "name": { 2384 "text": "bar" 2385 } 2386 }, 2387 "existence_condition": { 2388 "function": { 2389 "function": "LESS_OR_EQUAL", 2390 "args": [ 2391 { 2392 "constant": { 2393 "value": "1" 2394 } 2395 }, 2396 { 2397 "constant": { 2398 "value": "2" 2399 } 2400 } 2401 ] 2402 } 2403 } 2404 } 2405 ] 2406 } 2407 } 2408 ] 2409} 2410 2411=== 2412greater-than comparison 2413--- 2414struct Foo: 2415 if 1 > 2: 2416 0 [+1] UInt bar 2417--- 2418{ 2419 "type": [ 2420 { 2421 "structure": { 2422 "field": [ 2423 { 2424 "name": { 2425 "name": { 2426 "text": "bar" 2427 } 2428 }, 2429 "existence_condition": { 2430 "function": { 2431 "function": "GREATER", 2432 "args": [ 2433 { 2434 "constant": { 2435 "value": "1" 2436 } 2437 }, 2438 { 2439 "constant": { 2440 "value": "2" 2441 } 2442 } 2443 ] 2444 } 2445 } 2446 } 2447 ] 2448 } 2449 } 2450 ] 2451} 2452 2453=== 2454greater-than-or-equal comparison 2455--- 2456struct Foo: 2457 if 1 >= 2: 2458 0 [+1] UInt bar 2459--- 2460{ 2461 "type": [ 2462 { 2463 "structure": { 2464 "field": [ 2465 { 2466 "name": { 2467 "name": { 2468 "text": "bar" 2469 } 2470 }, 2471 "existence_condition": { 2472 "function": { 2473 "function": "GREATER_OR_EQUAL", 2474 "args": [ 2475 { 2476 "constant": { 2477 "value": "1" 2478 } 2479 }, 2480 { 2481 "constant": { 2482 "value": "2" 2483 } 2484 } 2485 ] 2486 } 2487 } 2488 } 2489 ] 2490 } 2491 } 2492 ] 2493} 2494 2495=== 2496chained less-than comparison 2497--- 2498struct Foo: 2499 if 1 < 2 < 3: 2500 0 [+1] UInt bar 2501--- 2502{ 2503 "type": [ 2504 { 2505 "structure": { 2506 "field": [ 2507 { 2508 "name": { 2509 "name": { 2510 "text": "bar" 2511 } 2512 }, 2513 "existence_condition": { 2514 "function": { 2515 "function": "AND", 2516 "args": [ 2517 { 2518 "function": { 2519 "function": "LESS", 2520 "args": [ 2521 { 2522 "constant": { 2523 "value": "1" 2524 } 2525 }, 2526 { 2527 "constant": { 2528 "value": "2" 2529 } 2530 } 2531 ] 2532 } 2533 }, 2534 { 2535 "function": { 2536 "function": "LESS", 2537 "args": [ 2538 { 2539 "constant": { 2540 "value": "2" 2541 } 2542 }, 2543 { 2544 "constant": { 2545 "value": "3" 2546 } 2547 } 2548 ] 2549 } 2550 } 2551 ] 2552 } 2553 } 2554 } 2555 ] 2556 } 2557 } 2558 ] 2559} 2560 2561=== 2562chained greater-than comparison 2563--- 2564struct Foo: 2565 if 1 > 2 > 3: 2566 0 [+1] UInt bar 2567--- 2568{ 2569 "type": [ 2570 { 2571 "structure": { 2572 "field": [ 2573 { 2574 "name": { 2575 "name": { 2576 "text": "bar" 2577 } 2578 }, 2579 "existence_condition": { 2580 "function": { 2581 "function": "AND", 2582 "args": [ 2583 { 2584 "function": { 2585 "function": "GREATER", 2586 "args": [ 2587 { 2588 "constant": { 2589 "value": "1" 2590 } 2591 }, 2592 { 2593 "constant": { 2594 "value": "2" 2595 } 2596 } 2597 ] 2598 } 2599 }, 2600 { 2601 "function": { 2602 "function": "GREATER", 2603 "args": [ 2604 { 2605 "constant": { 2606 "value": "2" 2607 } 2608 }, 2609 { 2610 "constant": { 2611 "value": "3" 2612 } 2613 } 2614 ] 2615 } 2616 } 2617 ] 2618 } 2619 } 2620 } 2621 ] 2622 } 2623 } 2624 ] 2625} 2626 2627=== 2628longer chained less-than comparison 2629--- 2630struct Foo: 2631 if 1 < 2 < 3 <= 4: 2632 0 [+1] UInt bar 2633--- 2634{ 2635 "type": [ 2636 { 2637 "structure": { 2638 "field": [ 2639 { 2640 "name": { 2641 "name": { 2642 "text": "bar" 2643 } 2644 }, 2645 "existence_condition": { 2646 "function": { 2647 "function": "AND", 2648 "args": [ 2649 { 2650 "function": { 2651 "function": "AND", 2652 "args": [ 2653 { 2654 "function": { 2655 "function": "LESS", 2656 "args": [ 2657 { 2658 "constant": { 2659 "value": "1" 2660 } 2661 }, 2662 { 2663 "constant": { 2664 "value": "2" 2665 } 2666 } 2667 ] 2668 } 2669 }, 2670 { 2671 "function": { 2672 "function": "LESS", 2673 "args": [ 2674 { 2675 "constant": { 2676 "value": "2" 2677 } 2678 }, 2679 { 2680 "constant": { 2681 "value": "3" 2682 } 2683 } 2684 ] 2685 } 2686 } 2687 ] 2688 } 2689 }, 2690 { 2691 "function": { 2692 "function": "LESS_OR_EQUAL", 2693 "args": [ 2694 { 2695 "constant": { 2696 "value": "3" 2697 } 2698 }, 2699 { 2700 "constant": { 2701 "value": "4" 2702 } 2703 } 2704 ] 2705 } 2706 } 2707 ] 2708 } 2709 } 2710 } 2711 ] 2712 } 2713 } 2714 ] 2715} 2716 2717=== 2718longer chained greater-than comparison 2719--- 2720struct Foo: 2721 if 1 > 2 > 3 >= 4: 2722 0 [+1] UInt bar 2723--- 2724{ 2725 "type": [ 2726 { 2727 "structure": { 2728 "field": [ 2729 { 2730 "name": { 2731 "name": { 2732 "text": "bar" 2733 } 2734 }, 2735 "existence_condition": { 2736 "function": { 2737 "function": "AND", 2738 "args": [ 2739 { 2740 "function": { 2741 "function": "AND", 2742 "args": [ 2743 { 2744 "function": { 2745 "function": "GREATER", 2746 "args": [ 2747 { 2748 "constant": { 2749 "value": "1" 2750 } 2751 }, 2752 { 2753 "constant": { 2754 "value": "2" 2755 } 2756 } 2757 ] 2758 } 2759 }, 2760 { 2761 "function": { 2762 "function": "GREATER", 2763 "args": [ 2764 { 2765 "constant": { 2766 "value": "2" 2767 } 2768 }, 2769 { 2770 "constant": { 2771 "value": "3" 2772 } 2773 } 2774 ] 2775 } 2776 } 2777 ] 2778 } 2779 }, 2780 { 2781 "function": { 2782 "function": "GREATER_OR_EQUAL", 2783 "args": [ 2784 { 2785 "constant": { 2786 "value": "3" 2787 } 2788 }, 2789 { 2790 "constant": { 2791 "value": "4" 2792 } 2793 } 2794 ] 2795 } 2796 } 2797 ] 2798 } 2799 } 2800 } 2801 ] 2802 } 2803 } 2804 ] 2805} 2806 2807=== 2808chained less-than and equal comparison 2809--- 2810struct Foo: 2811 if 1 < 2 == 3: 2812 0 [+1] UInt bar 2813--- 2814{ 2815 "type": [ 2816 { 2817 "structure": { 2818 "field": [ 2819 { 2820 "name": { 2821 "name": { 2822 "text": "bar" 2823 } 2824 }, 2825 "existence_condition": { 2826 "function": { 2827 "function": "AND", 2828 "args": [ 2829 { 2830 "function": { 2831 "function": "LESS", 2832 "args": [ 2833 { 2834 "constant": { 2835 "value": "1" 2836 } 2837 }, 2838 { 2839 "constant": { 2840 "value": "2" 2841 } 2842 } 2843 ] 2844 } 2845 }, 2846 { 2847 "function": { 2848 "function": "EQUALITY", 2849 "args": [ 2850 { 2851 "constant": { 2852 "value": "2" 2853 } 2854 }, 2855 { 2856 "constant": { 2857 "value": "3" 2858 } 2859 } 2860 ] 2861 } 2862 } 2863 ] 2864 } 2865 } 2866 } 2867 ] 2868 } 2869 } 2870 ] 2871} 2872 2873=== 2874chained greater-than and equal comparison 2875--- 2876struct Foo: 2877 if 1 > 2 == 3: 2878 0 [+1] UInt bar 2879--- 2880{ 2881 "type": [ 2882 { 2883 "structure": { 2884 "field": [ 2885 { 2886 "name": { 2887 "name": { 2888 "text": "bar" 2889 } 2890 }, 2891 "existence_condition": { 2892 "function": { 2893 "function": "AND", 2894 "args": [ 2895 { 2896 "function": { 2897 "function": "GREATER", 2898 "args": [ 2899 { 2900 "constant": { 2901 "value": "1" 2902 } 2903 }, 2904 { 2905 "constant": { 2906 "value": "2" 2907 } 2908 } 2909 ] 2910 } 2911 }, 2912 { 2913 "function": { 2914 "function": "EQUALITY", 2915 "args": [ 2916 { 2917 "constant": { 2918 "value": "2" 2919 } 2920 }, 2921 { 2922 "constant": { 2923 "value": "3" 2924 } 2925 } 2926 ] 2927 } 2928 } 2929 ] 2930 } 2931 } 2932 } 2933 ] 2934 } 2935 } 2936 ] 2937} 2938 2939=== 2940chained equal and less-than comparison 2941--- 2942struct Foo: 2943 if 1 == 2 < 3: 2944 0 [+1] UInt bar 2945--- 2946{ 2947 "type": [ 2948 { 2949 "structure": { 2950 "field": [ 2951 { 2952 "name": { 2953 "name": { 2954 "text": "bar" 2955 } 2956 }, 2957 "existence_condition": { 2958 "function": { 2959 "function": "AND", 2960 "args": [ 2961 { 2962 "function": { 2963 "function": "EQUALITY", 2964 "args": [ 2965 { 2966 "constant": { 2967 "value": "1" 2968 } 2969 }, 2970 { 2971 "constant": { 2972 "value": "2" 2973 } 2974 } 2975 ] 2976 } 2977 }, 2978 { 2979 "function": { 2980 "function": "LESS", 2981 "args": [ 2982 { 2983 "constant": { 2984 "value": "2" 2985 } 2986 }, 2987 { 2988 "constant": { 2989 "value": "3" 2990 } 2991 } 2992 ] 2993 } 2994 } 2995 ] 2996 } 2997 } 2998 } 2999 ] 3000 } 3001 } 3002 ] 3003} 3004 3005=== 3006chained equal and greater-than comparison 3007--- 3008struct Foo: 3009 if 1 == 2 > 3: 3010 0 [+1] UInt bar 3011--- 3012{ 3013 "type": [ 3014 { 3015 "structure": { 3016 "field": [ 3017 { 3018 "name": { 3019 "name": { 3020 "text": "bar" 3021 } 3022 }, 3023 "existence_condition": { 3024 "function": { 3025 "function": "AND", 3026 "args": [ 3027 { 3028 "function": { 3029 "function": "EQUALITY", 3030 "args": [ 3031 { 3032 "constant": { 3033 "value": "1" 3034 } 3035 }, 3036 { 3037 "constant": { 3038 "value": "2" 3039 } 3040 } 3041 ] 3042 } 3043 }, 3044 { 3045 "function": { 3046 "function": "GREATER", 3047 "args": [ 3048 { 3049 "constant": { 3050 "value": "2" 3051 } 3052 }, 3053 { 3054 "constant": { 3055 "value": "3" 3056 } 3057 } 3058 ] 3059 } 3060 } 3061 ] 3062 } 3063 } 3064 } 3065 ] 3066 } 3067 } 3068 ] 3069} 3070 3071=== 3072chained equality comparison 3073--- 3074struct Foo: 3075 if 1 == 2 == 3: 3076 0 [+1] UInt bar 3077--- 3078{ 3079 "type": [ 3080 { 3081 "structure": { 3082 "field": [ 3083 { 3084 "name": { 3085 "name": { 3086 "text": "bar" 3087 } 3088 }, 3089 "existence_condition": { 3090 "function": { 3091 "function": "AND", 3092 "args": [ 3093 { 3094 "function": { 3095 "function": "EQUALITY", 3096 "args": [ 3097 { 3098 "constant": { 3099 "value": "1" 3100 } 3101 }, 3102 { 3103 "constant": { 3104 "value": "2" 3105 } 3106 } 3107 ] 3108 } 3109 }, 3110 { 3111 "function": { 3112 "function": "EQUALITY", 3113 "args": [ 3114 { 3115 "constant": { 3116 "value": "2" 3117 } 3118 }, 3119 { 3120 "constant": { 3121 "value": "3" 3122 } 3123 } 3124 ] 3125 } 3126 } 3127 ] 3128 } 3129 } 3130 } 3131 ] 3132 } 3133 } 3134 ] 3135} 3136 3137=== 3138choice operator 3139--- 3140struct Foo: 3141 true ? 0 : 1 [+1] UInt bar 3142--- 3143{ 3144 "type": [ 3145 { 3146 "structure": { 3147 "field": [ 3148 { 3149 "name": { 3150 "name": { 3151 "text": "bar" 3152 } 3153 }, 3154 "location": { 3155 "start": { 3156 "function": { 3157 "function": "CHOICE", 3158 "args": [ 3159 { 3160 "boolean_constant": { 3161 "value": true 3162 } 3163 }, 3164 { 3165 "constant": { 3166 "value": "0" 3167 } 3168 }, 3169 { 3170 "constant": { 3171 "value": "1" 3172 } 3173 } 3174 ] 3175 } 3176 } 3177 } 3178 } 3179 ] 3180 } 3181 } 3182 ] 3183} 3184 3185=== 3186max function 3187--- 3188struct Foo: 3189 $max() [+1] UInt no_arg 3190 $max(0) [+1] UInt one_arg 3191 $max(2 * 3) [+1] UInt mul_arg 3192 $max(2, 3) [+1] UInt two_arg 3193 $max(2, 3, 4, 5, 6) [+1] UInt five_arg 3194--- 3195{ 3196 "type": [ 3197 { 3198 "structure": { 3199 "field": [ 3200 { 3201 "name": { 3202 "name": { 3203 "text": "no_arg" 3204 } 3205 }, 3206 "location": { 3207 "start": { 3208 "function": { 3209 "function": "MAXIMUM" 3210 } 3211 } 3212 } 3213 }, 3214 { 3215 "name": { 3216 "name": { 3217 "text": "one_arg" 3218 } 3219 }, 3220 "location": { 3221 "start": { 3222 "function": { 3223 "function": "MAXIMUM", 3224 "args": [ 3225 { 3226 "constant": { 3227 "value": "0" 3228 } 3229 } 3230 ] 3231 } 3232 } 3233 } 3234 }, 3235 { 3236 "name": { 3237 "name": { 3238 "text": "mul_arg" 3239 } 3240 }, 3241 "location": { 3242 "start": { 3243 "function": { 3244 "function": "MAXIMUM", 3245 "args": [ 3246 { 3247 "function": { 3248 "function": "MULTIPLICATION", 3249 "args": [ 3250 { 3251 "constant": { 3252 "value": "2" 3253 } 3254 }, 3255 { 3256 "constant": { 3257 "value": "3" 3258 } 3259 } 3260 ] 3261 } 3262 } 3263 ] 3264 } 3265 } 3266 } 3267 }, 3268 { 3269 "name": { 3270 "name": { 3271 "text": "two_arg" 3272 } 3273 }, 3274 "location": { 3275 "start": { 3276 "function": { 3277 "function": "MAXIMUM", 3278 "args": [ 3279 { 3280 "constant": { 3281 "value": "2" 3282 } 3283 }, 3284 { 3285 "constant": { 3286 "value": "3" 3287 } 3288 } 3289 ] 3290 } 3291 } 3292 } 3293 }, 3294 { 3295 "name": { 3296 "name": { 3297 "text": "five_arg" 3298 } 3299 }, 3300 "location": { 3301 "start": { 3302 "function": { 3303 "function": "MAXIMUM", 3304 "args": [ 3305 { 3306 "constant": { 3307 "value": "2" 3308 } 3309 }, 3310 { 3311 "constant": { 3312 "value": "3" 3313 } 3314 }, 3315 { 3316 "constant": { 3317 "value": "4" 3318 } 3319 }, 3320 { 3321 "constant": { 3322 "value": "5" 3323 } 3324 }, 3325 { 3326 "constant": { 3327 "value": "6" 3328 } 3329 } 3330 ] 3331 } 3332 } 3333 } 3334 } 3335 ] 3336 } 3337 } 3338 ] 3339} 3340 3341=== 3342has function 3343--- 3344struct Foo: 3345 if $present(x): 3346 0 [+1] UInt field 3347 if $present(x.y.z): 3348 0 [+1] UInt field2 3349--- 3350{ 3351 "type": [ 3352 { 3353 "structure": { 3354 "field": [ 3355 { 3356 "name": { 3357 "name": { 3358 "text": "field" 3359 } 3360 }, 3361 "existence_condition": { 3362 "function": { 3363 "function": "PRESENCE", 3364 "args": [ 3365 { 3366 "field_reference": { 3367 "path": [ 3368 { 3369 "source_name": [ 3370 { 3371 "text": "x" 3372 } 3373 ] 3374 } 3375 ] 3376 } 3377 } 3378 ] 3379 } 3380 } 3381 }, 3382 { 3383 "name": { 3384 "name": { 3385 "text": "field2" 3386 } 3387 }, 3388 "existence_condition": { 3389 "function": { 3390 "function": "PRESENCE", 3391 "args": [ 3392 { 3393 "field_reference": { 3394 "path": [ 3395 { 3396 "source_name": [ 3397 { 3398 "text": "x" 3399 } 3400 ] 3401 }, 3402 { 3403 "source_name": [ 3404 { 3405 "text": "y" 3406 } 3407 ] 3408 }, 3409 { 3410 "source_name": [ 3411 { 3412 "text": "z" 3413 } 3414 ] 3415 } 3416 ] 3417 } 3418 } 3419 ] 3420 } 3421 } 3422 } 3423 ] 3424 } 3425 } 3426 ] 3427} 3428 3429=== 3430upper_bound function 3431--- 3432struct Foo: 3433 $upper_bound(0) [+1] UInt one 3434--- 3435{ 3436 "type": [ 3437 { 3438 "structure": { 3439 "field": [ 3440 { 3441 "name": { 3442 "name": { 3443 "text": "one" 3444 } 3445 }, 3446 "location": { 3447 "start": { 3448 "function": { 3449 "function": "UPPER_BOUND", 3450 "args": [ 3451 { 3452 "constant": { 3453 "value": "0" 3454 } 3455 } 3456 ] 3457 } 3458 } 3459 } 3460 } 3461 ] 3462 } 3463 } 3464 ] 3465} 3466 3467=== 3468lower_bound function 3469--- 3470struct Foo: 3471 $lower_bound(0) [+1] UInt one 3472--- 3473{ 3474 "type": [ 3475 { 3476 "structure": { 3477 "field": [ 3478 { 3479 "name": { 3480 "name": { 3481 "text": "one" 3482 } 3483 }, 3484 "location": { 3485 "start": { 3486 "function": { 3487 "function": "LOWER_BOUND", 3488 "args": [ 3489 { 3490 "constant": { 3491 "value": "0" 3492 } 3493 } 3494 ] 3495 } 3496 } 3497 } 3498 } 3499 ] 3500 } 3501 } 3502 ] 3503} 3504 3505=== 3506struct addressable_unit 3507--- 3508struct Foo: 3509 0 [+1] UInt size 3510--- 3511{ "type": [ { "structure": {}, "addressable_unit": "BYTE" } ] } 3512 3513=== 3514bits addressable_unit 3515--- 3516bits Foo: 3517 0 [+1] UInt size 3518--- 3519{ "type": [ { "structure": {}, "addressable_unit": "BIT" } ] } 3520 3521=== 3522enum addressable_unit 3523--- 3524enum Foo: 3525 BAR = 0 3526--- 3527{ "type": [ { "enumeration": {}, "addressable_unit": "BIT" } ] } 3528 3529=== 3530type size source_location 3531--- 3532struct Foo: 3533 0 [+4] UInt:32 field 3534--- 3535{ 3536 "type": [ 3537 { 3538 "structure": { 3539 "field": [ 3540 { 3541 "type": { 3542 "atomic_type": { 3543 "reference": { "source_name": [ { "text": "UInt" } ] } 3544 }, 3545 "size_in_bits": { 3546 "source_location": { 3547 "start": { "line": 3, "column": 15 }, 3548 "end": { "line": 3, "column": 18 } 3549 } 3550 }, 3551 "source_location": { 3552 "start": { "line": 3, "column": 11 }, 3553 "end": { "line": 3, "column": 18 } 3554 } 3555 }, 3556 "name": { "name": { "text": "field" } } 3557 } 3558 ] 3559 } 3560 } 3561 ] 3562} 3563 3564=== 3565builtin references 3566--- 3567external Foo: 3568 [requires: $is_statically_sized && $static_size_in_bits == 64] 3569--- 3570{ 3571 "type": [ 3572 { 3573 "external": {}, 3574 "attribute": [ 3575 { 3576 "name": { "text": "requires" }, 3577 "value": { 3578 "expression": { 3579 "function": { 3580 "args": [ 3581 { 3582 "builtin_reference": { 3583 "canonical_name": { 3584 "module_file": "", 3585 "object_path": [ "$is_statically_sized" ] 3586 }, 3587 "source_name": [ { "text": "$is_statically_sized" } ] 3588 } 3589 }, 3590 { 3591 "function": { 3592 "args": [ 3593 { 3594 "builtin_reference": { 3595 "canonical_name": { 3596 "module_file": "", 3597 "object_path": [ "$static_size_in_bits" ] 3598 }, 3599 "source_name": [ 3600 { "text": "$static_size_in_bits" } 3601 ] 3602 } 3603 } 3604 ] 3605 } 3606 } 3607 ] 3608 } 3609 } 3610 } 3611 } 3612 ] 3613 } 3614 ] 3615} 3616 3617=== 3618$next 3619--- 3620struct Foo: 3621 $next [+0] UInt x 3622--- 3623{ 3624 "type": [ 3625 { 3626 "structure": { 3627 "field": [ 3628 { 3629 "location": { 3630 "start": { 3631 "builtin_reference": { "source_name": [ { "text": "$next" } ] } 3632 } 3633 }, 3634 "name": { "name": { "text": "x" } } 3635 } 3636 ] 3637 } 3638 } 3639 ] 3640} 3641 3642=== 3643virtual fields 3644--- 3645struct Foo: 3646 let x = 10 3647bits Bar: 3648 let y = 100 3649--- 3650{ 3651 "type": [ 3652 { 3653 "structure": { 3654 "field": [ 3655 { 3656 "name": { "name": { "text": "x" } }, 3657 "read_transform": { "constant": { "value": "10" } } 3658 } 3659 ] 3660 } 3661 }, 3662 { 3663 "structure": { 3664 "field": [ 3665 { 3666 "name": { "name": { "text": "y" } }, 3667 "read_transform": { "constant": { "value": "100" } } 3668 } 3669 ] 3670 } 3671 } 3672 ] 3673} 3674 3675=== 3676builtin fields 3677--- 3678struct Foo: 3679 let x = $size_in_bytes 3680 let y = $max_size_in_bytes 3681 let z = $min_size_in_bytes 3682bits Bar: 3683 let x = $size_in_bits 3684 let y = $max_size_in_bits 3685 let z = $min_size_in_bits 3686--- 3687{ 3688 "type": [ 3689 { 3690 "structure": { 3691 "field": [ 3692 { 3693 "name": { "name": { "text": "x" } }, 3694 "read_transform": { 3695 "field_reference": { 3696 "path": [ { "source_name": [ { "text": "$size_in_bytes" } ] } ] 3697 } 3698 } 3699 }, 3700 { 3701 "name": { "name": { "text": "y" } }, 3702 "read_transform": { 3703 "field_reference": { 3704 "path": [ 3705 { "source_name": [ { "text": "$max_size_in_bytes" } ] } 3706 ] 3707 } 3708 } 3709 }, 3710 { 3711 "name": { "name": { "text": "z" } }, 3712 "read_transform": { 3713 "field_reference": { 3714 "path": [ 3715 { "source_name": [ { "text": "$min_size_in_bytes" } ] } 3716 ] 3717 } 3718 } 3719 } 3720 ] 3721 } 3722 }, 3723 { 3724 "structure": { 3725 "field": [ 3726 { 3727 "name": { "name": { "text": "x" } }, 3728 "read_transform": { 3729 "field_reference": { 3730 "path": [ { "source_name": [ { "text": "$size_in_bits" } ] } ] 3731 } 3732 } 3733 }, 3734 { 3735 "name": { "name": { "text": "y" } }, 3736 "read_transform": { 3737 "field_reference": { 3738 "path": [ 3739 { "source_name": [ { "text": "$max_size_in_bits" } ] } 3740 ] 3741 } 3742 } 3743 }, 3744 { 3745 "name": { "name": { "text": "z" } }, 3746 "read_transform": { 3747 "field_reference": { 3748 "path": [ 3749 { "source_name": [ { "text": "$min_size_in_bits" } ] } 3750 ] 3751 } 3752 } 3753 } 3754 ] 3755 } 3756 } 3757 ] 3758} 3759 3760=== 3761parameterized type definitions 3762--- 3763struct Foo(a: Flag, b: UInt:32): 3764 let x = 10 3765bits Bar(c: UInt:16): 3766 let y = 100 3767struct Baz(): 3768 let x = 10 3769--- 3770{ 3771 "type": [ 3772 { 3773 "runtime_parameter": [ 3774 { 3775 "name": { "name": { "text": "a" } }, 3776 "physical_type_alias": { 3777 "atomic_type": { 3778 "reference": { "source_name": [ { "text": "Flag" } ] } 3779 } 3780 } 3781 }, 3782 { 3783 "name": { "name": { "text": "b" } }, 3784 "physical_type_alias": { 3785 "atomic_type": { 3786 "reference": { "source_name": [ { "text": "UInt" } ] } 3787 }, 3788 "size_in_bits": { "constant": { "value": "32" } } 3789 } 3790 } 3791 ] 3792 }, 3793 { 3794 "runtime_parameter": [ 3795 { 3796 "name": { "name": { "text": "c" } }, 3797 "physical_type_alias": { 3798 "atomic_type": { 3799 "reference": { "source_name": [ { "text": "UInt" } ] } 3800 }, 3801 "size_in_bits": { "constant": { "value": "16" } } 3802 } 3803 } 3804 ] 3805 }, 3806 {} 3807 ] 3808} 3809 3810=== 3811parameterized type usages 3812--- 3813struct Foo: 3814 0 [+1] Two(1, 2) two 3815 1 [+1] One(3) one 3816 2 [+1] Zero() zero 3817--- 3818{ 3819 "type": [ 3820 { 3821 "structure": { 3822 "field": [ 3823 { 3824 "type": { 3825 "atomic_type": { 3826 "reference": { "source_name": [ { "text": "Two" } ] }, 3827 "runtime_parameter": [ 3828 { "constant": { "value": "1" } }, 3829 { "constant": { "value": "2" } } 3830 ] 3831 } 3832 }, 3833 "name": { "name": { "text": "two" } } 3834 }, 3835 { 3836 "type": { 3837 "atomic_type": { 3838 "reference": { "source_name": [ { "text": "One" } ] }, 3839 "runtime_parameter": [ { "constant": { "value": "3" } } ] 3840 } 3841 }, 3842 "name": { "name": { "text": "one" } } 3843 }, 3844 { 3845 "type": { 3846 "atomic_type": { 3847 "reference": { "source_name": [ { "text": "Zero" } ] } 3848 } 3849 }, 3850 "name": { "name": { "text": "zero" } } 3851 } 3852 ] 3853 } 3854 } 3855 ] 3856} 3857 3858=== 3859enum value attribute 3860--- 3861enum Foo: 3862 BAR = 1 [test: 0] 3863 BAZ = 2 3864 [test: 1] 3865 [different: "test"] 3866 FOO_BAR = 4 3867 -- foo bar doc 3868 [test: 2] 3869 FOO_BAZ = 8 [test: 3] -- foo baz doc 3870 BAR_FOO = 16 [test: 4] 3871 -- bar foo doc 3872 BAZ_FOO = 32 -- baz foo doc 3873 [test: 5] 3874--- 3875{ 3876 "type": [ 3877 { 3878 "enumeration": { 3879 "value": [ 3880 { 3881 "name": { "name": { "text": "BAR" } }, 3882 "attribute": [ 3883 { 3884 "name": { "text": "test" }, 3885 "value": { "expression": { "constant": { "value": "0" } } } 3886 } 3887 ] 3888 }, 3889 { 3890 "name": { "name": { "text": "BAZ" } }, 3891 "attribute": [ 3892 { 3893 "name": { "text": "test" }, 3894 "value": { "expression": { "constant": { "value": "1" } } } 3895 }, 3896 { 3897 "name": { "text": "different" }, 3898 "value": { "string_constant": { "text": "test" } } 3899 } 3900 ] 3901 }, 3902 { 3903 "name": { "name": { "text": "FOO_BAR" } }, 3904 "documentation": [ { "text": "foo bar doc" } ], 3905 "attribute": [ 3906 { 3907 "name": { "text": "test" }, 3908 "value": { "expression": { "constant": { "value": "2" } } } 3909 } 3910 ] 3911 }, 3912 { 3913 "name": { "name": { "text": "FOO_BAZ" } }, 3914 "documentation": [ { "text": "foo baz doc" } ], 3915 "attribute": [ 3916 { 3917 "name": { "text": "test" }, 3918 "value": { "expression": { "constant": { "value": "3" } } } 3919 } 3920 ] 3921 }, 3922 { 3923 "name": { "name": { "text": "BAR_FOO" } }, 3924 "documentation": [ { "text": "bar foo doc" } ], 3925 "attribute": [ 3926 { 3927 "name": { "text": "test" }, 3928 "value": { "expression": { "constant": { "value": "4" } } } 3929 } 3930 ] 3931 }, 3932 { 3933 "name": { "name": { "text": "BAZ_FOO" } }, 3934 "documentation": [ { "text": "baz foo doc" } ], 3935 "attribute": [ 3936 { 3937 "name": { "text": "test" }, 3938 "value": { "expression": { "constant": { "value": "5" } } } 3939 } 3940 ] 3941 } 3942 ] 3943 }, 3944 "name": { "name": { "text": "Foo" } } 3945 } 3946 ] 3947} 3948 3949""" 3950 3951 3952# For each test in _NEGATIVE_TEST_CASES, parsing should fail, and the failure 3953# should indicate the specified token. 3954_NEGATIVE_TEST_CASES = """ 3955anonymous bits does not allow documentation 3956--- 3957-- doc 3958--- 3959struct Foo: 3960 0 [+1] bits: 3961 -- doc 3962 0 [+2] UInt bar 3963=== 3964anonymous bits does not allow subtypes 3965--- 3966enum 3967--- 3968struct Foo: 3969 0 [+1] bits: 3970 enum Bar: 3971 X = 1 3972 0 [+2] Bar bar 3973""" 3974 3975 3976def _get_test_cases(): 3977 test_case = collections.namedtuple("test_case", ["name", "parse_tree", "ir"]) 3978 result = [] 3979 for case in _TEST_CASES.split("==="): 3980 name, emb, ir_text = case.split("---") 3981 name = name.strip() 3982 try: 3983 ir = ir_data_utils.IrDataSerializer.from_json(ir_data.Module, ir_text) 3984 except Exception: 3985 print(name) 3986 raise 3987 parse_result = parser.parse_module(tokenizer.tokenize(emb, "")[0]) 3988 assert not parse_result.error, "{}:\n{}".format(name, parse_result.error) 3989 result.append(test_case(name, parse_result.parse_tree, ir)) 3990 return result 3991 3992 3993def _get_negative_test_cases(): 3994 test_case = collections.namedtuple("test_case", 3995 ["name", "text", "error_token"]) 3996 result = [] 3997 for case in _NEGATIVE_TEST_CASES.split("==="): 3998 name, error_token, text = case.split("---") 3999 name = name.strip() 4000 error_token = error_token.strip() 4001 result.append(test_case(name, text, error_token)) 4002 return result 4003 4004 4005def _check_source_location(source_location, path, min_start, max_end): 4006 """Performs sanity checks on a source_location field. 4007 4008 Arguments: 4009 source_location: The source_location to check. 4010 path: The path, to use in error messages. 4011 min_start: A minimum value for source_location.start, or None. 4012 max_end: A maximum value for source_location.end, or None. 4013 4014 Returns: 4015 A list of error messages, or an empty list if no errors. 4016 """ 4017 if source_location.is_disjoint_from_parent: 4018 # If source_location.is_disjoint_from_parent, then this source_location is 4019 # allowed to be outside of the parent's source_location. 4020 return [] 4021 4022 result = [] 4023 start = None 4024 end = None 4025 if not source_location.HasField("start"): 4026 result.append("{}.start missing".format(path)) 4027 else: 4028 start = source_location.start 4029 if not source_location.HasField("end"): 4030 result.append("{}.end missing".format(path)) 4031 else: 4032 end = source_location.end 4033 4034 if start and end: 4035 if start.HasField("line") and end.HasField("line"): 4036 if start.line > end.line: 4037 result.append("{}.start.line > {}.end.line ({} vs {})".format( 4038 path, path, start.line, end.line)) 4039 elif start.line == end.line: 4040 if (start.HasField("column") and end.HasField("column") and 4041 start.column > end.column): 4042 result.append("{}.start.column > {}.end.column ({} vs {})".format( 4043 path, path, start.column, end.column)) 4044 4045 for name, field in (("start", start), ("end", end)): 4046 if not field: 4047 continue 4048 if field.HasField("line"): 4049 if field.line <= 0: 4050 result.append("{}.{}.line <= 0 ({})".format(path, name, field.line)) 4051 else: 4052 result.append("{}.{}.line missing".format(path, name)) 4053 if field.HasField("column"): 4054 if field.column <= 0: 4055 result.append("{}.{}.column <= 0 ({})".format(path, name, field.column)) 4056 else: 4057 result.append("{}.{}.column missing".format(path, name)) 4058 4059 if min_start and start: 4060 if min_start.line > start.line or ( 4061 min_start.line == start.line and min_start.column > start.column): 4062 result.append("{}.start before parent start".format(path)) 4063 4064 if max_end and end: 4065 if max_end.line < end.line or ( 4066 max_end.line == end.line and max_end.column < end.column): 4067 result.append("{}.end after parent end".format(path)) 4068 4069 return result 4070 4071 4072def _check_all_source_locations(proto, path="", min_start=None, max_end=None): 4073 """Performs sanity checks on all source_locations in proto. 4074 4075 Arguments: 4076 proto: The proto to recursively check. 4077 path: The path, to use in error messages. 4078 min_start: A minimum value for source_location.start, or None. 4079 max_end: A maximum value for source_location.end, or None. 4080 4081 Returns: 4082 A list of error messages, or an empty list if no errors. 4083 """ 4084 if path: 4085 path += "." 4086 4087 errors = [] 4088 4089 child_start = None 4090 child_end = None 4091 # Only check the source_location value if this proto message actually has a 4092 # source_location field. 4093 if proto.HasField("source_location"): 4094 errors.extend(_check_source_location(proto.source_location, 4095 path + "source_location", 4096 min_start, max_end)) 4097 child_start = proto.source_location.start 4098 child_end = proto.source_location.end 4099 4100 for name, spec in ir_data_fields.field_specs(proto).items(): 4101 if name == "source_location": 4102 continue 4103 if not proto.HasField(name): 4104 continue 4105 field_path = "{}{}".format(path, name) 4106 if spec.is_dataclass: 4107 if spec.is_sequence: 4108 index = 0 4109 for i in getattr(proto, name): 4110 item_path = "{}[{}]".format(field_path, index) 4111 index += 1 4112 errors.extend( 4113 _check_all_source_locations(i, item_path, child_start, child_end)) 4114 else: 4115 errors.extend(_check_all_source_locations(getattr(proto, name), 4116 field_path, child_start, 4117 child_end)) 4118 4119 return errors 4120 4121 4122class ModuleIrTest(unittest.TestCase): 4123 """Tests the module_ir.build_ir() function.""" 4124 4125 def test_build_ir(self): 4126 ir = module_ir.build_ir(_MINIMAL_SAMPLE) 4127 ir.source_text = _MINIMAL_SOURCE 4128 self.assertEqual(ir, _MINIMAL_SAMPLE_IR) 4129 4130 def test_production_coverage(self): 4131 """Checks that all grammar productions are used somewhere in tests.""" 4132 used_productions = set() 4133 module_ir.build_ir(_MINIMAL_SAMPLE, used_productions) 4134 for test in _get_test_cases(): 4135 module_ir.build_ir(test.parse_tree, used_productions) 4136 self.assertEqual(set(module_ir.PRODUCTIONS) - used_productions, set([])) 4137 4138 def test_double_negative_non_compilation(self): 4139 """Checks that unparenthesized double unary minus/plus is a parse error.""" 4140 for example in ("[x: - -3]", "[x: + -3]", "[x: - +3]", "[x: + +3]"): 4141 parse_result = parser.parse_module(tokenizer.tokenize(example, "")[0]) 4142 self.assertTrue(parse_result.error) 4143 self.assertEqual(7, parse_result.error.token.source_location.start.column) 4144 for example in ("[x:-(-3)]", "[x:+(-3)]", "[x:-(+3)]", "[x:+(+3)]"): 4145 parse_result = parser.parse_module(tokenizer.tokenize(example, "")[0]) 4146 self.assertFalse(parse_result.error) 4147 4148 4149def _make_superset_tests(): 4150 4151 def _make_superset_test(test): 4152 4153 def test_case(self): 4154 ir = module_ir.build_ir(test.parse_tree) 4155 is_superset, error_message = test_util.proto_is_superset(ir, test.ir) 4156 4157 self.assertTrue( 4158 is_superset, 4159 error_message + "\n" + ir_data_utils.IrDataSerializer(ir).to_json(indent=2) + "\n" + 4160 ir_data_utils.IrDataSerializer(test.ir).to_json(indent=2)) 4161 4162 return test_case 4163 4164 for test in _get_test_cases(): 4165 test_name = "test " + test.name + " proto superset" 4166 assert not hasattr(ModuleIrTest, test_name) 4167 setattr(ModuleIrTest, test_name, _make_superset_test(test)) 4168 4169 4170def _make_source_location_tests(): 4171 4172 def _make_source_location_test(test): 4173 4174 def test_case(self): 4175 error_list = _check_all_source_locations( 4176 module_ir.build_ir(test.parse_tree)) 4177 self.assertFalse(error_list, "\n".join([test.name] + error_list)) 4178 4179 return test_case 4180 4181 for test in _get_test_cases(): 4182 test_name = "test " + test.name + " source location" 4183 assert not hasattr(ModuleIrTest, test_name) 4184 setattr(ModuleIrTest, test_name, _make_source_location_test(test)) 4185 4186 4187def _make_negative_tests(): 4188 4189 def _make_negative_test(test): 4190 4191 def test_case(self): 4192 parse_result = parser.parse_module(tokenizer.tokenize(test.text, "")[0]) 4193 self.assertEqual(test.error_token, parse_result.error.token.text.strip()) 4194 4195 return test_case 4196 4197 for test in _get_negative_test_cases(): 4198 test_name = "test " + test.name + " compilation failure" 4199 assert not hasattr(ModuleIrTest, test_name) 4200 setattr(ModuleIrTest, test_name, _make_negative_test(test)) 4201 4202_make_negative_tests() 4203_make_superset_tests() 4204_make_source_location_tests() 4205 4206 4207if __name__ == "__main__": 4208 unittest.main() 4209