├── .editorconfig ├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── command_test.v ├── src ├── c2v.v ├── c2v_test.v ├── configuration.v ├── cpp.v ├── node.v ├── node_kind.v └── struct.v ├── tests ├── 1.hello.c ├── 1.hello.out ├── 10.jni.h ├── 10.jni.out ├── 11.enum_default.c ├── 11.enum_default.out ├── 12.if_stmt.c ├── 12.if_stmt.out ├── 13.switch.c ├── 13.switch.out ├── 14.default.c ├── 14.default.out ├── 15.multi_var_decl.c ├── 15.multi_var_decl.out ├── 16.literals.c ├── 16.literals.out ├── 17.partial_struct.c ├── 17.partial_struct.out ├── 18.header_types.h ├── 18.header_types.out ├── 19.header_visibility_attribute.h ├── 19.header_visibility_attribute.out ├── 2.if.c ├── 2.if.out ├── 20.header_duplicate_type_declaration.h ├── 20.header_duplicate_type_declaration.out ├── 21.header_uninited_global_var.h ├── 21.header_uninited_global_var.out ├── 22.getline_linux.c ├── 22.getline_linux.out ├── 22.getline_macos.c ├── 22.getline_macos.out ├── 23.sizeof.c ├── 23.sizeof.out ├── 24.typedef_struct.h ├── 24.typedef_struct.out ├── 25.return_val_2.c ├── 25.return_val_2.out ├── 26.assign_zerof.c ├── 26.assign_zerof.out ├── 3.if_switch_enum.c ├── 3.if_switch_enum.out ├── 4.for.c ├── 4.for.out ├── 5.struct.c ├── 5.struct.out ├── 6.types.c ├── 6.types.out ├── 7.api_types.h ├── 7.api_types.out ├── 8.simple_func_header.h ├── 8.simple_func_header.out ├── 9.func_declaration.h ├── 9.func_declaration.out ├── IGNORE_header_duplicate_type_declaration_2.h ├── run_doom_tests.vsh ├── run_tests.vsh └── test.c │ ├── 1.hello.c │ └── 1.hello.out ├── tests_todo ├── 5.if_paren_call.c └── 5.if_paren_call.out ├── tools ├── build_doom_file.vsh └── node_kind_gen │ ├── gen_node_kind_code.v │ └── types └── v.mod /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset = utf-8 3 | end_of_line = lf 4 | insert_final_newline = true 5 | trim_trailing_whitespace = true 6 | 7 | [*.v] 8 | indent_style = tab 9 | indent_size = 4 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.v linguist-language=V text=auto eol=lf 2 | *.vv linguist-language=V text=auto eol=lf 3 | *.vsh linguist-language=V text=auto eol=lf 4 | **/v.mod linguist-language=V text=auto eol=lf 5 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | paths-ignore: ['**/*.md', '^\.*', 'LICENSE'] 6 | pull_request: 7 | paths-ignore: ['**/*.md', '^\.*', 'LICENSE'] 8 | schedule: 9 | - cron: '31 1,12 * * *' 10 | 11 | jobs: 12 | build: 13 | strategy: 14 | matrix: 15 | os: [ubuntu-latest, macos-latest] 16 | fail-fast: false 17 | runs-on: ${{ matrix.os }} 18 | steps: 19 | - name: Checkout V 20 | uses: actions/checkout@v4 21 | with: 22 | repository: vlang/v 23 | - name: Checkout C2V 24 | uses: actions/checkout@v4 25 | with: 26 | path: c2v 27 | - name: Install dependencies 28 | run: | 29 | if [ "${{ runner.os }}" == "Linux" ]; then 30 | sudo apt update -y -qq 31 | sudo apt install libsdl2-dev libsdl2-mixer-dev libsdl2-net-dev libpng-dev libsamplerate0-dev 32 | else 33 | brew install sdl2 sdl2_mixer sdl2_net libpng libsamplerate 34 | fi 35 | - name: Build V 36 | run: make && ./v symlink 37 | - name: Setup C2V 38 | run: | 39 | mv c2v ~/.vmodules/c2v 40 | v -g ~/.vmodules/c2v/ || true 41 | - name: Test C2V 42 | run: v -g test ~/.vmodules/c2v/ 43 | - name: Build original Chocolate Doom 44 | run: | 45 | git clone --quiet --depth 1 https://github.com/vlang/doom ~/code/doom 46 | cd ~/code/doom/chocolate-doom 47 | cmake -DCMAKE_BUILD_TYPE=Debug . 48 | make chocolate-doom 49 | - name: Translate just p_enemy.v 50 | run: | 51 | cd ~/.vmodules/c2v/ 52 | v -g run tools/build_doom_file.vsh doom/p_enemy 53 | - name: Translate the whole game in project/folder mode 54 | run: | 55 | touch ~/DOOM1.WAD 56 | if [ "${{ runner.os }}" == "Linux" ]; then 57 | WAD_FILE=~/DOOM1.WAD ~/code/doom/build_whole_project.sh 58 | else 59 | echo "TODO: ... building doom should be fixed on macos, after it regressed in eafdd3c" 60 | fi 61 | 62 | test-regressions: 63 | runs-on: ubuntu-latest 64 | timeout-minutes: 10 65 | env: 66 | VFLAGS: -cc tcc 67 | DISPLAY: :99 68 | LIBGL_ALWAYS_SOFTWARE: true 69 | VTMP: /tmp 70 | steps: 71 | - name: Checkout V 72 | uses: actions/checkout@v4 73 | with: 74 | repository: vlang/v 75 | - name: Checkout C2V 76 | uses: actions/checkout@v4 77 | with: 78 | path: c2v 79 | - name: Install dependencies 80 | run: | 81 | sudo apt update -y -qq 82 | sudo apt install libsdl2-dev libsdl2-mixer-dev libsdl2-net-dev libpng-dev libsamplerate0-dev 83 | # c2v / DOOM dependencies 84 | # vgret dependencies 85 | # imagemagick : convert, mogrify, import 86 | # xvfb : For starting X11 Virtual FrameBuffers 87 | # openimageio-tools : idiff 88 | # libgl1-mesa-dri : For headless rendering / software DRI driver (LIBGL_ALWAYS_SOFTWARE=true) 89 | # freeglut3-dev : Fixes graphic apps compilation with tcc 90 | sudo apt install imagemagick openimageio-tools freeglut3-dev libgl1-mesa-dri xvfb xsel xclip 91 | - name: Setup test tools 92 | run: | 93 | # Fetch the free ~4MB DOOM1.WAD from the link at https://doomwiki.org/wiki/DOOM1.WAD 94 | wget https://distro.ibiblio.org/slitaz/sources/packages/d/doom1.wad -O ~/doom1.wad 95 | # Get imgur upload script 96 | wget https://raw.githubusercontent.com/tremby/imgur.sh/c98345d/imgur.sh 97 | chmod +x ./imgur.sh 98 | # Get regression images to test against 99 | git clone https://github.com/Larpon/doom-regression-images 100 | - name: Build V 101 | run: make && ./v symlink 102 | - name: Setup C2V 103 | run: | 104 | mv c2v ~/.vmodules/c2v 105 | v -g ~/.vmodules/c2v/ || true 106 | - name: Test C2V 107 | run: v -g test ~/.vmodules/c2v/ 108 | - name: Build original Chocolate Doom 109 | run: | 110 | git clone --quiet --depth 1 https://github.com/vlang/doom ~/code/doom 111 | cd ~/code/doom/chocolate-doom 112 | cmake -DCMAKE_BUILD_TYPE=Debug . 113 | make chocolate-doom 114 | - name: Translate the whole game in project/folder mode 115 | run: WAD_FILE=~/doom1.wad ~/code/doom/build_whole_project.sh 116 | - name: Sample and compare 117 | id: compare 118 | continue-on-error: true 119 | run: | 120 | Xvfb $DISPLAY -screen 0 800x600x24 -fbdir /var/tmp/ & 121 | sleep 1; while [ ! -f /var/tmp/Xvfb_screen0 ]; do sleep 0.5; done # give xvfb time to start, even on slow CI runs 122 | sleep 1; v gret -r ~/code/doom -t ./doom-regression-images/vgret.doom.toml -v ./doom-sample_images ./doom-regression-images 123 | - name: Upload regression to imgur 124 | if: steps.compare.outcome != 'success' 125 | run: | 126 | ./imgur.sh /tmp/fail.png 127 | ./imgur.sh /tmp/diff.png 128 | exit 1 129 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | main 3 | c2v 4 | *.exe 5 | *.exe~ 6 | *.so 7 | *.dylib 8 | *.dll 9 | vls.log 10 | tests/run_tests 11 | .idea/ 12 | tests/**.json 13 | 14 | tests/test.c/1.hello.json 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: c2v 2 | 3 | c2v: *.v 4 | v -experimental -w . 5 | 6 | clean: 7 | rm -rf c2v 8 | 9 | .PHONY: all clean 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## C2V 2 | 3 | C => V source code translator. 4 | 5 | Demo Video: Translating DOOM from C to V, building and running it. 6 | 7 | https://www.youtube.com/watch?v=6oXrz3oRoEg 8 | 9 | 10 | ### Building 11 | 12 | ```bash 13 | v . 14 | ``` 15 | ... or if you want to debug c2v behaviour: 16 | ```bash 17 | v -d trace_verbose . 18 | ``` 19 | 20 | No dependencies other than a `clang` binary. 21 | 22 | 23 | ### Usage 24 | 25 | c2v accepts the following arguments: 26 | ``` 27 | -keep_ast keep ast files 28 | -print_tree print the entire tree 29 | ``` 30 | 31 | ``` 32 | c2v file.c 33 | ``` 34 | 35 | This will generate `file.v`. 36 | 37 | ``` 38 | c2v project 39 | ``` 40 | 41 | This will translate each C file in the `project` directory. 42 | 43 | ``` 44 | project/ ==> project/ 45 | a.c a.c 46 | foo.c a.v 47 | foo.c 48 | foo.v 49 | ``` 50 | 51 | You may need to run translated code with `v -translated file.v` until early 2023. 52 | 53 | ### Wrapper generation 54 | 55 | C2V can also generate V wrappers on top of C libraries. 56 | 57 | ``` 58 | c2v wrapper file.c 59 | ``` 60 | 61 | ### Notes 62 | 63 | C2V is using Clang's AST to generate V. This allowed us to avoid writing a C parser. 64 | 65 | In order to avoid LLVM dependencies/C++ complexity, C2V parses AST generated by the `clang` binary. 66 | 67 | 68 | ### Configuration 69 | C2V supports reading from a project configuration file named `c2v.toml`, located in one of these places, in this order: 70 | 1) if C2V_CONFIG is set, it should contain the c2v.toml path. 71 | 2) the project folder (the last folder passed to c2v) + /c2v.toml 72 | 3) the project folder (the folder of the file that is last passed to c2v) + /c2v.toml 73 | 74 | That file has the following format: 75 | ```toml 76 | [project] 77 | uses_sdl = true 78 | output_dirname = "c2v_out.dir" 79 | additional_flags = "-I. -I.. -I../.." 80 | 81 | ["info.c"] 82 | additional_flags = "-I/some/folder/used/only/for/that/specific/file" 83 | ``` 84 | 85 | In the above: 86 | `uses_sdl` is a boolean, that defaults to false. 87 | When it is true, c2v will append the result of `sdl2-config --cflags` to `additional_flags` . 88 | `output_dirname` is a string, that defaults to `c2v_output`. c2v will create that folder, if it does not exist, and it will put all the translated .v files there. 89 | `additional_flags` is a string, that will be passed verbatim to the clang parser for each .c file. It can be used to pass additional -I flags, that are specific to your project, so that clang can find all the headers needed by that project. 90 | 91 | Note: all these are global to the project. 92 | 93 | The c2v.toml configuration file also supports file specific overrides, for the `additional_flags` option, just put them in their own sections, 94 | titled as the file name. 95 | -------------------------------------------------------------------------------- /command_test.v: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | fn testsuite_begin() { 4 | os.chdir(os.dir(@FILE))! 5 | } 6 | 7 | fn test_run_tests() { 8 | res := os.system('${os.quoted_path(@VEXE)} tests/run_tests.vsh') 9 | assert res == 0 10 | } 11 | -------------------------------------------------------------------------------- /src/c2v_test.v: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn check_ct(str_typ string, expected string) { 4 | t := convert_type(str_typ) 5 | assert t.name == expected 6 | if t.name != expected { 7 | println('!!!' + t.name) 8 | } 9 | } 10 | 11 | fn test_convert_type() { 12 | check_ct('FuncDef *[23]', '[23]&FuncDef') 13 | check_ct('void (*)(void *, void *)', 'fn (voidptr, voidptr)') 14 | check_ct('const char **', '&&u8') 15 | check_ct('byte [20]', '[20]u8') 16 | check_ct('byte *', '&u8') 17 | check_ct('byte *:byte *', '&u8') 18 | check_ct('short', 'i16') 19 | check_ct('signed char', 'i8') 20 | check_ct('int **', '&&int') 21 | check_ct('void **', '&voidptr') 22 | } 23 | 24 | fn test_trim_underscore() { 25 | assert trim_underscores('__name') == 'name' 26 | assert trim_underscores('_name') == 'name' 27 | } 28 | -------------------------------------------------------------------------------- /src/configuration.v: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | import os 4 | import toml 5 | 6 | fn (mut c2v C2V) handle_configuration(args []string) { 7 | last_path := args.last() 8 | if os.is_dir(last_path) { 9 | c2v.is_dir = true 10 | c2v.project_folder = os.real_path(last_path) 11 | } else { 12 | c2v.is_dir = false 13 | c2v.project_folder = os.dir(os.real_path(last_path)) 14 | } 15 | // Configuration file priority: 16 | // 1) C2V_CONFIG, but only if it exits 17 | // 2) project_folder/c2v.toml, but only if it exists 18 | mut c2v_config_file := os.getenv('C2V_CONFIG') 19 | if c2v_config_file == '' || !os.exists(c2v_config_file) { 20 | c2v_config_file = '' 21 | folder_file := os.join_path(c2v.project_folder, 'c2v.toml') 22 | if os.exists(folder_file) { 23 | c2v_config_file = folder_file 24 | } 25 | } 26 | c2v.read_toml_configuration(c2v_config_file) 27 | c2v.set_config_overrides_for_project() 28 | } 29 | 30 | fn (mut c2v C2V) get_additional_flags(path string) string { 31 | return '${c2v.project_additional_flags} ${c2v.file_additional_flags} ' 32 | } 33 | 34 | fn (mut c2v C2V) get_globals_path() string { 35 | return c2v.project_globals_path 36 | } 37 | 38 | fn (mut c2v C2V) read_toml_configuration(toml_file string) { 39 | if toml_file == '' { 40 | return 41 | } 42 | vprintln('> reading from toml configuration file: ${toml_file}') 43 | c2v.conf = toml.parse_file(toml_file) or { panic(err) } 44 | // dump(c2v.conf) 45 | } 46 | 47 | // called once per invocation 48 | fn (mut c2v C2V) set_config_overrides_for_project() { 49 | c2v.project_uses_sdl = c2v.conf.value('project.uses_sdl').default_to(false).bool() 50 | c2v.project_output_dirname = c2v.conf.value('project.output_dirname').default_to('c2v_output').string() 51 | c2v.project_additional_flags = c2v.conf.value('project.additional_flags').default_to('-I.').string() 52 | c2v.wrapper_module_name = c2v.conf.value('project.wrapper_module_name').default_to('').string() 53 | c2v.keep_ast = c2v.conf.value('keep_ast').default_to(false).bool() 54 | if c2v.project_uses_sdl { 55 | sdl_cflags := get_sdl_cflags() 56 | c2v.project_additional_flags += ' ' + sdl_cflags 57 | } 58 | c2v.project_globals_path = os.real_path(os.join_path(c2v.project_folder, c2v.project_output_dirname, 59 | '_globals.v')) 60 | } 61 | 62 | // called once per each .c file 63 | fn (mut c2v C2V) set_config_overrides_for_file(path string) { 64 | fname := os.file_name(path) 65 | c2v.file_additional_flags = c2v.conf.value("'${fname}'.additional_flags").default_to('').string() 66 | } 67 | 68 | fn get_sdl_cflags() string { 69 | res := os.execute('sdl2-config --cflags') 70 | if res.exit_code != 0 { 71 | eprintln('The project uses sdl, but `sdl2-config` was not found. Try installing a development package for SDL2') 72 | exit(1) 73 | } 74 | return res.output.trim_space() 75 | } 76 | -------------------------------------------------------------------------------- /src/cpp.v: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn (mut c C2V) cpp_top_level(_node &Node) bool { 4 | println('C++ top level') 5 | mut node := unsafe { _node } 6 | if node.kindof(.namespace_decl) { 7 | for child in node.inner { 8 | c.top_level(child) 9 | } 10 | } else if node.kindof(.cxx_constructor_decl) { 11 | c.constructor_decl(node) 12 | } else if node.kindof(.cxx_destructor_decl) { 13 | c.destructor_decl(node) 14 | } else if node.kindof(.original) { 15 | } else if node.kindof(.using_decl) { 16 | } else if node.kindof(.using_shadow_decl) { 17 | } else if node.kindof(.class_template_decl) { 18 | c.class_template_decl(node) 19 | } else if node.kindof(.class_template_specialization_decl) { 20 | } else if node.kindof(.cxx_record_decl) { 21 | } else if node.kindof(.linkage_spec_decl) { 22 | } else if node.kindof(.using_directive_decl) { 23 | } else if node.kindof(.class_template_partial_specialization_decl) { 24 | } else if node.kindof(.function_template_decl) { 25 | c.fn_template_decl(mut node) 26 | } else if node.kindof(.cxx_method_decl) { 27 | c.cxx_method_decl(node) 28 | } else { 29 | return false 30 | } 31 | return true 32 | } 33 | 34 | fn (mut c C2V) cpp_expr(_node &Node) bool { 35 | mut node := unsafe { _node } 36 | vprintln('C++ expr check') 37 | // println(node.vals) 38 | vprintln(node.ast_type.str()) 39 | // std::vector a; OR 40 | // User u(34); 41 | if node.kindof(.cxx_construct_expr) { 42 | // println(node.vals) 43 | // c.genln(node.vals.str()) 44 | c.genln('// cxx cons') 45 | typ := node.ast_type.qualified // get_val(-2) 46 | if typ.contains('') { 47 | c.gen('int') 48 | } 49 | } else if node.kindof(.cxx_member_call_expr) { 50 | // c.gen('[CXX MEMBER] ') 51 | mut member_expr := node.try_get_next_child_of_kind(.member_expr) or { 52 | println(err) 53 | bad_node 54 | } 55 | 56 | method_name := member_expr.name // get_val(-2) 57 | child := member_expr.try_get_next_child() or { 58 | println(err) 59 | bad_node 60 | } 61 | c.expr(child) 62 | mut add_par := false 63 | match method_name { 64 | '.push_back' { 65 | c.gen(' << ') 66 | } 67 | '.size' { 68 | c.gen('.len') 69 | } 70 | else { 71 | add_par = true 72 | method := method_name.replace('->', '.') 73 | c.gen('${method}(') 74 | } 75 | } 76 | mut mat_tmp_expr := node.try_get_next_child() or { 77 | println(err) 78 | bad_node 79 | } 80 | if mat_tmp_expr.kindof(.materialize_temporary_expr) { 81 | expr := mat_tmp_expr.try_get_next_child() or { 82 | println(err) 83 | bad_node 84 | } 85 | c.expr(expr) 86 | } 87 | if add_par { 88 | c.gen(')') 89 | } 90 | } 91 | // operator call (std::cout << etc) 92 | else if node.kindof(.cxx_operator_call_expr) { 93 | c.operator_call(node) 94 | } 95 | // std::string s = "HI"; 96 | else if node.kindof(.expr_with_cleanups) { 97 | vprintln('expr with cle') 98 | typ := node.ast_type.qualified // get_val(-1) 99 | vprintln('TYP=${typ}') 100 | if typ.contains('basic_string<') { 101 | // All this for a simple std::string = "hello"; 102 | mut construct_expr := node.try_get_next_child_of_kind(.cxx_construct_expr) or { 103 | println(err) 104 | bad_node 105 | } 106 | 107 | mut mat_tmp_expr := construct_expr.try_get_next_child_of_kind(.materialize_temporary_expr) or { 108 | println(err) 109 | bad_node 110 | } 111 | 112 | // cast_expr := mat_tmp_expr.get(ImplicitCastExpr) 113 | mut cast_expr := mat_tmp_expr.try_get_next_child() or { 114 | println(err) 115 | bad_node 116 | } 117 | if !cast_expr.kindof(.implicit_cast_expr) { 118 | return true 119 | } 120 | mut bind_tmp_expr := cast_expr.try_get_next_child_of_kind(.cxx_bind_temporary_expr) or { 121 | println(err) 122 | bad_node 123 | } 124 | 125 | mut cast_expr2 := bind_tmp_expr.try_get_next_child_of_kind(.implicit_cast_expr) or { 126 | println(err) 127 | bad_node 128 | } 129 | 130 | mut construct_expr2 := cast_expr2.try_get_next_child_of_kind(.cxx_construct_expr) or { 131 | println(err) 132 | bad_node 133 | } 134 | 135 | mut cast_expr3 := construct_expr2.try_get_next_child_of_kind(.implicit_cast_expr) or { 136 | println(err) 137 | bad_node 138 | } 139 | 140 | str_lit := cast_expr3.try_get_next_child_of_kind(.string_literal) or { 141 | println(err) 142 | bad_node 143 | } 144 | 145 | c.gen(str_lit.value as string) // get_val(-1)) 146 | } 147 | } else if node.kindof(.unresolved_lookup_expr) { 148 | } else if node.kindof(.cxx_try_stmt) { 149 | } else if node.kindof(.cxx_throw_expr) { 150 | } else if node.kindof(.cxx_dynamic_cast_expr) { 151 | typ_ := convert_type(node.ast_type.qualified) // get_val(2)) 152 | mut dtyp := typ_.name 153 | dtyp = dtyp.replace('* ', '&') 154 | c.gen('${dtyp}( ') 155 | child := node.try_get_next_child() or { 156 | println(err) 157 | bad_node 158 | } 159 | c.expr(child) 160 | c.gen(')') 161 | } else if node.kindof(.cxx_reinterpret_cast_expr) { 162 | } else if node.kindof(.cxx_unresolved_construct_expr) { 163 | } else if node.kindof(.cxx_dependent_scope_member_expr) { 164 | } else if node.kindof(.cxx_this_expr) { 165 | c.gen('this') 166 | } else if node.kindof(.cxx_bool_literal_expr) { 167 | val := node.value // get_val(-1) 168 | c.gen(val as string) 169 | } else if node.kindof(.cxx_null_ptr_literal_expr) { 170 | c.gen('nullptr') 171 | } else if node.kindof(.cxx_functional_cast_expr) { 172 | } else if node.kindof(.cxx_delete_expr) { 173 | } 174 | // static_cast(a) 175 | else if node.kindof(.cxx_static_cast_expr) { 176 | typ := node.ast_type.qualified // get_val(0) 177 | // v := node.vals.join(' ') 178 | c.gen('(${typ})(') 179 | expr := node.try_get_next_child() or { 180 | println(err) 181 | bad_node 182 | } 183 | c.expr(expr) 184 | c.gen(')') 185 | } else if node.kindof(.materialize_temporary_expr) { 186 | } else if node.kindof(.cxx_temporary_object_expr) { 187 | } else if node.kindof(.decl_stmt) { 188 | // TODO WTF 189 | } else if node.kindof(.cxx_new_expr) { 190 | } else { 191 | return false 192 | } 193 | return true 194 | } 195 | 196 | fn (mut c C2V) fn_template_decl(mut node Node) { 197 | // name := node.get_val(- 1) 198 | // build "" 199 | mut types := '<' 200 | nr_types := node.count_children_of_kind(.template_type_parm_decl) 201 | for i := 0; i < nr_types; i++ { 202 | t := node.try_get_next_child_of_kind(.template_type_parm_decl) or { 203 | println(err) 204 | bad_node 205 | } 206 | 207 | types += t.ast_type.qualified // get_val(-1) 208 | if i != nr_types - 1 { 209 | types += ', ' 210 | } 211 | } 212 | types = types + '>' 213 | // First child fn decl is with 214 | // fn_node := node.get(.FunctionDecl) 215 | mut children := node.find_children(.function_decl) 216 | for mut fn_node in children { 217 | // fn_node2 := node.get(FunctionDecl) 218 | c.fn_decl(mut fn_node, '') // types) 219 | } 220 | } 221 | 222 | fn (mut c C2V) class_template_decl(node &Node) { 223 | // mut node := _node 224 | name := node.name // get_val(-1) 225 | c.genln('CLASS ${name}') 226 | } 227 | 228 | // CBattleAnimation::CBattleAnimation() 229 | fn (mut c C2V) constructor_decl(_node &Node) { 230 | mut node := unsafe { _node } 231 | // nt := get_name_type(node) 232 | name := node.name 233 | typ := convert_type(node.ast_type.qualified) 234 | str_args := c.fn_params(mut node) 235 | c.genln('fn new_${name}(${str_args}) ${typ.name} {') 236 | // User::User() : field1(val1), field2(val2) 237 | nr_ctor_inits := node.count_children_of_kind(.cxx_ctor_initializer) 238 | for i := 0; i < nr_ctor_inits; i++ { 239 | mut init := node.try_get_next_child_of_kind(.cxx_ctor_initializer) or { 240 | println(err) 241 | bad_node 242 | } 243 | 244 | expr := init.try_get_next_child() or { 245 | println(err) 246 | bad_node 247 | } 248 | c.expr(expr) 249 | c.genln('') 250 | } 251 | mut stmts := node.try_get_next_child_of_kind(.compound_stmt) or { 252 | println(err) 253 | bad_node 254 | } 255 | 256 | c.st_block_no_start(mut stmts) 257 | c.genln('') 258 | } 259 | 260 | // CBattleAnimation::~CBattleAnimation() 261 | fn (mut c C2V) destructor_decl(node &Node) { 262 | } 263 | 264 | fn (mut c C2V) cxx_method_decl(_node &Node) { 265 | mut node := unsafe { _node } 266 | name := node.name 267 | typ := convert_type(node.ast_type.qualified) 268 | str_args := c.fn_params(mut node) 269 | c.genln('fn (this typ) ${name}(${str_args}) ${typ.name} {') 270 | if node.has_child_of_kind(.overrides) { 271 | node.try_get_next_child_of_kind(.overrides) or { 272 | println(err) 273 | bad_node 274 | } 275 | } 276 | mut stmts := node.try_get_next_child_of_kind(.compound_stmt) or { 277 | println(err) 278 | bad_node 279 | } 280 | 281 | c.statements(mut stmts) 282 | } 283 | 284 | // std::cout << etc 285 | fn (mut c C2V) operator_call(_node &Node) { 286 | mut node := unsafe { _node } 287 | // cast_expr := node.get(ImplicitCastExpr) 288 | mut cast_expr := node.try_get_next_child() or { 289 | println(err) 290 | bad_node 291 | } 292 | if !cast_expr.kindof(.implicit_cast_expr) { 293 | c.genln('OP@@') 294 | return 295 | } 296 | decl_ref_expr := cast_expr.try_get_next_child_of_kind(.decl_ref_expr) or { 297 | println(err) 298 | bad_node 299 | } 300 | 301 | // vprintln('\n CXX OPERATOR DRE') 302 | // vprintln(decl_ref_expr.vals) 303 | typ := decl_ref_expr.ast_type.qualified // get_val(-1) 304 | op := decl_ref_expr.opcode // get_val(-2) 305 | mut add_par := false 306 | if op == 'operator<<' && typ.contains('basic_ostream') { 307 | c.gen('println(') 308 | add_par = true 309 | } else { 310 | // c.gen('op1 $op op2') 311 | } 312 | // vprintln('op="$op"') 313 | // decl_ref_expr2 := node.get(DeclRefExpr) 314 | // expr := decl_ref_expr2.get2() 315 | // expr := node.get2() 316 | expr := node.try_get_next_child() or { 317 | println(err) 318 | bad_node 319 | } 320 | // vprintln('<< EXPR $expr.typ') 321 | // vprintln(expr.vals) 322 | c.expr(expr) 323 | if add_par { 324 | c.gen(')') 325 | } 326 | } 327 | 328 | fn (mut c C2V) for_range(node &Node) { 329 | // mut node := unsafe { _node } 330 | // decl := node.get(DeclStmt) 331 | mut stmt := node.inner.last() 332 | // decls := node.find_children(DeclStmt) 333 | // decl:=decls.last() 334 | // var_name := j 335 | c.genln('for val in vals {') 336 | c.st_block_no_start(mut stmt) 337 | } 338 | -------------------------------------------------------------------------------- /src/node.v: -------------------------------------------------------------------------------- 1 | // To generate example AST JSON, that Node structure maps, 2 | // use clang -w -Xclang -ast-dump=json -fsyntax-only -fno-diagnostics-color -c 1.hello.c > ast.json command, for example. 3 | 4 | module main 5 | 6 | type Value = string | int 7 | 8 | // vfmt off 9 | struct Node { 10 | id string 11 | kind_str string @[json: 'kind'] // e.g. "IntegerLiteral" 12 | previous_declaration string @[json: 'previousDecl'] 13 | name string // e.g. "my_var_name" 14 | ast_type AstJsonType @[json: 'type'] 15 | class_modifier string @[json: 'storageClass'] 16 | tags string @[json: 'tagUsed'] 17 | initialization_type string @[json: 'init'] // "c" => "cinit" 18 | value Value @[json: 'value'] // For CharacterLiterals, since `value` is a number there, not at string 19 | opcode string // e.g. "+" in BinaryOperator 20 | ast_argument_type AstJsonType @[json: 'argType'] 21 | declaration_id string @[json: 'declId'] // for goto labels 22 | label_id string @[json: 'targetLabelDeclId'] // for goto statements 23 | is_postfix bool @[json: 'isPostfix'] 24 | mut: 25 | //parent_node &Node [skip] = unsafe {nil } 26 | location NodeLocation @[json: 'loc'] 27 | comment string @[skip] // comment string before this node 28 | unique_id int = -1 @[skip] 29 | range Range 30 | inner []Node 31 | array_filler []Node // for InitListExpr 32 | ref_declaration RefDeclarationNode @[json: 'referencedDecl'] //&Node 33 | kind NodeKind @[skip] 34 | current_child_id int @[skip] 35 | redeclarations_count int @[skip] // increased when some *other* Node had previous_decl == this Node.id 36 | owned_tag_decl OwnedTagDecl @[json: 'ownedTagDecl'] // for TagDecl nodes, to store the TagDecl node that is owned by this node 37 | } 38 | // vfmt on 39 | 40 | struct NodeLocation { 41 | mut: 42 | offset int 43 | file string @[json: 'file'] 44 | line int 45 | source_file SourceFile @[json: 'includedFrom'] 46 | spelling_file SourceFile @[json: 'spellingLoc'] 47 | file_index int = -1 48 | } 49 | 50 | struct Range { 51 | mut: 52 | begin Begin 53 | end End 54 | } 55 | 56 | struct Begin { 57 | mut: 58 | offset int 59 | spelling_file SourceFile @[json: 'spellingLoc'] 60 | expansion_file SourceFile @[json: 'expansionLoc'] 61 | } 62 | 63 | struct End { 64 | mut: 65 | offset int 66 | spelling_file SourceFile @[json: 'spellingLoc'] 67 | expansion_file SourceFile @[json: 'expansionLoc'] 68 | } 69 | 70 | struct SourceFile { 71 | offset int @[json: 'offset'] 72 | path string @[json: 'file'] 73 | } 74 | 75 | struct AstJsonType { 76 | desugared_qualified string @[json: 'desugaredQualType'] 77 | qualified string @[json: 'qualType'] 78 | } 79 | 80 | struct RefDeclarationNode { 81 | kind_str string @[json: 'kind'] // e.g. "IntegerLiteral" 82 | name string 83 | mut: 84 | kind NodeKind @[skip] 85 | } 86 | 87 | struct OwnedTagDecl { 88 | id string 89 | kind_str string @[json: 'kind'] 90 | name string 91 | } 92 | 93 | const bad_node = Node{ 94 | kind: .bad 95 | } 96 | 97 | fn (value Value) to_str() string { 98 | if value is int { 99 | return value.str() 100 | } else { 101 | return value as string 102 | } 103 | } 104 | 105 | fn (node Node) kindof(expected_kind NodeKind) bool { 106 | return node.kind == expected_kind 107 | } 108 | 109 | fn (node Node) has_child_of_kind(expected_kind NodeKind) bool { 110 | for child in node.inner { 111 | if child.kindof(expected_kind) { 112 | return true 113 | } 114 | } 115 | 116 | return false 117 | } 118 | 119 | fn (node Node) count_children_of_kind(kind_filter NodeKind) int { 120 | mut count := 0 121 | 122 | for child in node.inner { 123 | if child.kindof(kind_filter) { 124 | count++ 125 | } 126 | } 127 | 128 | return count 129 | } 130 | 131 | fn (node Node) find_children(wanted_kind NodeKind) []Node { 132 | mut suitable_children := []Node{} 133 | 134 | if node.inner.len == 0 { 135 | return suitable_children 136 | } 137 | 138 | for child in node.inner { 139 | if child.kindof(wanted_kind) { 140 | suitable_children << child 141 | } 142 | } 143 | 144 | return suitable_children 145 | } 146 | 147 | fn (mut node Node) try_get_next_child_of_kind(wanted_kind NodeKind) !Node { 148 | if node.current_child_id >= node.inner.len { 149 | return error('No more children') 150 | } 151 | 152 | mut current_child := node.inner[node.current_child_id] 153 | 154 | if current_child.kindof(wanted_kind) == false { 155 | error('try_get_next_child_of_kind(): WANTED ${wanted_kind.str()} BUT GOT ${current_child.kind.str()}') 156 | } 157 | 158 | node.current_child_id++ 159 | 160 | return current_child 161 | } 162 | 163 | fn (mut node Node) try_get_next_child() !Node { 164 | if node.current_child_id >= node.inner.len { 165 | return error('No more children') 166 | } 167 | 168 | current_child := node.inner[node.current_child_id] 169 | node.current_child_id++ 170 | 171 | return current_child 172 | } 173 | 174 | fn (mut node Node) initialize_node_and_children() { 175 | node.kind = convert_str_into_node_kind(node.kind_str) 176 | 177 | for mut child in node.inner { 178 | child.initialize_node_and_children() 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/node_kind.v: -------------------------------------------------------------------------------- 1 | // Since C2V uses Clang AST to "parse" C code and output of this parse step is a JSON file that describes code "nodes", 2 | // names of nodes from this JSON are converted into enum form to simplify working on a code level. 3 | // 4 | // This file contains 2 main things - constant str_to_node_kind_map and NodeKind enum declaration itself. 5 | // str_to_node_kind_map contains data pairs, so to add a new node that C2V should support, 6 | // simply define a new member of NodeKind enum (that is snake_case name of node) and add it to str_to_node_kind_map. 7 | // 8 | // You can also generate NodeKind enum and str_to_node_kind_map map code. See tools/node_kind_gen/gen_node_kind_code.v for details. 9 | 10 | module main 11 | 12 | // Take into account that members of this enum are sorted alphabetically A -> Z, but 'bad' value is on the top. 13 | // Use this style when defining a new record. 14 | enum NodeKind { 15 | bad // is used only inside a C2V to mark unknown or corrupted node. 16 | access_spec_decl 17 | acquire_capability_attr 18 | addr_label_expr 19 | aligned_attr 20 | alloc_size_attr 21 | always_inline_attr 22 | analyzer_no_return_attr 23 | array_filler 24 | array_subscript_expr 25 | asm_label_attr 26 | assert_exclusive_lock_attr 27 | atomic_expr 28 | availability_attr 29 | binary_operator 30 | block_command_comment 31 | block_expr 32 | break_stmt 33 | builtin_template_decl 34 | builtin_type 35 | call_expr 36 | capability_attr 37 | case_stmt 38 | character_literal 39 | class_decl 40 | class_template 41 | class_template_decl 42 | class_template_partial_specialization 43 | class_template_partial_specialization_decl 44 | class_template_specialization 45 | class_template_specialization_decl 46 | cold_attr 47 | compound_assign_operator 48 | compound_literal_expr 49 | compound_stmt 50 | conditional_operator 51 | constant_array_type 52 | constant_expr 53 | const_attr 54 | continue_stmt 55 | c_style_cast_expr 56 | cx_cursor_kind 57 | cxx 58 | cxx_access_specifier 59 | cxx_bind_temporary_expr 60 | cxx_bool_literal_expr 61 | cxx_catch_stmt 62 | cxx_const_cast_expr 63 | cxx_construct_expr 64 | cxx_constructor 65 | cxx_constructor_decl 66 | cxx_conversion 67 | cxx_conversion_decl 68 | cxx_ctor_initializer 69 | cxx_default_arg_expr 70 | cxx_default_init_expr 71 | cxx_delete_expr 72 | cxx_dependent_scope_member_expr 73 | cxx_destructor 74 | cxx_destructor_decl 75 | cxx_dynamic_cast_expr 76 | cxx_for_range_stmt 77 | cxx_functional_cast_expr 78 | cxx_member_call_expr 79 | cxx_method 80 | cxx_method_decl 81 | cxx_new_expr 82 | cxx_noexcept_expr 83 | cxx_null_ptr_literal_expr 84 | cxx_operator_call_expr 85 | cxx_pseudo_destructor_expr 86 | cxx_record 87 | cxx_record_decl 88 | cxx_reinterpret_cast_expr 89 | cxx_scalar_value_init_expr 90 | cxx_static_cast_expr 91 | cxx_temporary_object_expr 92 | cxx_this_expr 93 | cxx_throw_expr 94 | cxx_try_stmt 95 | cxx_typeid_expr 96 | cxx_unresolved_construct_expr 97 | decayed_type 98 | decl_ref_expr 99 | decl_stmt 100 | decltype_type 101 | default_stmt 102 | dependent_name_type 103 | dependent_scope_decl_ref_expr 104 | dependent_template_specialization_type 105 | deprecated_attr 106 | diagnose_if_attr 107 | disable_tail_calls_attr 108 | do_stmt 109 | elaborated_type 110 | enable_if_attr 111 | @enum 112 | enum_constant_decl 113 | enum_decl 114 | enum_type 115 | expr_with_cleanups 116 | field 117 | field_decl 118 | fixed_point_literal 119 | floating_literal 120 | format_arg_attr 121 | format_attr 122 | for_stmt 123 | friend_decl 124 | full_comment 125 | function 126 | function_decl 127 | function_no_proto_type 128 | function_proto_type 129 | function_template 130 | function_template_decl 131 | gcc_asm_stmt 132 | generic_selection_expr 133 | gnu_null_expr 134 | goto_stmt 135 | guarded_by_attr 136 | html_end_tag_comment 137 | html_start_tag_comment 138 | if_stmt 139 | imaginary_literal 140 | implicit_cast_expr 141 | implicit_value_init_expr 142 | incomplete_array_type 143 | indirect_field_decl 144 | indirect_goto_stmt 145 | init_list_expr 146 | injected_class_name_type 147 | inline_command_comment 148 | integer_literal 149 | invalid_code 150 | invalid_file 151 | label_ref 152 | label_stmt 153 | lambda_expr 154 | linkage_spec 155 | linkage_spec_decl 156 | l_value_reference_type 157 | materialize_temporary_expr 158 | max_field_alignment_attr 159 | member_expr 160 | member_pointer_type 161 | member_ref 162 | member_ref_expr 163 | module_import 164 | ms_asm_stmt 165 | namespace 166 | namespace_alias 167 | namespace_decl 168 | namespace_ref 169 | no_decl_found 170 | no_escape_attr 171 | no_inline_attr 172 | non_type_template_parameter 173 | non_type_template_parm_decl 174 | no_sanitize_attr 175 | no_throw_attr 176 | not_implemented 177 | null 178 | null_stmt 179 | obj_c_at_catch_stmt 180 | obj_c_at_finally_stmt 181 | obj_c_at_synchronized_stmt 182 | obj_c_at_throw_stmt 183 | obj_c_at_try_stmt 184 | obj_c_autorelease_pool_stmt 185 | obj_c_availability_check_expr 186 | obj_c_bool_literal_expr 187 | obj_c_bridged_cast_expr 188 | obj_c_category_decl 189 | obj_c_category_impl_decl 190 | obj_c_class_method_decl 191 | obj_c_class_ref 192 | obj_c_dynamic_decl 193 | obj_c_encode_expr 194 | obj_c_for_collection_stmt 195 | obj_c_implementation_decl 196 | obj_c_instance_method_decl 197 | obj_c_interface_decl 198 | obj_c_ivar_decl 199 | obj_c_message_expr 200 | obj_c_property_decl 201 | obj_c_protocol_decl 202 | obj_c_protocol_expr 203 | obj_c_protocol_ref 204 | obj_c_selector_expr 205 | obj_c_self_expr 206 | obj_c_string_literal 207 | obj_c_super_class_ref 208 | obj_c_synthesize_decl 209 | offset_of_expr 210 | omp_array_section_expr 211 | omp_atomic_directive 212 | omp_barrier_directive 213 | omp_cancel_directive 214 | omp_cancellation_point_directive 215 | omp_critical_directive 216 | omp_distribute_directive 217 | omp_distribute_parallel_for_directive 218 | omp_distribute_parallel_for_simd_directive 219 | omp_distribute_simd_directive 220 | omp_flush_directive 221 | omp_for_directive 222 | omp_for_simd_directive 223 | omp_master_directive 224 | omp_ordered_directive 225 | omp_parallel_directive 226 | omp_parallel_for_directive 227 | omp_parallel_for_simd_directive 228 | omp_parallel_sections_directive 229 | omp_section_directive 230 | omp_sections_directive 231 | omp_simd_directive 232 | omp_single_directive 233 | omp_target_data_directive 234 | omp_target_directive 235 | omp_target_enter_data_directive 236 | omp_target_exit_data_directive 237 | omp_target_parallel_directive 238 | omp_target_parallel_for_directive 239 | omp_target_parallel_for_simd_directive 240 | omp_target_simd_directive 241 | omp_target_teams_directive 242 | omp_target_teams_distribute_directive 243 | omp_target_teams_distribute_parallel_for_directive 244 | omp_target_teams_distribute_parallel_for_simd_directive 245 | omp_target_teams_distribute_simd_directive 246 | omp_target_update_directive 247 | omp_task_directive 248 | omp_taskgroup_directive 249 | omp_task_loop_directive 250 | omp_task_loop_simd_directive 251 | omp_taskwait_directive 252 | omp_taskyield_directive 253 | omp_teams_directive 254 | omp_teams_distribute_directive 255 | omp_teams_distribute_parallel_for_directive 256 | omp_teams_distribute_parallel_for_simd_directive 257 | omp_teams_distribute_simd_directive 258 | opaque_value_expr 259 | original 260 | overload_candidate 261 | overloaded_decl_ref 262 | override_attr 263 | overrides 264 | packed_attr 265 | pack_expansion_expr 266 | pack_expansion_type 267 | paragraph_comment 268 | paren_expr 269 | paren_list_expr 270 | paren_type 271 | parm_decl 272 | parm_var_decl 273 | pointer_type 274 | predefined_expr 275 | private 276 | protected 277 | public 278 | pure_attr 279 | qual_type 280 | record 281 | record_decl 282 | record_type 283 | release_capability_attr 284 | requires_capability_attr 285 | restrict_attr 286 | return_stmt 287 | returns_twice_attr 288 | ruct 289 | r_value_reference_type 290 | scoped_lockable_attr 291 | seh_except_stmt 292 | seh_finally_stmt 293 | seh_leave_stmt 294 | seh_try_stmt 295 | size_of_pack_expr 296 | static_assert 297 | static_assert_decl 298 | stmt_expr 299 | string_literal 300 | struct_decl 301 | subst_non_type_template_parm_expr 302 | subst_template_type_parm_type 303 | switch_stmt 304 | template_argument 305 | template_ref 306 | template_specialization_type 307 | template_template_parameter 308 | template_template_parm_decl 309 | template_type_parameter 310 | template_type_parm 311 | template_type_parm_decl 312 | template_type_parm_type 313 | text_comment 314 | translation_unit 315 | translation_unit_decl 316 | type_alias_decl 317 | type_alias_template_decl 318 | typedef 319 | typedef_decl 320 | typedef_type 321 | type_ref 322 | type_visibility_attr 323 | unary_expr 324 | unary_expr_or_type_trait_expr 325 | unary_operator 326 | unary_transform_type 327 | unexposed_attr 328 | unexposed_decl 329 | unexposed_expr 330 | unexposed_stmt 331 | unhandled 332 | union_decl 333 | unresolved_lookup_expr 334 | unresolved_member_expr 335 | unused_attr 336 | using_decl 337 | using_declaration 338 | using_directive 339 | using_directive_decl 340 | using_shadow_decl 341 | va_arg_expr 342 | var_decl 343 | variable_ref 344 | virtual 345 | visibility_attr 346 | warn_unused_result_attr 347 | while_stmt 348 | } 349 | 350 | // Take into account that records of this map are sorted alphabetically A -> Z, but 'bad' value is on the top. 351 | // Use this style when defining a new record. 352 | const str_to_node_kind_map = { 353 | 'BAD': NodeKind.bad // is used only inside a C2V to mark unknown or corrupted node. 354 | 'AccessSpecDecl': .access_spec_decl 355 | 'AcquireCapabilityAttr': .acquire_capability_attr 356 | 'AddrLabelExpr': .addr_label_expr 357 | 'AlignedAttr': .aligned_attr 358 | 'AllocSizeAttr': .alloc_size_attr 359 | 'AlwaysInlineAttr': .always_inline_attr 360 | 'AnalyzerNoReturnAttr': .analyzer_no_return_attr 361 | 'ArrayFiller': .array_filler 362 | 'ArraySubscriptExpr': .array_subscript_expr 363 | 'AsmLabelAttr': .asm_label_attr 364 | 'AssertExclusiveLockAttr': .assert_exclusive_lock_attr 365 | 'AtomicExpr': .atomic_expr 366 | 'AvailabilityAttr': .availability_attr 367 | 'BinaryOperator': .binary_operator 368 | 'BlockCommandComment': .block_command_comment 369 | 'BlockExpr': .block_expr 370 | 'BreakStmt': .break_stmt 371 | 'BuiltinTemplateDecl': .builtin_template_decl 372 | 'BuiltinType': .builtin_type 373 | 'CallExpr': .call_expr 374 | 'CapabilityAttr': .capability_attr 375 | 'CaseStmt': .case_stmt 376 | 'CharacterLiteral': .character_literal 377 | 'ClassDecl': .class_decl 378 | 'ClassTemplate': .class_template 379 | 'ClassTemplateDecl': .class_template_decl 380 | 'ClassTemplatePartialSpecialization': .class_template_partial_specialization 381 | 'ClassTemplatePartialSpecializationDecl': .class_template_partial_specialization_decl 382 | 'ClassTemplateSpecialization': .class_template_specialization 383 | 'ClassTemplateSpecializationDecl': .class_template_specialization_decl 384 | 'ColdAttr': .cold_attr 385 | 'CompoundAssignOperator': .compound_assign_operator 386 | 'CompoundLiteralExpr': .compound_literal_expr 387 | 'CompoundStmt': .compound_stmt 388 | 'ConditionalOperator': .conditional_operator 389 | 'ConstantArrayType': .constant_array_type 390 | 'ConstantExpr': .constant_expr 391 | 'ConstAttr': .const_attr 392 | 'ContinueStmt': .continue_stmt 393 | 'CStyleCastExpr': .c_style_cast_expr 394 | 'CXCursorKind': .cx_cursor_kind 395 | 'CXX': .cxx 396 | 'CXXAccessSpecifier': .cxx_access_specifier 397 | 'CXXBindTemporaryExpr': .cxx_bind_temporary_expr 398 | 'CXXBoolLiteralExpr': .cxx_bool_literal_expr 399 | 'CXXCatchStmt': .cxx_catch_stmt 400 | 'CXXConstCastExpr': .cxx_const_cast_expr 401 | 'CXXConstructExpr': .cxx_construct_expr 402 | 'CXXConstructor': .cxx_constructor 403 | 'CXXConstructorDecl': .cxx_constructor_decl 404 | 'CXXConversion': .cxx_conversion 405 | 'CXXConversionDecl': .cxx_conversion_decl 406 | 'CXXCtorInitializer': .cxx_ctor_initializer 407 | 'CXXDefaultArgExpr': .cxx_default_arg_expr 408 | 'CXXDefaultInitExpr': .cxx_default_init_expr 409 | 'CXXDeleteExpr': .cxx_delete_expr 410 | 'CXXDependentScopeMemberExpr': .cxx_dependent_scope_member_expr 411 | 'CXXDestructor': .cxx_destructor 412 | 'CXXDestructorDecl': .cxx_destructor_decl 413 | 'CXXDynamicCastExpr': .cxx_dynamic_cast_expr 414 | 'CXXForRangeStmt': .cxx_for_range_stmt 415 | 'CXXFunctionalCastExpr': .cxx_functional_cast_expr 416 | 'CXXMemberCallExpr': .cxx_member_call_expr 417 | 'CXXMethod': .cxx_method 418 | 'CXXMethodDecl': .cxx_method_decl 419 | 'CXXNewExpr': .cxx_new_expr 420 | 'CXXNoexceptExpr': .cxx_noexcept_expr 421 | 'CXXNullPtrLiteralExpr': .cxx_null_ptr_literal_expr 422 | 'CXXOperatorCallExpr': .cxx_operator_call_expr 423 | 'CXXPseudoDestructorExpr': .cxx_pseudo_destructor_expr 424 | 'CXXRecord': .cxx_record 425 | 'CXXRecordDecl': .cxx_record_decl 426 | 'CXXReinterpretCastExpr': .cxx_reinterpret_cast_expr 427 | 'CXXScalarValueInitExpr': .cxx_scalar_value_init_expr 428 | 'CXXStaticCastExpr': .cxx_static_cast_expr 429 | 'CXXTemporaryObjectExpr': .cxx_temporary_object_expr 430 | 'CXXThisExpr': .cxx_this_expr 431 | 'CXXThrowExpr': .cxx_throw_expr 432 | 'CXXTryStmt': .cxx_try_stmt 433 | 'CXXTypeidExpr': .cxx_typeid_expr 434 | 'CXXUnresolvedConstructExpr': .cxx_unresolved_construct_expr 435 | 'DecayedType': .decayed_type 436 | 'DeclRefExpr': .decl_ref_expr 437 | 'DeclStmt': .decl_stmt 438 | 'DecltypeType': .decltype_type 439 | 'DefaultStmt': .default_stmt 440 | 'DependentNameType': .dependent_name_type 441 | 'DependentScopeDeclRefExpr': .dependent_scope_decl_ref_expr 442 | 'DependentTemplateSpecializationType': .dependent_template_specialization_type 443 | 'DeprecatedAttr': .deprecated_attr 444 | 'DiagnoseIfAttr': .diagnose_if_attr 445 | 'DisableTailCallsAttr': .disable_tail_calls_attr 446 | 'DoStmt': .do_stmt 447 | 'ElaboratedType': .elaborated_type 448 | 'EnableIfAttr': .enable_if_attr 449 | 'Enum': .@enum 450 | 'EnumConstantDecl': .enum_constant_decl 451 | 'EnumDecl': .enum_decl 452 | 'EnumType': .enum_type 453 | 'ExprWithCleanups': .expr_with_cleanups 454 | 'Field': .field 455 | 'FieldDecl': .field_decl 456 | 'FixedPointLiteral': .fixed_point_literal 457 | 'FloatingLiteral': .floating_literal 458 | 'FormatArgAttr': .format_arg_attr 459 | 'FormatAttr': .format_attr 460 | 'ForStmt': .for_stmt 461 | 'FriendDecl': .friend_decl 462 | 'FullComment': .full_comment 463 | 'Function': .function 464 | 'FunctionDecl': .function_decl 465 | 'FunctionNoProtoType': .function_no_proto_type 466 | 'FunctionProtoType': .function_proto_type 467 | 'FunctionTemplate': .function_template 468 | 'FunctionTemplateDecl': .function_template_decl 469 | 'GCCAsmStmt': .gcc_asm_stmt 470 | 'GenericSelectionExpr': .generic_selection_expr 471 | 'GNUNullExpr': .gnu_null_expr 472 | 'GotoStmt': .goto_stmt 473 | 'GuardedByAttr': .guarded_by_attr 474 | 'HTMLEndTagComment': .html_end_tag_comment 475 | 'HTMLStartTagComment': .html_start_tag_comment 476 | 'IfStmt': .if_stmt 477 | 'ImaginaryLiteral': .imaginary_literal 478 | 'ImplicitCastExpr': .implicit_cast_expr 479 | 'ImplicitValueInitExpr': .implicit_value_init_expr 480 | 'IncompleteArrayType': .incomplete_array_type 481 | 'IndirectFieldDecl': .indirect_field_decl 482 | 'IndirectGotoStmt': .indirect_goto_stmt 483 | 'InitListExpr': .init_list_expr 484 | 'InjectedClassNameType': .injected_class_name_type 485 | 'InlineCommandComment': .inline_command_comment 486 | 'IntegerLiteral': .integer_literal 487 | 'InvalidCode': .invalid_code 488 | 'InvalidFile': .invalid_file 489 | 'LabelRef': .label_ref 490 | 'LabelStmt': .label_stmt 491 | 'LambdaExpr': .lambda_expr 492 | 'LinkageSpec': .linkage_spec 493 | 'LinkageSpecDecl': .linkage_spec_decl 494 | 'LValueReferenceType': .l_value_reference_type 495 | 'MaterializeTemporaryExpr': .materialize_temporary_expr 496 | 'MaxFieldAlignmentAttr': .max_field_alignment_attr 497 | 'MemberExpr': .member_expr 498 | 'MemberPointerType': .member_pointer_type 499 | 'MemberRef': .member_ref 500 | 'MemberRefExpr': .member_ref_expr 501 | 'ModuleImport': .module_import 502 | 'MSAsmStmt': .ms_asm_stmt 503 | 'Namespace': .namespace 504 | 'NamespaceAlias': .namespace_alias 505 | 'NamespaceDecl': .namespace_decl 506 | 'NamespaceRef': .namespace_ref 507 | 'NoDeclFound': .no_decl_found 508 | 'NoEscapeAttr': .no_escape_attr 509 | 'NoInlineAttr': .no_inline_attr 510 | 'NonTypeTemplateParameter': .non_type_template_parameter 511 | 'NonTypeTemplateParmDecl': .non_type_template_parm_decl 512 | 'NoSanitizeAttr': .no_sanitize_attr 513 | 'NoThrowAttr': .no_throw_attr 514 | 'NotImplemented': .not_implemented 515 | 'Null': .null 516 | 'NullStmt': .null_stmt 517 | 'ObjCAtCatchStmt': .obj_c_at_catch_stmt 518 | 'ObjCAtFinallyStmt': .obj_c_at_finally_stmt 519 | 'ObjCAtSynchronizedStmt': .obj_c_at_synchronized_stmt 520 | 'ObjCAtThrowStmt': .obj_c_at_throw_stmt 521 | 'ObjCAtTryStmt': .obj_c_at_try_stmt 522 | 'ObjCAutoreleasePoolStmt': .obj_c_autorelease_pool_stmt 523 | 'ObjCAvailabilityCheckExpr': .obj_c_availability_check_expr 524 | 'ObjCBoolLiteralExpr': .obj_c_bool_literal_expr 525 | 'ObjCBridgedCastExpr': .obj_c_bridged_cast_expr 526 | 'ObjCCategoryDecl': .obj_c_category_decl 527 | 'ObjCCategoryImplDecl': .obj_c_category_impl_decl 528 | 'ObjCClassMethodDecl': .obj_c_class_method_decl 529 | 'ObjCClassRef': .obj_c_class_ref 530 | 'ObjCDynamicDecl': .obj_c_dynamic_decl 531 | 'ObjCEncodeExpr': .obj_c_encode_expr 532 | 'ObjCForCollectionStmt': .obj_c_for_collection_stmt 533 | 'ObjCImplementationDecl': .obj_c_implementation_decl 534 | 'ObjCInstanceMethodDecl': .obj_c_instance_method_decl 535 | 'ObjCInterfaceDecl': .obj_c_interface_decl 536 | 'ObjCIvarDecl': .obj_c_ivar_decl 537 | 'ObjCMessageExpr': .obj_c_message_expr 538 | 'ObjCPropertyDecl': .obj_c_property_decl 539 | 'ObjCProtocolDecl': .obj_c_protocol_decl 540 | 'ObjCProtocolExpr': .obj_c_protocol_expr 541 | 'ObjCProtocolRef': .obj_c_protocol_ref 542 | 'ObjCSelectorExpr': .obj_c_selector_expr 543 | 'ObjCSelfExpr': .obj_c_self_expr 544 | 'ObjCStringLiteral': .obj_c_string_literal 545 | 'ObjCSuperClassRef': .obj_c_super_class_ref 546 | 'ObjCSynthesizeDecl': .obj_c_synthesize_decl 547 | 'OffsetOfExpr': .offset_of_expr 548 | 'OMPArraySectionExpr': .omp_array_section_expr 549 | 'OMPAtomicDirective': .omp_atomic_directive 550 | 'OMPBarrierDirective': .omp_barrier_directive 551 | 'OMPCancelDirective': .omp_cancel_directive 552 | 'OMPCancellationPointDirective': .omp_cancellation_point_directive 553 | 'OMPCriticalDirective': .omp_critical_directive 554 | 'OMPDistributeDirective': .omp_distribute_directive 555 | 'OMPDistributeParallelForDirective': .omp_distribute_parallel_for_directive 556 | 'OMPDistributeParallelForSimdDirective': .omp_distribute_parallel_for_simd_directive 557 | 'OMPDistributeSimdDirective': .omp_distribute_simd_directive 558 | 'OMPFlushDirective': .omp_flush_directive 559 | 'OMPForDirective': .omp_for_directive 560 | 'OMPForSimdDirective': .omp_for_simd_directive 561 | 'OMPMasterDirective': .omp_master_directive 562 | 'OMPOrderedDirective': .omp_ordered_directive 563 | 'OMPParallelDirective': .omp_parallel_directive 564 | 'OMPParallelForDirective': .omp_parallel_for_directive 565 | 'OMPParallelForSimdDirective': .omp_parallel_for_simd_directive 566 | 'OMPParallelSectionsDirective': .omp_parallel_sections_directive 567 | 'OMPSectionDirective': .omp_section_directive 568 | 'OMPSectionsDirective': .omp_sections_directive 569 | 'OMPSimdDirective': .omp_simd_directive 570 | 'OMPSingleDirective': .omp_single_directive 571 | 'OMPTargetDataDirective': .omp_target_data_directive 572 | 'OMPTargetDirective': .omp_target_directive 573 | 'OMPTargetEnterDataDirective': .omp_target_enter_data_directive 574 | 'OMPTargetExitDataDirective': .omp_target_exit_data_directive 575 | 'OMPTargetParallelDirective': .omp_target_parallel_directive 576 | 'OMPTargetParallelForDirective': .omp_target_parallel_for_directive 577 | 'OMPTargetParallelForSimdDirective': .omp_target_parallel_for_simd_directive 578 | 'OMPTargetSimdDirective': .omp_target_simd_directive 579 | 'OMPTargetTeamsDirective': .omp_target_teams_directive 580 | 'OMPTargetTeamsDistributeDirective': .omp_target_teams_distribute_directive 581 | 'OMPTargetTeamsDistributeParallelForDirective': .omp_target_teams_distribute_parallel_for_directive 582 | 'OMPTargetTeamsDistributeParallelForSimdDirective': .omp_target_teams_distribute_parallel_for_simd_directive 583 | 'OMPTargetTeamsDistributeSimdDirective': .omp_target_teams_distribute_simd_directive 584 | 'OMPTargetUpdateDirective': .omp_target_update_directive 585 | 'OMPTaskDirective': .omp_task_directive 586 | 'OMPTaskgroupDirective': .omp_taskgroup_directive 587 | 'OMPTaskLoopDirective': .omp_task_loop_directive 588 | 'OMPTaskLoopSimdDirective': .omp_task_loop_simd_directive 589 | 'OMPTaskwaitDirective': .omp_taskwait_directive 590 | 'OMPTaskyieldDirective': .omp_taskyield_directive 591 | 'OMPTeamsDirective': .omp_teams_directive 592 | 'OMPTeamsDistributeDirective': .omp_teams_distribute_directive 593 | 'OMPTeamsDistributeParallelForDirective': .omp_teams_distribute_parallel_for_directive 594 | 'OMPTeamsDistributeParallelForSimdDirective': .omp_teams_distribute_parallel_for_simd_directive 595 | 'OMPTeamsDistributeSimdDirective': .omp_teams_distribute_simd_directive 596 | 'OpaqueValueExpr': .opaque_value_expr 597 | 'original': .original 598 | 'OverloadCandidate': .overload_candidate 599 | 'OverloadedDeclRef': .overloaded_decl_ref 600 | 'OverrideAttr': .override_attr 601 | 'Overrides': .overrides 602 | 'PackedAttr': .packed_attr 603 | 'PackExpansionExpr': .pack_expansion_expr 604 | 'PackExpansionType': .pack_expansion_type 605 | 'ParagraphComment': .paragraph_comment 606 | 'ParenExpr': .paren_expr 607 | 'ParenListExpr': .paren_list_expr 608 | 'ParenType': .paren_type 609 | 'ParmDecl': .parm_decl 610 | 'ParmVarDecl': .parm_var_decl 611 | 'PointerType': .pointer_type 612 | 'PredefinedExpr': .predefined_expr 613 | 'private': .private 614 | 'protected': .protected 615 | 'public': .public 616 | 'PureAttr': .pure_attr 617 | 'QualType': .qual_type 618 | 'Record': .record 619 | 'RecordDecl': .record_decl 620 | 'RecordType': .record_type 621 | 'ReleaseCapabilityAttr': .release_capability_attr 622 | 'RequiresCapabilityAttr': .requires_capability_attr 623 | 'RestrictAttr': .restrict_attr 624 | 'ReturnStmt': .return_stmt 625 | 'ReturnsTwiceAttr': .returns_twice_attr 626 | 'ruct': .ruct 627 | 'RValueReferenceType': .r_value_reference_type 628 | 'ScopedLockableAttr': .scoped_lockable_attr 629 | 'SEHExceptStmt': .seh_except_stmt 630 | 'SEHFinallyStmt': .seh_finally_stmt 631 | 'SEHLeaveStmt': .seh_leave_stmt 632 | 'SEHTryStmt': .seh_try_stmt 633 | 'SizeOfPackExpr': .size_of_pack_expr 634 | 'StaticAssert': .static_assert 635 | 'StaticAssertDecl': .static_assert_decl 636 | 'StmtExpr': .stmt_expr 637 | 'StringLiteral': .string_literal 638 | 'StructDecl': .struct_decl 639 | 'SubstNonTypeTemplateParmExpr': .subst_non_type_template_parm_expr 640 | 'SubstTemplateTypeParmType': .subst_template_type_parm_type 641 | 'SwitchStmt': .switch_stmt 642 | 'TemplateArgument': .template_argument 643 | 'TemplateRef': .template_ref 644 | 'TemplateSpecializationType': .template_specialization_type 645 | 'TemplateTemplateParameter': .template_template_parameter 646 | 'TemplateTemplateParmDecl': .template_template_parm_decl 647 | 'TemplateTypeParameter': .template_type_parameter 648 | 'TemplateTypeParm': .template_type_parm 649 | 'TemplateTypeParmDecl': .template_type_parm_decl 650 | 'TemplateTypeParmType': .template_type_parm_type 651 | 'TextComment': .text_comment 652 | 'TranslationUnit': .translation_unit 653 | 'TranslationUnitDecl': .translation_unit_decl 654 | 'TypeAliasDecl': .type_alias_decl 655 | 'TypeAliasTemplateDecl': .type_alias_template_decl 656 | 'Typedef': .typedef 657 | 'TypedefDecl': .typedef_decl 658 | 'TypedefType': .typedef_type 659 | 'TypeRef': .type_ref 660 | 'TypeVisibilityAttr': .type_visibility_attr 661 | 'UnaryExpr': .unary_expr 662 | 'UnaryExprOrTypeTraitExpr': .unary_expr_or_type_trait_expr 663 | 'UnaryOperator': .unary_operator 664 | 'UnaryTransformType': .unary_transform_type 665 | 'UnexposedAttr': .unexposed_attr 666 | 'UnexposedDecl': .unexposed_decl 667 | 'UnexposedExpr': .unexposed_expr 668 | 'UnexposedStmt': .unexposed_stmt 669 | 'Unhandled': .unhandled 670 | 'UnionDecl': .union_decl 671 | 'UnresolvedLookupExpr': .unresolved_lookup_expr 672 | 'UnresolvedMemberExpr': .unresolved_member_expr 673 | 'UnusedAttr': .unused_attr 674 | 'UsingDecl': .using_decl 675 | 'UsingDeclaration': .using_declaration 676 | 'UsingDirective': .using_directive 677 | 'UsingDirectiveDecl': .using_directive_decl 678 | 'UsingShadowDecl': .using_shadow_decl 679 | 'VAArgExpr': .va_arg_expr 680 | 'VarDecl': .var_decl 681 | 'VariableRef': .variable_ref 682 | 'virtual': .virtual 683 | 'VisibilityAttr': .visibility_attr 684 | 'WarnUnusedResultAttr': .warn_unused_result_attr 685 | 'WhileStmt': .while_stmt 686 | } 687 | 688 | // Reverse process is done in a runtime, so this map always contains correct data. 689 | // We are using reversed str_to_node_kind_map to implement NodeKind.str() method. 690 | const node_kind_to_str_map = reverse_str_to_node_kind_map() 691 | 692 | // Use this method when you want to convert a node's name into NodeKind enum form. 693 | // ATTENTION: the 'value' parameter is case sensitive! 694 | // 695 | // Example: 696 | // convert_str_into_node_kind('AccessSpecDecl') -> NodeKind.access_spec_decl 697 | // convert_str_into_node_kind('access_spec_decl') -> NodeKind.bad 698 | // convert_str_into_node_kind('RANDOM123_NOT_EXISTS') -> NodeKind.bad 699 | pub fn convert_str_into_node_kind(value string) NodeKind { 700 | return str_to_node_kind_map[value] or { NodeKind.bad } 701 | } 702 | 703 | // ATTENTION: NodeKind string form - is the original name of a node, generated by Clang AST, 704 | // not a 'node_kind_enum_member_name'. 705 | // 706 | // Example: 707 | // NodeKind.access_spec_decl.str() -> 'AccessSpecDecl' 708 | pub fn (kind NodeKind) str() string { 709 | return node_kind_to_str_map[kind] 710 | } 711 | 712 | fn reverse_str_to_node_kind_map() map[NodeKind]string { 713 | mut reversed_map := map[NodeKind]string{} 714 | 715 | for key, value in str_to_node_kind_map { 716 | reversed_map[value] = key 717 | } 718 | 719 | return reversed_map 720 | } 721 | -------------------------------------------------------------------------------- /src/struct.v: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | import strings 4 | 5 | // |-RecordDecl 0x7fd7c302c560 line:3:8 struct User definition 6 | fn (mut c C2V) record_decl(node &Node) { 7 | vprintln('record_decl("${node.name}")') 8 | // Skip empty structs (extern or forward decls) 9 | if node.kindof(.record_decl) && node.inner.len == 0 { 10 | return 11 | } 12 | mut c_name := node.name 13 | // Dont generate struct header if it was already generated by typedef 14 | // Confusing, but typedefs in C AST are really messy. 15 | // ... 16 | // If the struct has no name, then it's `typedef struct { ... } name` 17 | // AST: 1) RecordDecl struct definition 2) TypedefDecl struct name 18 | if c.tree.inner.len > c.node_i + 1 { 19 | next_node := c.tree.inner[c.node_i + 1] 20 | if next_node.kind == .typedef_decl { 21 | if c.is_verbose { 22 | c.genln('// typedef struct') 23 | } 24 | c_name = next_node.name 25 | if c_name.contains('apthing_t') { 26 | vprintln(node.str()) 27 | } 28 | } 29 | } 30 | 31 | if c_name in builtin_type_names { 32 | return 33 | } 34 | if c.is_verbose { 35 | c.genln('// struct decl name="${c_name}"') 36 | } 37 | if c_name in c.types { 38 | if node.previous_declaration == '' { 39 | return 40 | } 41 | } 42 | // Anonymous struct, most likely the next node is a vardecl with this anon struct type, so remember it 43 | if c_name == '' { 44 | c_name = 'AnonStruct_${node.location.line}' 45 | c.last_declared_type_name = c_name 46 | } 47 | if c_name !in ['struct', 'union'] { 48 | v_name := c.add_struct_name(mut c.types, c_name) 49 | // prevent duplicate generations: 50 | if v_name in c.generated_declarations { 51 | return 52 | } 53 | c.generated_declarations[v_name] = true 54 | if node.tags.contains('union') { 55 | c.genln('union ${v_name} { ') 56 | } else { 57 | c.genln('struct ${v_name} { ') 58 | } 59 | } 60 | mut new_struct := Struct{} 61 | // in V it's `field struct {...}`, but in C we get struct definition first, so save it and use it in the 62 | // next child 63 | mut anon_struct_definition := '' 64 | for field in node.inner { 65 | c.gen_comment(field) 66 | // Handle anon structs 67 | if field.kind == .record_decl { 68 | anon_struct_definition = c.anon_struct_field_type(field) 69 | continue 70 | } 71 | // There may be comments, skip them 72 | if field.kind != .field_decl { 73 | continue 74 | } 75 | field_type := convert_type(field.ast_type.qualified) 76 | field_name := filter_name(field.name, false).uncapitalize() 77 | mut field_type_name := field_type.name 78 | 79 | // Handle anon structs, the anonymous struct has just been defined above, use its definition 80 | if field_type_name.contains('unnamed at') { 81 | field_type_name = anon_struct_definition 82 | } 83 | if field_type_name.contains('anonymous at') { 84 | continue 85 | } 86 | /* 87 | if field_type.name.contains('union') { 88 | continue // TODO 89 | } 90 | */ 91 | new_struct.fields << field_name 92 | if field_type.name.ends_with('_s') { // TODO doom _t _s hack, remove 93 | n := field_type.name[..field_type.name.len - 2] + '_t' 94 | c.genln('\t${field_name} ${n}') 95 | } else { 96 | c.genln('\t${field_name} ${field_type_name}') 97 | } 98 | } 99 | c.structs[c_name] = new_struct 100 | c.genln('}') 101 | } 102 | 103 | fn (mut c C2V) anon_struct_field_type(node &Node) string { 104 | mut sb := strings.new_builder(50) 105 | sb.write_string(' struct {') 106 | for field in node.inner { 107 | if field.kind != .field_decl { 108 | continue 109 | } 110 | field_type := convert_type(field.ast_type.qualified) 111 | field_name := filter_name(field.name, false) 112 | sb.write_string('\t${field_name} ${field_type.name}\n') 113 | } 114 | sb.write_string('}\n') 115 | return sb.str() 116 | } 117 | 118 | // Typedef node goes after struct enum, but we need to parse it first, so that "type name { " is 119 | // generated first 120 | fn (mut c C2V) typedef_decl(node &Node) { 121 | mut typ := node.ast_type.qualified 122 | // just a single line typedef: (alias) 123 | // typedef sha1_context_t sha1_context_s ; 124 | // typedef after enum decl, just generate "enum NAME {" header 125 | mut c_alias_name := node.name // get_val(-2) 126 | if c_alias_name.contains('et_context_t') { 127 | // TODO remove this 128 | return 129 | } 130 | if c_alias_name in builtin_type_names { 131 | return 132 | } 133 | 134 | if c_alias_name in c.types || c_alias_name in c.enums { 135 | // This means that this is a struct/enum typedef that has already been defined. 136 | return 137 | } 138 | 139 | v_alias_name := c.add_struct_name(mut c.types, c_alias_name) 140 | 141 | if typ.starts_with('struct ') && typ.ends_with(' *') { 142 | // Opaque pointer, for example: typedef struct TSTexture_t *TSTexture; 143 | c.genln('type ${v_alias_name} = voidptr') 144 | return 145 | } 146 | 147 | if !typ.contains(c_alias_name) { 148 | if typ.contains('(*)') { 149 | tt := convert_type(typ) 150 | typ = tt.name 151 | } 152 | // Struct types have junk before spaces 153 | else { 154 | c_alias_name = c_alias_name.all_after(' ') 155 | tt := convert_type(typ) 156 | typ = tt.name 157 | } 158 | if c_alias_name.starts_with('__') { 159 | // Skip internal stuff like __builtin_ms_va_list 160 | return 161 | } 162 | if typ in c.enums { 163 | return 164 | } 165 | 166 | mut cgen_alias := typ 167 | if cgen_alias.starts_with('_') { 168 | cgen_alias = trim_underscores(typ) 169 | } 170 | if typ !in ['int', 'i8', 'i16', 'i64', 'u8', 'u16', 'u32', 'u64', 'f32', 'f64', 'usize', 'isize', 'bool', 'void', 'voidptr'] 171 | && !typ.starts_with('fn (') { 172 | // TODO handle this better 173 | cgen_alias = cgen_alias.capitalize() 174 | } 175 | c.genln('type ${c_alias_name.capitalize()} = ${cgen_alias}') // typedef alias (SINGLE LINE)') 176 | return 177 | } 178 | if typ.contains('enum ') { 179 | // enums were alredy handled in enum_decl 180 | return 181 | } else if typ.contains('struct ') { 182 | // structs were already handled in struct_decl 183 | return 184 | } else if typ.contains('union ') { 185 | // unions were alredy handled in struct_decl 186 | return 187 | } 188 | } 189 | 190 | // this calls typedef_decl() above 191 | fn (mut c C2V) parse_next_typedef() bool { 192 | // Hack: typedef with the actual enum name is next, parse it and generate "enum NAME {" first 193 | /* 194 | XTODO 195 | next_line := c.lines[c.line_i + 1] 196 | if next_line.contains('TypedefDecl') { 197 | c.line_i++ 198 | c.parse_next_node() 199 | return true 200 | } 201 | */ 202 | return false 203 | } 204 | -------------------------------------------------------------------------------- /tests/1.hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | printf("hello world!"); 5 | return 0; 6 | } 7 | 8 | typedef struct Foo { 9 | int bar; 10 | } Foo; 11 | 12 | void implicit_inits() { 13 | int num; 14 | Foo foo; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /tests/1.hello.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | fn main() { 5 | C.printf(c'hello world!') 6 | return 7 | } 8 | 9 | struct Foo { 10 | bar int 11 | } 12 | 13 | fn implicit_inits() { 14 | num := 0 15 | foo := Foo{} 16 | } 17 | -------------------------------------------------------------------------------- /tests/10.jni.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | #ifndef CLASSFILE_CONSTANTS_H 27 | #define CLASSFILE_CONSTANTS_H 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | /* Classfile version number for this information */ 34 | #define JVM_CLASSFILE_MAJOR_VERSION @@VERSION_CLASSFILE_MAJOR@@ 35 | #define JVM_CLASSFILE_MINOR_VERSION @@VERSION_CLASSFILE_MINOR@@ 36 | 37 | /* Flags */ 38 | 39 | enum { 40 | JVM_ACC_PUBLIC = 0x0001, 41 | JVM_ACC_PRIVATE = 0x0002, 42 | JVM_ACC_PROTECTED = 0x0004, 43 | JVM_ACC_STATIC = 0x0008, 44 | JVM_ACC_FINAL = 0x0010, 45 | JVM_ACC_SYNCHRONIZED = 0x0020, 46 | JVM_ACC_SUPER = 0x0020, 47 | JVM_ACC_VOLATILE = 0x0040, 48 | JVM_ACC_BRIDGE = 0x0040, 49 | JVM_ACC_TRANSIENT = 0x0080, 50 | JVM_ACC_VARARGS = 0x0080, 51 | JVM_ACC_NATIVE = 0x0100, 52 | JVM_ACC_INTERFACE = 0x0200, 53 | JVM_ACC_ABSTRACT = 0x0400, 54 | JVM_ACC_STRICT = 0x0800, 55 | JVM_ACC_SYNTHETIC = 0x1000, 56 | JVM_ACC_ANNOTATION = 0x2000, 57 | JVM_ACC_ENUM = 0x4000, 58 | JVM_ACC_MODULE = 0x8000 59 | }; 60 | 61 | #define JVM_ACC_PUBLIC_BIT 0 62 | #define JVM_ACC_PRIVATE_BIT 1 63 | #define JVM_ACC_PROTECTED_BIT 2 64 | #define JVM_ACC_STATIC_BIT 3 65 | #define JVM_ACC_FINAL_BIT 4 66 | #define JVM_ACC_SYNCHRONIZED_BIT 5 67 | #define JVM_ACC_SUPER_BIT 5 68 | #define JVM_ACC_VOLATILE_BIT 6 69 | #define JVM_ACC_BRIDGE_BIT 6 70 | #define JVM_ACC_TRANSIENT_BIT 7 71 | #define JVM_ACC_VARARGS_BIT 7 72 | #define JVM_ACC_NATIVE_BIT 8 73 | #define JVM_ACC_INTERFACE_BIT 9 74 | #define JVM_ACC_ABSTRACT_BIT 10 75 | #define JVM_ACC_STRICT_BIT 11 76 | #define JVM_ACC_SYNTHETIC_BIT 12 77 | #define JVM_ACC_ANNOTATION_BIT 13 78 | #define JVM_ACC_ENUM_BIT 14 79 | 80 | /* Used in newarray instruction. */ 81 | 82 | enum { 83 | JVM_T_BOOLEAN = 4, 84 | JVM_T_CHAR = 5, 85 | JVM_T_FLOAT = 6, 86 | JVM_T_DOUBLE = 7, 87 | JVM_T_BYTE = 8, 88 | JVM_T_SHORT = 9, 89 | JVM_T_INT = 10, 90 | JVM_T_LONG = 11 91 | }; 92 | 93 | /* Constant Pool Entries */ 94 | 95 | enum { 96 | JVM_CONSTANT_Utf8 = 1, 97 | JVM_CONSTANT_Unicode = 2, /* unused */ 98 | JVM_CONSTANT_Integer = 3, 99 | JVM_CONSTANT_Float = 4, 100 | JVM_CONSTANT_Long = 5, 101 | JVM_CONSTANT_Double = 6, 102 | JVM_CONSTANT_Class = 7, 103 | JVM_CONSTANT_String = 8, 104 | JVM_CONSTANT_Fieldref = 9, 105 | JVM_CONSTANT_Methodref = 10, 106 | JVM_CONSTANT_InterfaceMethodref = 11, 107 | JVM_CONSTANT_NameAndType = 12, 108 | JVM_CONSTANT_MethodHandle = 15, // JSR 292 109 | JVM_CONSTANT_MethodType = 16, // JSR 292 110 | JVM_CONSTANT_Dynamic = 17, 111 | JVM_CONSTANT_InvokeDynamic = 18, 112 | JVM_CONSTANT_Module = 19, 113 | JVM_CONSTANT_Package = 20, 114 | JVM_CONSTANT_ExternalMax = 20 115 | }; 116 | 117 | /* JVM_CONSTANT_MethodHandle subtypes */ 118 | enum { 119 | JVM_REF_getField = 1, 120 | JVM_REF_getStatic = 2, 121 | JVM_REF_putField = 3, 122 | JVM_REF_putStatic = 4, 123 | JVM_REF_invokeVirtual = 5, 124 | JVM_REF_invokeStatic = 6, 125 | JVM_REF_invokeSpecial = 7, 126 | JVM_REF_newInvokeSpecial = 8, 127 | JVM_REF_invokeInterface = 9 128 | }; 129 | 130 | /* StackMapTable type item numbers */ 131 | 132 | enum { 133 | JVM_ITEM_Top = 0, 134 | JVM_ITEM_Integer = 1, 135 | JVM_ITEM_Float = 2, 136 | JVM_ITEM_Double = 3, 137 | JVM_ITEM_Long = 4, 138 | JVM_ITEM_Null = 5, 139 | JVM_ITEM_UninitializedThis = 6, 140 | JVM_ITEM_Object = 7, 141 | JVM_ITEM_Uninitialized = 8 142 | }; 143 | 144 | /* Type signatures */ 145 | 146 | enum { 147 | JVM_SIGNATURE_SLASH = '/', 148 | JVM_SIGNATURE_DOT = '.', 149 | JVM_SIGNATURE_SPECIAL = '<', 150 | JVM_SIGNATURE_ENDSPECIAL = '>', 151 | JVM_SIGNATURE_ARRAY = '[', 152 | JVM_SIGNATURE_BYTE = 'B', 153 | JVM_SIGNATURE_CHAR = 'C', 154 | JVM_SIGNATURE_CLASS = 'L', 155 | JVM_SIGNATURE_ENDCLASS = ';', 156 | JVM_SIGNATURE_ENUM = 'E', 157 | JVM_SIGNATURE_FLOAT = 'F', 158 | JVM_SIGNATURE_DOUBLE = 'D', 159 | JVM_SIGNATURE_FUNC = '(', 160 | JVM_SIGNATURE_ENDFUNC = ')', 161 | JVM_SIGNATURE_INT = 'I', 162 | JVM_SIGNATURE_LONG = 'J', 163 | JVM_SIGNATURE_SHORT = 'S', 164 | JVM_SIGNATURE_VOID = 'V', 165 | JVM_SIGNATURE_BOOLEAN = 'Z' 166 | }; 167 | 168 | /* Opcodes */ 169 | 170 | enum { 171 | JVM_OPC_nop = 0, 172 | JVM_OPC_aconst_null = 1, 173 | JVM_OPC_iconst_m1 = 2, 174 | JVM_OPC_iconst_0 = 3, 175 | JVM_OPC_iconst_1 = 4, 176 | JVM_OPC_iconst_2 = 5, 177 | JVM_OPC_iconst_3 = 6, 178 | JVM_OPC_iconst_4 = 7, 179 | JVM_OPC_iconst_5 = 8, 180 | JVM_OPC_lconst_0 = 9, 181 | JVM_OPC_lconst_1 = 10, 182 | JVM_OPC_fconst_0 = 11, 183 | JVM_OPC_fconst_1 = 12, 184 | JVM_OPC_fconst_2 = 13, 185 | JVM_OPC_dconst_0 = 14, 186 | JVM_OPC_dconst_1 = 15, 187 | JVM_OPC_bipush = 16, 188 | JVM_OPC_sipush = 17, 189 | JVM_OPC_ldc = 18, 190 | JVM_OPC_ldc_w = 19, 191 | JVM_OPC_ldc2_w = 20, 192 | JVM_OPC_iload = 21, 193 | JVM_OPC_lload = 22, 194 | JVM_OPC_fload = 23, 195 | JVM_OPC_dload = 24, 196 | JVM_OPC_aload = 25, 197 | JVM_OPC_iload_0 = 26, 198 | JVM_OPC_iload_1 = 27, 199 | JVM_OPC_iload_2 = 28, 200 | JVM_OPC_iload_3 = 29, 201 | JVM_OPC_lload_0 = 30, 202 | JVM_OPC_lload_1 = 31, 203 | JVM_OPC_lload_2 = 32, 204 | JVM_OPC_lload_3 = 33, 205 | JVM_OPC_fload_0 = 34, 206 | JVM_OPC_fload_1 = 35, 207 | JVM_OPC_fload_2 = 36, 208 | JVM_OPC_fload_3 = 37, 209 | JVM_OPC_dload_0 = 38, 210 | JVM_OPC_dload_1 = 39, 211 | JVM_OPC_dload_2 = 40, 212 | JVM_OPC_dload_3 = 41, 213 | JVM_OPC_aload_0 = 42, 214 | JVM_OPC_aload_1 = 43, 215 | JVM_OPC_aload_2 = 44, 216 | JVM_OPC_aload_3 = 45, 217 | JVM_OPC_iaload = 46, 218 | JVM_OPC_laload = 47, 219 | JVM_OPC_faload = 48, 220 | JVM_OPC_daload = 49, 221 | JVM_OPC_aaload = 50, 222 | JVM_OPC_baload = 51, 223 | JVM_OPC_caload = 52, 224 | JVM_OPC_saload = 53, 225 | JVM_OPC_istore = 54, 226 | JVM_OPC_lstore = 55, 227 | JVM_OPC_fstore = 56, 228 | JVM_OPC_dstore = 57, 229 | JVM_OPC_astore = 58, 230 | JVM_OPC_istore_0 = 59, 231 | JVM_OPC_istore_1 = 60, 232 | JVM_OPC_istore_2 = 61, 233 | JVM_OPC_istore_3 = 62, 234 | JVM_OPC_lstore_0 = 63, 235 | JVM_OPC_lstore_1 = 64, 236 | JVM_OPC_lstore_2 = 65, 237 | JVM_OPC_lstore_3 = 66, 238 | JVM_OPC_fstore_0 = 67, 239 | JVM_OPC_fstore_1 = 68, 240 | JVM_OPC_fstore_2 = 69, 241 | JVM_OPC_fstore_3 = 70, 242 | JVM_OPC_dstore_0 = 71, 243 | JVM_OPC_dstore_1 = 72, 244 | JVM_OPC_dstore_2 = 73, 245 | JVM_OPC_dstore_3 = 74, 246 | JVM_OPC_astore_0 = 75, 247 | JVM_OPC_astore_1 = 76, 248 | JVM_OPC_astore_2 = 77, 249 | JVM_OPC_astore_3 = 78, 250 | JVM_OPC_iastore = 79, 251 | JVM_OPC_lastore = 80, 252 | JVM_OPC_fastore = 81, 253 | JVM_OPC_dastore = 82, 254 | JVM_OPC_aastore = 83, 255 | JVM_OPC_bastore = 84, 256 | JVM_OPC_castore = 85, 257 | JVM_OPC_sastore = 86, 258 | JVM_OPC_pop = 87, 259 | JVM_OPC_pop2 = 88, 260 | JVM_OPC_dup = 89, 261 | JVM_OPC_dup_x1 = 90, 262 | JVM_OPC_dup_x2 = 91, 263 | JVM_OPC_dup2 = 92, 264 | JVM_OPC_dup2_x1 = 93, 265 | JVM_OPC_dup2_x2 = 94, 266 | JVM_OPC_swap = 95, 267 | JVM_OPC_iadd = 96, 268 | JVM_OPC_ladd = 97, 269 | JVM_OPC_fadd = 98, 270 | JVM_OPC_dadd = 99, 271 | JVM_OPC_isub = 100, 272 | JVM_OPC_lsub = 101, 273 | JVM_OPC_fsub = 102, 274 | JVM_OPC_dsub = 103, 275 | JVM_OPC_imul = 104, 276 | JVM_OPC_lmul = 105, 277 | JVM_OPC_fmul = 106, 278 | JVM_OPC_dmul = 107, 279 | JVM_OPC_idiv = 108, 280 | JVM_OPC_ldiv = 109, 281 | JVM_OPC_fdiv = 110, 282 | JVM_OPC_ddiv = 111, 283 | JVM_OPC_irem = 112, 284 | JVM_OPC_lrem = 113, 285 | JVM_OPC_frem = 114, 286 | JVM_OPC_drem = 115, 287 | JVM_OPC_ineg = 116, 288 | JVM_OPC_lneg = 117, 289 | JVM_OPC_fneg = 118, 290 | JVM_OPC_dneg = 119, 291 | JVM_OPC_ishl = 120, 292 | JVM_OPC_lshl = 121, 293 | JVM_OPC_ishr = 122, 294 | JVM_OPC_lshr = 123, 295 | JVM_OPC_iushr = 124, 296 | JVM_OPC_lushr = 125, 297 | JVM_OPC_iand = 126, 298 | JVM_OPC_land = 127, 299 | JVM_OPC_ior = 128, 300 | JVM_OPC_lor = 129, 301 | JVM_OPC_ixor = 130, 302 | JVM_OPC_lxor = 131, 303 | JVM_OPC_iinc = 132, 304 | JVM_OPC_i2l = 133, 305 | JVM_OPC_i2f = 134, 306 | JVM_OPC_i2d = 135, 307 | JVM_OPC_l2i = 136, 308 | JVM_OPC_l2f = 137, 309 | JVM_OPC_l2d = 138, 310 | JVM_OPC_f2i = 139, 311 | JVM_OPC_f2l = 140, 312 | JVM_OPC_f2d = 141, 313 | JVM_OPC_d2i = 142, 314 | JVM_OPC_d2l = 143, 315 | JVM_OPC_d2f = 144, 316 | JVM_OPC_i2b = 145, 317 | JVM_OPC_i2c = 146, 318 | JVM_OPC_i2s = 147, 319 | JVM_OPC_lcmp = 148, 320 | JVM_OPC_fcmpl = 149, 321 | JVM_OPC_fcmpg = 150, 322 | JVM_OPC_dcmpl = 151, 323 | JVM_OPC_dcmpg = 152, 324 | JVM_OPC_ifeq = 153, 325 | JVM_OPC_ifne = 154, 326 | JVM_OPC_iflt = 155, 327 | JVM_OPC_ifge = 156, 328 | JVM_OPC_ifgt = 157, 329 | JVM_OPC_ifle = 158, 330 | JVM_OPC_if_icmpeq = 159, 331 | JVM_OPC_if_icmpne = 160, 332 | JVM_OPC_if_icmplt = 161, 333 | JVM_OPC_if_icmpge = 162, 334 | JVM_OPC_if_icmpgt = 163, 335 | JVM_OPC_if_icmple = 164, 336 | JVM_OPC_if_acmpeq = 165, 337 | JVM_OPC_if_acmpne = 166, 338 | JVM_OPC_goto = 167, 339 | JVM_OPC_jsr = 168, 340 | JVM_OPC_ret = 169, 341 | JVM_OPC_tableswitch = 170, 342 | JVM_OPC_lookupswitch = 171, 343 | JVM_OPC_ireturn = 172, 344 | JVM_OPC_lreturn = 173, 345 | JVM_OPC_freturn = 174, 346 | JVM_OPC_dreturn = 175, 347 | JVM_OPC_areturn = 176, 348 | JVM_OPC_return = 177, 349 | JVM_OPC_getstatic = 178, 350 | JVM_OPC_putstatic = 179, 351 | JVM_OPC_getfield = 180, 352 | JVM_OPC_putfield = 181, 353 | JVM_OPC_invokevirtual = 182, 354 | JVM_OPC_invokespecial = 183, 355 | JVM_OPC_invokestatic = 184, 356 | JVM_OPC_invokeinterface = 185, 357 | JVM_OPC_invokedynamic = 186, 358 | JVM_OPC_new = 187, 359 | JVM_OPC_newarray = 188, 360 | JVM_OPC_anewarray = 189, 361 | JVM_OPC_arraylength = 190, 362 | JVM_OPC_athrow = 191, 363 | JVM_OPC_checkcast = 192, 364 | JVM_OPC_instanceof = 193, 365 | JVM_OPC_monitorenter = 194, 366 | JVM_OPC_monitorexit = 195, 367 | JVM_OPC_wide = 196, 368 | JVM_OPC_multianewarray = 197, 369 | JVM_OPC_ifnull = 198, 370 | JVM_OPC_ifnonnull = 199, 371 | JVM_OPC_goto_w = 200, 372 | JVM_OPC_jsr_w = 201, 373 | JVM_OPC_MAX = 201 374 | }; 375 | 376 | /* Opcode length initializer, use with something like: 377 | * unsigned char opcode_length[JVM_OPC_MAX+1] = JVM_OPCODE_LENGTH_INITIALIZER; 378 | */ 379 | #define JVM_OPCODE_LENGTH_INITIALIZER { \ 380 | 1, /* nop */ \ 381 | 1, /* aconst_null */ \ 382 | 1, /* iconst_m1 */ \ 383 | 1, /* iconst_0 */ \ 384 | 1, /* iconst_1 */ \ 385 | 1, /* iconst_2 */ \ 386 | 1, /* iconst_3 */ \ 387 | 1, /* iconst_4 */ \ 388 | 1, /* iconst_5 */ \ 389 | 1, /* lconst_0 */ \ 390 | 1, /* lconst_1 */ \ 391 | 1, /* fconst_0 */ \ 392 | 1, /* fconst_1 */ \ 393 | 1, /* fconst_2 */ \ 394 | 1, /* dconst_0 */ \ 395 | 1, /* dconst_1 */ \ 396 | 2, /* bipush */ \ 397 | 3, /* sipush */ \ 398 | 2, /* ldc */ \ 399 | 3, /* ldc_w */ \ 400 | 3, /* ldc2_w */ \ 401 | 2, /* iload */ \ 402 | 2, /* lload */ \ 403 | 2, /* fload */ \ 404 | 2, /* dload */ \ 405 | 2, /* aload */ \ 406 | 1, /* iload_0 */ \ 407 | 1, /* iload_1 */ \ 408 | 1, /* iload_2 */ \ 409 | 1, /* iload_3 */ \ 410 | 1, /* lload_0 */ \ 411 | 1, /* lload_1 */ \ 412 | 1, /* lload_2 */ \ 413 | 1, /* lload_3 */ \ 414 | 1, /* fload_0 */ \ 415 | 1, /* fload_1 */ \ 416 | 1, /* fload_2 */ \ 417 | 1, /* fload_3 */ \ 418 | 1, /* dload_0 */ \ 419 | 1, /* dload_1 */ \ 420 | 1, /* dload_2 */ \ 421 | 1, /* dload_3 */ \ 422 | 1, /* aload_0 */ \ 423 | 1, /* aload_1 */ \ 424 | 1, /* aload_2 */ \ 425 | 1, /* aload_3 */ \ 426 | 1, /* iaload */ \ 427 | 1, /* laload */ \ 428 | 1, /* faload */ \ 429 | 1, /* daload */ \ 430 | 1, /* aaload */ \ 431 | 1, /* baload */ \ 432 | 1, /* caload */ \ 433 | 1, /* saload */ \ 434 | 2, /* istore */ \ 435 | 2, /* lstore */ \ 436 | 2, /* fstore */ \ 437 | 2, /* dstore */ \ 438 | 2, /* astore */ \ 439 | 1, /* istore_0 */ \ 440 | 1, /* istore_1 */ \ 441 | 1, /* istore_2 */ \ 442 | 1, /* istore_3 */ \ 443 | 1, /* lstore_0 */ \ 444 | 1, /* lstore_1 */ \ 445 | 1, /* lstore_2 */ \ 446 | 1, /* lstore_3 */ \ 447 | 1, /* fstore_0 */ \ 448 | 1, /* fstore_1 */ \ 449 | 1, /* fstore_2 */ \ 450 | 1, /* fstore_3 */ \ 451 | 1, /* dstore_0 */ \ 452 | 1, /* dstore_1 */ \ 453 | 1, /* dstore_2 */ \ 454 | 1, /* dstore_3 */ \ 455 | 1, /* astore_0 */ \ 456 | 1, /* astore_1 */ \ 457 | 1, /* astore_2 */ \ 458 | 1, /* astore_3 */ \ 459 | 1, /* iastore */ \ 460 | 1, /* lastore */ \ 461 | 1, /* fastore */ \ 462 | 1, /* dastore */ \ 463 | 1, /* aastore */ \ 464 | 1, /* bastore */ \ 465 | 1, /* castore */ \ 466 | 1, /* sastore */ \ 467 | 1, /* pop */ \ 468 | 1, /* pop2 */ \ 469 | 1, /* dup */ \ 470 | 1, /* dup_x1 */ \ 471 | 1, /* dup_x2 */ \ 472 | 1, /* dup2 */ \ 473 | 1, /* dup2_x1 */ \ 474 | 1, /* dup2_x2 */ \ 475 | 1, /* swap */ \ 476 | 1, /* iadd */ \ 477 | 1, /* ladd */ \ 478 | 1, /* fadd */ \ 479 | 1, /* dadd */ \ 480 | 1, /* isub */ \ 481 | 1, /* lsub */ \ 482 | 1, /* fsub */ \ 483 | 1, /* dsub */ \ 484 | 1, /* imul */ \ 485 | 1, /* lmul */ \ 486 | 1, /* fmul */ \ 487 | 1, /* dmul */ \ 488 | 1, /* idiv */ \ 489 | 1, /* ldiv */ \ 490 | 1, /* fdiv */ \ 491 | 1, /* ddiv */ \ 492 | 1, /* irem */ \ 493 | 1, /* lrem */ \ 494 | 1, /* frem */ \ 495 | 1, /* drem */ \ 496 | 1, /* ineg */ \ 497 | 1, /* lneg */ \ 498 | 1, /* fneg */ \ 499 | 1, /* dneg */ \ 500 | 1, /* ishl */ \ 501 | 1, /* lshl */ \ 502 | 1, /* ishr */ \ 503 | 1, /* lshr */ \ 504 | 1, /* iushr */ \ 505 | 1, /* lushr */ \ 506 | 1, /* iand */ \ 507 | 1, /* land */ \ 508 | 1, /* ior */ \ 509 | 1, /* lor */ \ 510 | 1, /* ixor */ \ 511 | 1, /* lxor */ \ 512 | 3, /* iinc */ \ 513 | 1, /* i2l */ \ 514 | 1, /* i2f */ \ 515 | 1, /* i2d */ \ 516 | 1, /* l2i */ \ 517 | 1, /* l2f */ \ 518 | 1, /* l2d */ \ 519 | 1, /* f2i */ \ 520 | 1, /* f2l */ \ 521 | 1, /* f2d */ \ 522 | 1, /* d2i */ \ 523 | 1, /* d2l */ \ 524 | 1, /* d2f */ \ 525 | 1, /* i2b */ \ 526 | 1, /* i2c */ \ 527 | 1, /* i2s */ \ 528 | 1, /* lcmp */ \ 529 | 1, /* fcmpl */ \ 530 | 1, /* fcmpg */ \ 531 | 1, /* dcmpl */ \ 532 | 1, /* dcmpg */ \ 533 | 3, /* ifeq */ \ 534 | 3, /* ifne */ \ 535 | 3, /* iflt */ \ 536 | 3, /* ifge */ \ 537 | 3, /* ifgt */ \ 538 | 3, /* ifle */ \ 539 | 3, /* if_icmpeq */ \ 540 | 3, /* if_icmpne */ \ 541 | 3, /* if_icmplt */ \ 542 | 3, /* if_icmpge */ \ 543 | 3, /* if_icmpgt */ \ 544 | 3, /* if_icmple */ \ 545 | 3, /* if_acmpeq */ \ 546 | 3, /* if_acmpne */ \ 547 | 3, /* goto */ \ 548 | 3, /* jsr */ \ 549 | 2, /* ret */ \ 550 | 99, /* tableswitch */ \ 551 | 99, /* lookupswitch */ \ 552 | 1, /* ireturn */ \ 553 | 1, /* lreturn */ \ 554 | 1, /* freturn */ \ 555 | 1, /* dreturn */ \ 556 | 1, /* areturn */ \ 557 | 1, /* return */ \ 558 | 3, /* getstatic */ \ 559 | 3, /* putstatic */ \ 560 | 3, /* getfield */ \ 561 | 3, /* putfield */ \ 562 | 3, /* invokevirtual */ \ 563 | 3, /* invokespecial */ \ 564 | 3, /* invokestatic */ \ 565 | 5, /* invokeinterface */ \ 566 | 5, /* invokedynamic */ \ 567 | 3, /* new */ \ 568 | 2, /* newarray */ \ 569 | 3, /* anewarray */ \ 570 | 1, /* arraylength */ \ 571 | 1, /* athrow */ \ 572 | 3, /* checkcast */ \ 573 | 3, /* instanceof */ \ 574 | 1, /* monitorenter */ \ 575 | 1, /* monitorexit */ \ 576 | 0, /* wide */ \ 577 | 4, /* multianewarray */ \ 578 | 3, /* ifnull */ \ 579 | 3, /* ifnonnull */ \ 580 | 5, /* goto_w */ \ 581 | 5 /* jsr_w */ \ 582 | } 583 | 584 | #ifdef __cplusplus 585 | } /* extern "C" */ 586 | #endif /* __cplusplus */ 587 | 588 | #endif /* CLASSFILE_CONSTANTS */ -------------------------------------------------------------------------------- /tests/10.jni.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module tests 3 | 4 | // 5 | // *Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. 6 | // *DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7 | // * *This code is free software; you can redistribute it and/or modify it 8 | // *under the terms of the GNU General Public License version 2 only, as 9 | // *published by the Free Software Foundation. Oracle designates this 10 | // *particular file as subject to the "Classpath" exception as provided 11 | // *by Oracle in the LICENSE file that accompanied this code. 12 | // * *This code is distributed in the hope that it will be useful, but WITHOUT 13 | // *ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | // *FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 | // *version 2 for more details (a copy is included in the LICENSE file that 16 | // *accompanied this code). 17 | // * *You should have received a copy of the GNU General Public License version 18 | // *2 along with this work; if not, write to the Free Software Foundation, 19 | // *Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | // * *Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 | // *or visit www.oracle.com if you need additional information or have any 22 | // *questions. 23 | // 24 | // Classfile version number for this information 25 | // Flags 26 | 27 | // empty enum 28 | const jvm_acc_public = 1 29 | const jvm_acc_private = 2 30 | const jvm_acc_protected = 4 31 | const jvm_acc_static = 8 32 | const jvm_acc_final = 16 33 | const jvm_acc_synchronized = 32 34 | const jvm_acc_super = 32 35 | const jvm_acc_volatile = 64 36 | const jvm_acc_bridge = 64 37 | const jvm_acc_transient = 128 38 | const jvm_acc_varargs = 128 39 | const jvm_acc_native = 256 40 | const jvm_acc_interface = 512 41 | const jvm_acc_abstract = 1024 42 | const jvm_acc_strict = 2048 43 | const jvm_acc_synthetic = 4096 44 | const jvm_acc_annotation = 8192 45 | const jvm_acc_enum = 16384 46 | const jvm_acc_module = 32768 47 | 48 | // Used in newarray instruction. 49 | 50 | // empty enum 51 | const jvm_t_boolean = 4 52 | const jvm_t_char = 5 53 | const jvm_t_float = 6 54 | const jvm_t_double = 7 55 | const jvm_t_byte = 8 56 | const jvm_t_short = 9 57 | const jvm_t_int = 10 58 | const jvm_t_long = 11 59 | 60 | // Constant Pool Entries 61 | 62 | // empty enum 63 | const jvm_constant_utf8 = 1 64 | const jvm_constant_unicode = 2 65 | // unused 66 | const jvm_constant_integer = 3 67 | const jvm_constant_float = 4 68 | const jvm_constant_long = 5 69 | const jvm_constant_double = 6 70 | const jvm_constant_class = 7 71 | const jvm_constant_string = 8 72 | const jvm_constant_fieldref = 9 73 | const jvm_constant_methodref = 10 74 | const jvm_constant_interface_methodref = 11 75 | const jvm_constant_name_and_type = 12 76 | const jvm_constant_method_handle = 15 77 | // JSR 292 78 | const jvm_constant_method_type = 16 79 | // JSR 292 80 | const jvm_constant_dynamic = 17 81 | const jvm_constant_invoke_dynamic = 18 82 | const jvm_constant_module = 19 83 | const jvm_constant_package = 20 84 | const jvm_constant_external_max = 20 85 | 86 | // JVM_CONSTANT_MethodHandle subtypes 87 | 88 | // empty enum 89 | const jvm_ref_get_field = 1 90 | const jvm_ref_get_static = 2 91 | const jvm_ref_put_field = 3 92 | const jvm_ref_put_static = 4 93 | const jvm_ref_invoke_virtual = 5 94 | const jvm_ref_invoke_static = 6 95 | const jvm_ref_invoke_special = 7 96 | const jvm_ref_new_invoke_special = 8 97 | const jvm_ref_invoke_interface = 9 98 | 99 | // StackMapTable type item numbers 100 | 101 | // empty enum 102 | const jvm_item_top = 0 103 | const jvm_item_integer = 1 104 | const jvm_item_float = 2 105 | const jvm_item_double = 3 106 | const jvm_item_long = 4 107 | const jvm_item_null = 5 108 | const jvm_item_uninitialized_this = 6 109 | const jvm_item_object = 7 110 | const jvm_item_uninitialized = 8 111 | 112 | // Type signatures 113 | 114 | // empty enum 115 | const jvm_signature_slash = `/` 116 | const jvm_signature_dot = `.` 117 | const jvm_signature_special = `<` 118 | const jvm_signature_endspecial = `>` 119 | const jvm_signature_array = `[` 120 | const jvm_signature_byte = `B` 121 | const jvm_signature_char = `C` 122 | const jvm_signature_class = `L` 123 | const jvm_signature_endclass = `;` 124 | const jvm_signature_enum = `E` 125 | const jvm_signature_float = `F` 126 | const jvm_signature_double = `D` 127 | const jvm_signature_func = `(` 128 | const jvm_signature_endfunc = `)` 129 | const jvm_signature_int = `I` 130 | const jvm_signature_long = `J` 131 | const jvm_signature_short = `S` 132 | const jvm_signature_void = `V` 133 | const jvm_signature_boolean = `Z` 134 | 135 | // Opcodes 136 | 137 | // empty enum 138 | const jvm_opc_nop = 0 139 | const jvm_opc_aconst_null = 1 140 | const jvm_opc_iconst_m1 = 2 141 | const jvm_opc_iconst_0 = 3 142 | const jvm_opc_iconst_1 = 4 143 | const jvm_opc_iconst_2 = 5 144 | const jvm_opc_iconst_3 = 6 145 | const jvm_opc_iconst_4 = 7 146 | const jvm_opc_iconst_5 = 8 147 | const jvm_opc_lconst_0 = 9 148 | const jvm_opc_lconst_1 = 10 149 | const jvm_opc_fconst_0 = 11 150 | const jvm_opc_fconst_1 = 12 151 | const jvm_opc_fconst_2 = 13 152 | const jvm_opc_dconst_0 = 14 153 | const jvm_opc_dconst_1 = 15 154 | const jvm_opc_bipush = 16 155 | const jvm_opc_sipush = 17 156 | const jvm_opc_ldc = 18 157 | const jvm_opc_ldc_w = 19 158 | const jvm_opc_ldc2_w = 20 159 | const jvm_opc_iload = 21 160 | const jvm_opc_lload = 22 161 | const jvm_opc_fload = 23 162 | const jvm_opc_dload = 24 163 | const jvm_opc_aload = 25 164 | const jvm_opc_iload_0 = 26 165 | const jvm_opc_iload_1 = 27 166 | const jvm_opc_iload_2 = 28 167 | const jvm_opc_iload_3 = 29 168 | const jvm_opc_lload_0 = 30 169 | const jvm_opc_lload_1 = 31 170 | const jvm_opc_lload_2 = 32 171 | const jvm_opc_lload_3 = 33 172 | const jvm_opc_fload_0 = 34 173 | const jvm_opc_fload_1 = 35 174 | const jvm_opc_fload_2 = 36 175 | const jvm_opc_fload_3 = 37 176 | const jvm_opc_dload_0 = 38 177 | const jvm_opc_dload_1 = 39 178 | const jvm_opc_dload_2 = 40 179 | const jvm_opc_dload_3 = 41 180 | const jvm_opc_aload_0 = 42 181 | const jvm_opc_aload_1 = 43 182 | const jvm_opc_aload_2 = 44 183 | const jvm_opc_aload_3 = 45 184 | const jvm_opc_iaload = 46 185 | const jvm_opc_laload = 47 186 | const jvm_opc_faload = 48 187 | const jvm_opc_daload = 49 188 | const jvm_opc_aaload = 50 189 | const jvm_opc_baload = 51 190 | const jvm_opc_caload = 52 191 | const jvm_opc_saload = 53 192 | const jvm_opc_istore = 54 193 | const jvm_opc_lstore = 55 194 | const jvm_opc_fstore = 56 195 | const jvm_opc_dstore = 57 196 | const jvm_opc_astore = 58 197 | const jvm_opc_istore_0 = 59 198 | const jvm_opc_istore_1 = 60 199 | const jvm_opc_istore_2 = 61 200 | const jvm_opc_istore_3 = 62 201 | const jvm_opc_lstore_0 = 63 202 | const jvm_opc_lstore_1 = 64 203 | const jvm_opc_lstore_2 = 65 204 | const jvm_opc_lstore_3 = 66 205 | const jvm_opc_fstore_0 = 67 206 | const jvm_opc_fstore_1 = 68 207 | const jvm_opc_fstore_2 = 69 208 | const jvm_opc_fstore_3 = 70 209 | const jvm_opc_dstore_0 = 71 210 | const jvm_opc_dstore_1 = 72 211 | const jvm_opc_dstore_2 = 73 212 | const jvm_opc_dstore_3 = 74 213 | const jvm_opc_astore_0 = 75 214 | const jvm_opc_astore_1 = 76 215 | const jvm_opc_astore_2 = 77 216 | const jvm_opc_astore_3 = 78 217 | const jvm_opc_iastore = 79 218 | const jvm_opc_lastore = 80 219 | const jvm_opc_fastore = 81 220 | const jvm_opc_dastore = 82 221 | const jvm_opc_aastore = 83 222 | const jvm_opc_bastore = 84 223 | const jvm_opc_castore = 85 224 | const jvm_opc_sastore = 86 225 | const jvm_opc_pop = 87 226 | const jvm_opc_pop2 = 88 227 | const jvm_opc_dup = 89 228 | const jvm_opc_dup_x1 = 90 229 | const jvm_opc_dup_x2 = 91 230 | const jvm_opc_dup2 = 92 231 | const jvm_opc_dup2_x1 = 93 232 | const jvm_opc_dup2_x2 = 94 233 | const jvm_opc_swap = 95 234 | const jvm_opc_iadd = 96 235 | const jvm_opc_ladd = 97 236 | const jvm_opc_fadd = 98 237 | const jvm_opc_dadd = 99 238 | const jvm_opc_isub = 100 239 | const jvm_opc_lsub = 101 240 | const jvm_opc_fsub = 102 241 | const jvm_opc_dsub = 103 242 | const jvm_opc_imul = 104 243 | const jvm_opc_lmul = 105 244 | const jvm_opc_fmul = 106 245 | const jvm_opc_dmul = 107 246 | const jvm_opc_idiv = 108 247 | const jvm_opc_ldiv = 109 248 | const jvm_opc_fdiv = 110 249 | const jvm_opc_ddiv = 111 250 | const jvm_opc_irem = 112 251 | const jvm_opc_lrem = 113 252 | const jvm_opc_frem = 114 253 | const jvm_opc_drem = 115 254 | const jvm_opc_ineg = 116 255 | const jvm_opc_lneg = 117 256 | const jvm_opc_fneg = 118 257 | const jvm_opc_dneg = 119 258 | const jvm_opc_ishl = 120 259 | const jvm_opc_lshl = 121 260 | const jvm_opc_ishr = 122 261 | const jvm_opc_lshr = 123 262 | const jvm_opc_iushr = 124 263 | const jvm_opc_lushr = 125 264 | const jvm_opc_iand = 126 265 | const jvm_opc_land = 127 266 | const jvm_opc_ior = 128 267 | const jvm_opc_lor = 129 268 | const jvm_opc_ixor = 130 269 | const jvm_opc_lxor = 131 270 | const jvm_opc_iinc = 132 271 | const jvm_opc_i2l = 133 272 | const jvm_opc_i2f = 134 273 | const jvm_opc_i2d = 135 274 | const jvm_opc_l2i = 136 275 | const jvm_opc_l2f = 137 276 | const jvm_opc_l2d = 138 277 | const jvm_opc_f2i = 139 278 | const jvm_opc_f2l = 140 279 | const jvm_opc_f2d = 141 280 | const jvm_opc_d2i = 142 281 | const jvm_opc_d2l = 143 282 | const jvm_opc_d2f = 144 283 | const jvm_opc_i2b = 145 284 | const jvm_opc_i2c = 146 285 | const jvm_opc_i2s = 147 286 | const jvm_opc_lcmp = 148 287 | const jvm_opc_fcmpl = 149 288 | const jvm_opc_fcmpg = 150 289 | const jvm_opc_dcmpl = 151 290 | const jvm_opc_dcmpg = 152 291 | const jvm_opc_ifeq = 153 292 | const jvm_opc_ifne = 154 293 | const jvm_opc_iflt = 155 294 | const jvm_opc_ifge = 156 295 | const jvm_opc_ifgt = 157 296 | const jvm_opc_ifle = 158 297 | const jvm_opc_if_icmpeq = 159 298 | const jvm_opc_if_icmpne = 160 299 | const jvm_opc_if_icmplt = 161 300 | const jvm_opc_if_icmpge = 162 301 | const jvm_opc_if_icmpgt = 163 302 | const jvm_opc_if_icmple = 164 303 | const jvm_opc_if_acmpeq = 165 304 | const jvm_opc_if_acmpne = 166 305 | const jvm_opc_goto = 167 306 | const jvm_opc_jsr = 168 307 | const jvm_opc_ret = 169 308 | const jvm_opc_tableswitch = 170 309 | const jvm_opc_lookupswitch = 171 310 | const jvm_opc_ireturn = 172 311 | const jvm_opc_lreturn = 173 312 | const jvm_opc_freturn = 174 313 | const jvm_opc_dreturn = 175 314 | const jvm_opc_areturn = 176 315 | const jvm_opc_return = 177 316 | const jvm_opc_getstatic = 178 317 | const jvm_opc_putstatic = 179 318 | const jvm_opc_getfield = 180 319 | const jvm_opc_putfield = 181 320 | const jvm_opc_invokevirtual = 182 321 | const jvm_opc_invokespecial = 183 322 | const jvm_opc_invokestatic = 184 323 | const jvm_opc_invokeinterface = 185 324 | const jvm_opc_invokedynamic = 186 325 | const jvm_opc_new = 187 326 | const jvm_opc_newarray = 188 327 | const jvm_opc_anewarray = 189 328 | const jvm_opc_arraylength = 190 329 | const jvm_opc_athrow = 191 330 | const jvm_opc_checkcast = 192 331 | const jvm_opc_instanceof = 193 332 | const jvm_opc_monitorenter = 194 333 | const jvm_opc_monitorexit = 195 334 | const jvm_opc_wide = 196 335 | const jvm_opc_multianewarray = 197 336 | const jvm_opc_ifnull = 198 337 | const jvm_opc_ifnonnull = 199 338 | const jvm_opc_goto_w = 200 339 | const jvm_opc_jsr_w = 201 340 | const jvm_opc_max = 201 341 | 342 | // Opcode length initializer, use with something like: 343 | // * unsigned char opcode_length[JVM_OPC_MAX+1] = JVM_OPCODE_LENGTH_INITIALIZER; 344 | // 345 | // nop 346 | // aconst_null 347 | // iconst_m1 348 | // iconst_0 349 | // iconst_1 350 | // iconst_2 351 | // iconst_3 352 | // iconst_4 353 | // iconst_5 354 | // lconst_0 355 | // lconst_1 356 | // fconst_0 357 | // fconst_1 358 | // fconst_2 359 | // dconst_0 360 | // dconst_1 361 | // bipush 362 | // sipush 363 | // ldc 364 | // ldc_w 365 | // ldc2_w 366 | // iload 367 | // lload 368 | // fload 369 | // dload 370 | // aload 371 | // iload_0 372 | // iload_1 373 | // iload_2 374 | // iload_3 375 | // lload_0 376 | // lload_1 377 | // lload_2 378 | // lload_3 379 | // fload_0 380 | // fload_1 381 | // fload_2 382 | // fload_3 383 | // dload_0 384 | // dload_1 385 | // dload_2 386 | // dload_3 387 | // aload_0 388 | // aload_1 389 | // aload_2 390 | // aload_3 391 | // iaload 392 | // laload 393 | // faload 394 | // daload 395 | // aaload 396 | // baload 397 | // caload 398 | // saload 399 | // istore 400 | // lstore 401 | // fstore 402 | // dstore 403 | // astore 404 | // istore_0 405 | // istore_1 406 | // istore_2 407 | // istore_3 408 | // lstore_0 409 | // lstore_1 410 | // lstore_2 411 | // lstore_3 412 | // fstore_0 413 | // fstore_1 414 | // fstore_2 415 | // fstore_3 416 | // dstore_0 417 | // dstore_1 418 | // dstore_2 419 | // dstore_3 420 | // astore_0 421 | // astore_1 422 | // astore_2 423 | // astore_3 424 | // iastore 425 | // lastore 426 | // fastore 427 | // dastore 428 | // aastore 429 | // bastore 430 | // castore 431 | // sastore 432 | // pop 433 | // pop2 434 | // dup 435 | // dup_x1 436 | // dup_x2 437 | // dup2 438 | // dup2_x1 439 | // dup2_x2 440 | // swap 441 | // iadd 442 | // ladd 443 | // fadd 444 | // dadd 445 | // isub 446 | // lsub 447 | // fsub 448 | // dsub 449 | // imul 450 | // lmul 451 | // fmul 452 | // dmul 453 | // idiv 454 | // ldiv 455 | // fdiv 456 | // ddiv 457 | // irem 458 | // lrem 459 | // frem 460 | // drem 461 | // ineg 462 | // lneg 463 | // fneg 464 | // dneg 465 | // ishl 466 | // lshl 467 | // ishr 468 | // lshr 469 | // iushr 470 | // lushr 471 | // iand 472 | // land 473 | // ior 474 | // lor 475 | // ixor 476 | // lxor 477 | // iinc 478 | // i2l 479 | // i2f 480 | // i2d 481 | // l2i 482 | // l2f 483 | // l2d 484 | // f2i 485 | // f2l 486 | // f2d 487 | // d2i 488 | // d2l 489 | // d2f 490 | // i2b 491 | // i2c 492 | // i2s 493 | // lcmp 494 | // fcmpl 495 | // fcmpg 496 | // dcmpl 497 | // dcmpg 498 | // ifeq 499 | // ifne 500 | // iflt 501 | // ifge 502 | // ifgt 503 | // ifle 504 | // if_icmpeq 505 | // if_icmpne 506 | // if_icmplt 507 | // if_icmpge 508 | // if_icmpgt 509 | // if_icmple 510 | // if_acmpeq 511 | // if_acmpne 512 | // goto 513 | // jsr 514 | // ret 515 | // tableswitch 516 | // lookupswitch 517 | // ireturn 518 | // lreturn 519 | // freturn 520 | // dreturn 521 | // areturn 522 | // return 523 | // getstatic 524 | // putstatic 525 | // getfield 526 | // putfield 527 | // invokevirtual 528 | // invokespecial 529 | // invokestatic 530 | // invokeinterface 531 | // invokedynamic 532 | // new 533 | // newarray 534 | // anewarray 535 | // arraylength 536 | // athrow 537 | // checkcast 538 | // instanceof 539 | // monitorenter 540 | // monitorexit 541 | // wide 542 | // multianewarray 543 | // ifnull 544 | // ifnonnull 545 | // goto_w 546 | // jsr_w 547 | // extern "C" 548 | // __cplusplus 549 | // CLASSFILE_CONSTANTS -------------------------------------------------------------------------------- /tests/11.enum_default.c: -------------------------------------------------------------------------------- 1 | enum myEnum { 2 | A, 3 | B, 4 | C 5 | }; 6 | 7 | typedef enum { 8 | D, 9 | E, 10 | F 11 | } myAnotherEnum; 12 | 13 | typedef enum myStrangeEnum { 14 | G, 15 | H, 16 | I 17 | } myStrangeEnum; 18 | 19 | enum { J = 1 }; 20 | 21 | void enum_func(enum myEnum a) { 22 | } 23 | 24 | void enum_func_const(const enum myEnum a) { 25 | } 26 | 27 | int main() { 28 | enum myEnum myEnumVar = A; 29 | myAnotherEnum myEnumVar2 = D; 30 | myStrangeEnum myEnumVar3 = G; 31 | int myIntVar = J; 32 | enum_func(myEnumVar); 33 | enum_func_const(myEnumVar); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /tests/11.enum_default.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | enum MyEnum { 5 | a 6 | b 7 | c 8 | } 9 | 10 | enum MyAnotherEnum { 11 | d 12 | e 13 | f 14 | } 15 | 16 | enum MyStrangeEnum { 17 | g 18 | h 19 | i 20 | } 21 | 22 | // empty enum 23 | const j = 1 24 | 25 | fn enum_func(a MyEnum) { 26 | } 27 | 28 | fn enum_func_const(a MyEnum) { 29 | } 30 | 31 | fn main() { 32 | my_enum_var := MyEnum.a 33 | my_enum_var2 := MyAnotherEnum.d 34 | my_enum_var3 := MyStrangeEnum.g 35 | my_int_var := j 36 | enum_func(my_enum_var) 37 | enum_func_const(my_enum_var) 38 | return 39 | } 40 | -------------------------------------------------------------------------------- /tests/12.if_stmt.c: -------------------------------------------------------------------------------- 1 | int static inline quot( int x, int y ) { 2 | if( x == 0 || y == 0 ) 3 | return 0; 4 | if( x > y ) 5 | return x%y ? 0 : x/y; 6 | else if (x == y) 7 | return x%y ? 0 : x/y; 8 | else 9 | return y%x ? 0 : y/x; 10 | } 11 | int main() { 12 | quot(2,2); 13 | } -------------------------------------------------------------------------------- /tests/12.if_stmt.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | fn quot(x int, y int) int { 5 | if x == 0 || y == 0 { 6 | return 0 7 | } 8 | if x > y { 9 | return if x % y { 0 } else { x / y } 10 | } else if x == y { 11 | return if x % y { 0 } else { x / y } 12 | } else { 13 | return if y % x { 0 } else { y / x } 14 | } 15 | } 16 | 17 | fn main() { 18 | quot(2, 2) 19 | } 20 | -------------------------------------------------------------------------------- /tests/13.switch.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const int a = 0; 4 | 5 | void main() 6 | { 7 | switch(a) 8 | { 9 | default: 10 | printf("foo\n"); 11 | break; 12 | case 0: 13 | printf("bar\n"); 14 | break; 15 | } 16 | 17 | 18 | switch(a) 19 | { 20 | case 0: 21 | printf("bar\n"); 22 | break; 23 | default: 24 | printf("foo\n"); 25 | break; 26 | } 27 | } -------------------------------------------------------------------------------- /tests/13.switch.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | @[export: 'a'] 5 | const a = 0 6 | 7 | fn main() { 8 | match a { 9 | 0 { // case comp body kind=CallExpr is_enum=true 10 | C.printf(c'bar\n') 11 | } 12 | else { 13 | C.printf(c'foo\n') 14 | } 15 | } 16 | match a { 17 | 0 { // case comp body kind=CallExpr is_enum=true 18 | C.printf(c'bar\n') 19 | } 20 | else { 21 | C.printf(c'foo\n') 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/14.default.c: -------------------------------------------------------------------------------- 1 | const int a = 0; 2 | 3 | void f() 4 | { 5 | switch(a) 6 | { 7 | default: 8 | case 0: 9 | case 1: 10 | break; 11 | } 12 | 13 | switch(a) 14 | { 15 | default: 16 | case 0: 17 | break; 18 | } 19 | 20 | switch(a) 21 | { 22 | case 0: 23 | break; 24 | case 1: 25 | break; 26 | default: 27 | break; 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /tests/14.default.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | @[export: 'a'] 5 | const a = 0 6 | 7 | fn f() { 8 | match a { 9 | 0, 1 {} 10 | else {} 11 | } 12 | match a { 13 | 0 { // case comp body kind=BreakStmt is_enum=true 14 | } 15 | else {} 16 | } 17 | match a { 18 | 0 { // case comp body kind=BreakStmt is_enum=true 19 | } 20 | 1 { // case comp body kind=BreakStmt is_enum=true 21 | } 22 | else {} 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/15.multi_var_decl.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | int n, r, sum = 0, temp; 3 | } -------------------------------------------------------------------------------- /tests/15.multi_var_decl.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | fn main() { 5 | n := 0 6 | r := 0 7 | sum := 0 8 | temp := 0 9 | } 10 | -------------------------------------------------------------------------------- /tests/16.literals.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | char c1 = '\\'; 3 | char c2 = '`'; 4 | char c3 = '.'; 5 | } -------------------------------------------------------------------------------- /tests/16.literals.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | fn main() { 5 | c1 := `\\` 6 | c2 := `\`` 7 | c3 := `.` 8 | } 9 | -------------------------------------------------------------------------------- /tests/17.partial_struct.c: -------------------------------------------------------------------------------- 1 | typedef struct TSTexture_t *TSTexture; 2 | -------------------------------------------------------------------------------- /tests/17.partial_struct.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | type TSTexture = voidptr 5 | -------------------------------------------------------------------------------- /tests/18.header_types.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | uint16_t ts_f32tof16(float f); 4 | -------------------------------------------------------------------------------- /tests/18.header_types.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module tests 3 | 4 | fn C.ts_f32tof16(f f32) u16 5 | 6 | pub fn ts_f32tof16(f f32) u16 { 7 | return C.ts_f32tof16(f) 8 | } 9 | -------------------------------------------------------------------------------- /tests/19.header_visibility_attribute.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define TS_CAPI __attribute__ ((visibility("default"))) 4 | 5 | TS_CAPI uint16_t ts_f32tof16(float f); 6 | -------------------------------------------------------------------------------- /tests/19.header_visibility_attribute.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module tests 3 | 4 | fn C.ts_f32tof16(f f32) u16 5 | 6 | pub fn ts_f32tof16(f f32) u16 { 7 | return C.ts_f32tof16(f) 8 | } 9 | -------------------------------------------------------------------------------- /tests/2.if.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | if (10 > 5) { 5 | printf("10 > 5"); 6 | } 7 | else { 8 | printf("no"); 9 | } 10 | int x = 10; 11 | int y = 20; 12 | if (y > x) { 13 | printf("y > x"); 14 | } 15 | if (y + 1 > x); // TODO 16 | if (1) printf("one"); 17 | else if (1 > 0 || x < y || (x > y && x < y + 1)) { 18 | printf("two"); 19 | printf("three"); 20 | } 21 | return 0; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /tests/2.if.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | fn main() { 5 | if 10 > 5 { 6 | C.printf(c'10 > 5') 7 | } else { 8 | C.printf(c'no') 9 | } 10 | x := 10 11 | y := 20 12 | if y > x { 13 | C.printf(c'y > x') 14 | } 15 | if y + 1 > x { 16 | } 17 | // TODO 18 | if 1 { 19 | C.printf(c'one') 20 | } else if 1 > 0 || x < y || (x > y && x < y + 1) { 21 | C.printf(c'two') 22 | C.printf(c'three') 23 | } 24 | return 25 | } 26 | -------------------------------------------------------------------------------- /tests/20.header_duplicate_type_declaration.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "IGNORE_header_duplicate_type_declaration_2.h" 4 | 5 | typedef int dup_typ; 6 | -------------------------------------------------------------------------------- /tests/20.header_duplicate_type_declaration.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module tests 3 | 4 | type Dup_typ = int 5 | -------------------------------------------------------------------------------- /tests/21.header_uninited_global_var.h: -------------------------------------------------------------------------------- 1 | #define TS_CAPI __attribute__ ((visibility("default"))) 2 | 3 | TS_CAPI extern const char* tsMeshMaterialTypeBump; 4 | -------------------------------------------------------------------------------- /tests/21.header_uninited_global_var.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module tests 3 | -------------------------------------------------------------------------------- /tests/22.getline_linux.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | char *input = NULL; 6 | size_t len = 0; 7 | ssize_t read; 8 | printf("Enter text (Ctrl+D to quit):\n"); 9 | read = getline(&input, &len, stdin); 10 | 11 | if (read != -1) { 12 | printf("Entered: %s", input); 13 | } else { 14 | printf("error reading input\n"); 15 | } 16 | 17 | free(input); 18 | return 0; 19 | } -------------------------------------------------------------------------------- /tests/22.getline_linux.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | fn main() { 5 | input := (unsafe { nil }) 6 | len := 0 7 | read := isize(0) 8 | C.printf(c'Enter text (Ctrl+D to quit):\n') 9 | read = C.getline(&input, &len, C.stdin) 10 | if read != -1 { 11 | C.printf(c'Entered: %s', input) 12 | } else { 13 | C.printf(c'error reading input\n') 14 | } 15 | C.free(input) 16 | return 17 | } 18 | -------------------------------------------------------------------------------- /tests/22.getline_macos.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | char *input = NULL; 6 | size_t len = 0; 7 | ssize_t read; 8 | printf("Enter text (Ctrl+D to quit):\n"); 9 | read = getline(&input, &len, stdin); 10 | 11 | if (read != -1) { 12 | printf("Entered: %s", input); 13 | } else { 14 | printf("error reading input\n"); 15 | } 16 | 17 | free(input); 18 | return 0; 19 | } -------------------------------------------------------------------------------- /tests/22.getline_macos.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | fn main() { 5 | input := (unsafe { nil }) 6 | len := 0 7 | read := isize(0) 8 | C.printf(c'Enter text (Ctrl+D to quit):\n') 9 | read = C.getline(&input, &len, C.__stdinp) 10 | if read != -1 { 11 | C.printf(c'Entered: %s', input) 12 | } else { 13 | C.printf(c'error reading input\n') 14 | } 15 | C.free(input) 16 | return 17 | } 18 | -------------------------------------------------------------------------------- /tests/23.sizeof.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | char hello[] = "Hello, unistd world!\n"; 4 | write ( 1, hello, sizeof hello ); 5 | return 0; } -------------------------------------------------------------------------------- /tests/23.sizeof.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | fn main() { 5 | hello := c'Hello, unistd world!\n' 6 | C.write(1, hello, sizeof(hello)) 7 | return 8 | } 9 | -------------------------------------------------------------------------------- /tests/24.typedef_struct.h: -------------------------------------------------------------------------------- 1 | typedef struct 2 | { 3 | float x, y; 4 | } ImVec2; 5 | 6 | typedef struct ImVec3 ImVec3; 7 | struct ImVec3 8 | { 9 | float x, y, z; 10 | }; 11 | 12 | struct ImVec4 13 | { 14 | float x, y, z, w; 15 | }; 16 | typedef struct ImVec4 ImVec4; 17 | 18 | struct ImGuiTextRange 19 | { 20 | const char *b; 21 | const char *e; 22 | }; 23 | typedef struct ImGuiTextRange ImGuiTextRange; 24 | 25 | typedef struct ImVector_ImGuiTextRange 26 | { 27 | int Size; 28 | int Capacity; 29 | ImGuiTextRange *Data; 30 | } ImVector_ImGuiTextRange; 31 | 32 | struct ImGuiTextFilter 33 | { 34 | char InputBuf[256]; 35 | ImVector_ImGuiTextRange Filters; 36 | int CountGrep; 37 | }; 38 | typedef struct ImGuiTextRange ImGuiTextRange; 39 | 40 | typedef unsigned short ImWchar16; 41 | typedef ImWchar16 ImWchar; 42 | 43 | typedef struct ImGuiContext ImGuiContext; 44 | struct ImGuiContext; 45 | struct ImGuiContext 46 | { 47 | int Initialized; 48 | }; -------------------------------------------------------------------------------- /tests/24.typedef_struct.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module tests 3 | 4 | struct ImVec2 { 5 | x f32 6 | y f32 7 | } 8 | 9 | struct ImVec3 { 10 | x f32 11 | y f32 12 | z f32 13 | } 14 | 15 | struct ImVec4 { 16 | x f32 17 | y f32 18 | z f32 19 | w f32 20 | } 21 | 22 | struct ImGuiTextRange { 23 | b &i8 24 | e &i8 25 | } 26 | 27 | struct ImVector_ImGuiTextRange { 28 | size int 29 | capacity int 30 | data &ImGuiTextRange 31 | } 32 | 33 | type ImWchar16 = u16 34 | 35 | struct ImGuiContext { 36 | initialized int 37 | } 38 | -------------------------------------------------------------------------------- /tests/25.return_val_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | bool foo(int value) 4 | { 5 | return value == 2; 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/25.return_val_2.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | fn foo(value int) bool { 5 | return value == 2 6 | } 7 | 8 | -------------------------------------------------------------------------------- /tests/26.assign_zerof.c: -------------------------------------------------------------------------------- 1 | int main() { 2 | double a = 0.0f; 3 | double b = 0; 4 | float c = 0; 5 | } 6 | -------------------------------------------------------------------------------- /tests/26.assign_zerof.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | fn main() { 5 | a := 0.0 6 | b := f64(0) 7 | c := f32(0) 8 | } 9 | -------------------------------------------------------------------------------- /tests/3.if_switch_enum.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef enum { 4 | one, two 5 | } Number; 6 | 7 | Number return_number() { 8 | return one; 9 | } 10 | 11 | int main() { 12 | if (10 > 5) { 13 | printf("10 > 5"); 14 | } 15 | else { 16 | printf("no"); 17 | } 18 | int x = 10; 19 | int y = 20; 20 | if (y > x) { 21 | printf("y > x"); 22 | } 23 | if (y + 1 > x); // TODO 24 | if (1) printf("one"); 25 | else if (1 > 0 || x < y || (x > y && x < y + 1)) { 26 | printf("two"); 27 | printf("three"); 28 | } 29 | switch (x) { 30 | case 0: return 0; 31 | case 1: printf("one"); printf("ONE"); break; 32 | case 2: printf("two"); if (1 > 0) { printf("OK"); } break; 33 | } 34 | Number n = one; 35 | switch (n) { 36 | //case one: printf("one!"); int x = one + 1; break; 37 | //x := .one + 1 38 | case one: printf("one"); break; 39 | case two: printf("two"); break; 40 | } 41 | // handle enum <=> int in C: enum switch needs explicit casts to ints 42 | int m = 0; 43 | switch (m) { 44 | case one: printf("one"); break; 45 | case two: printf("two"); break; 46 | } 47 | return 0; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /tests/3.if_switch_enum.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | enum Number { 5 | one 6 | two 7 | } 8 | 9 | fn return_number() Number { 10 | return Number.one 11 | } 12 | 13 | fn main() { 14 | if 10 > 5 { 15 | C.printf(c'10 > 5') 16 | } else { 17 | C.printf(c'no') 18 | } 19 | x := 10 20 | y := 20 21 | if y > x { 22 | C.printf(c'y > x') 23 | } 24 | if y + 1 > x { 25 | } 26 | // TODO 27 | if 1 { 28 | C.printf(c'one') 29 | } else if 1 > 0 || x < y || (x > y && x < y + 1) { 30 | C.printf(c'two') 31 | C.printf(c'three') 32 | } 33 | match x { 34 | 0 { // case comp body kind=ReturnStmt is_enum=false 35 | return 36 | } 37 | 1 { // case comp body kind=CallExpr is_enum=false 38 | C.printf(c'one') 39 | C.printf(c'ONE') 40 | } 41 | 2 { // case comp body kind=CallExpr is_enum=false 42 | C.printf(c'two') 43 | if 1 > 0 { 44 | C.printf(c'OK') 45 | } 46 | } 47 | else {} 48 | } 49 | n := Number.one 50 | match n { 51 | // case one: printf("one!"); int x = one + 1; break; 52 | // x := .one + 1 53 | .one { // case comp body kind=CallExpr is_enum=true 54 | C.printf(c'one') 55 | } 56 | .two { // case comp body kind=CallExpr is_enum=true 57 | C.printf(c'two') 58 | } 59 | else {} 60 | } 61 | // handle enum <=> int in C: enum switch needs explicit casts to ints 62 | m := 0 63 | match Number(m) { 64 | .one { // case comp body kind=CallExpr is_enum=true 65 | C.printf(c'one') 66 | } 67 | .two { // case comp body kind=CallExpr is_enum=true 68 | C.printf(c'two') 69 | } 70 | else {} 71 | } 72 | return 73 | } -------------------------------------------------------------------------------- /tests/4.for.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void for_test() { 4 | for (int i = 0; i < 10; i++) { 5 | printf("i = %d\n", i); 6 | } 7 | for (int i = 0; i < 10; i++) printf("single line"); 8 | // 9 | int x = 1; 10 | int sum = 0; 11 | while (x < 10) { 12 | x++; 13 | sum += x; 14 | } 15 | // 16 | while (1) { 17 | printf("inf loop"); 18 | break; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/4.for.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | fn for_test() { 5 | for i := 0; i < 10; i++ { 6 | C.printf(c'i = %d\n', i) 7 | } 8 | for i := 0; i < 10; i++ { 9 | C.printf(c'single line') 10 | } 11 | // 12 | x := 1 13 | sum := 0 14 | for x < 10 { 15 | x++ 16 | sum += x 17 | } 18 | // 19 | for 1 { 20 | C.printf(c'inf loop') 21 | break 22 | } 23 | } -------------------------------------------------------------------------------- /tests/5.struct.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const int PI= 314; 4 | 5 | struct User { 6 | char *name; 7 | int age; 8 | }; 9 | 10 | // lots of structs are typedef'ed in C 11 | typedef struct { 12 | char *name; 13 | int age; 14 | float CapitalizedField; // fields in V must be lower case 15 | } TUser; 16 | 17 | // struct names have to be capitalized in V 18 | struct small { 19 | int foo; 20 | }; 21 | 22 | struct small3 { 23 | int foo; 24 | }; 25 | 26 | struct small2 { 27 | struct small struct_field; // make sure field types are capitalized 28 | struct small* struct_field_ptr; 29 | struct small3** struct_field_ptr2; 30 | }; 31 | 32 | void small_fn(struct small param) { // make sure arg types are capitalized 33 | 34 | } 35 | 36 | typedef unsigned int angle_t; 37 | 38 | enum Color { 39 | red, green, blue, 40 | }; 41 | 42 | void handle_user(struct User user) { 43 | 44 | } 45 | 46 | void handle_tuser(TUser user) { 47 | 48 | } 49 | 50 | void multi_assign() { 51 | int aa = 0; 52 | int bb = 10; 53 | int cc = 20; 54 | aa = bb = cc; 55 | } 56 | 57 | void x(int pi) {} 58 | 59 | #define arrlen(array) (sizeof(array) / sizeof(*array)) 60 | 61 | static int *weapon_keys[] = { 0, 0, 0 }; 62 | void sizeof_array() { 63 | int x = 10; 64 | int c = sizeof(x); 65 | int n = arrlen(weapon_keys); 66 | } 67 | 68 | int checkcoord[12][4] = 69 | { 70 | {3,0,2,1}, 71 | {3,0,2,0}, 72 | {3,1,2,0}, 73 | {0,0,0,0}, 74 | {2,0,2,1}, 75 | {0,0,0,0}, 76 | {3,1,3,0}, 77 | {0,0,0,0}, 78 | {2,0,3,1}, 79 | {2,1,3,1}, 80 | {2,1,3,0} 81 | }; 82 | 83 | void i_error(char* s, ...) { 84 | puts(s); 85 | } 86 | 87 | static unsigned long long sixtyfour(void) { 88 | return 64; 89 | } 90 | 91 | typedef union { 92 | int a; 93 | char b; 94 | } MyUnion; 95 | 96 | struct AnonStructTest { 97 | int age; 98 | struct { 99 | int bar; 100 | char* baz; 101 | } foo; 102 | float last_field; 103 | }; 104 | 105 | struct { 106 | int fff; 107 | char* sss; 108 | } global_state_using_anon_struct; 109 | 110 | int main() { 111 | struct User user; 112 | user.age = 20; 113 | user.name = "Bob"; 114 | printf("age=%d", user.age); 115 | handle_user(user); 116 | 117 | unsigned long long sf = sixtyfour(); 118 | printf("sixtyfour=%lld", sf); 119 | // TODO 120 | // struct User user2 = { .age = 30, .name = "Peter" }; 121 | TUser user2; 122 | user2.age = 30; 123 | user2.name = "Peter"; 124 | handle_tuser(user2); 125 | // 126 | struct small s; // make sure struct inits are capitalized 127 | struct small s2 = { .foo = 10 }; 128 | x(PI); // make sure cap consts stay capitalized 129 | return 0; 130 | } 131 | -------------------------------------------------------------------------------- /tests/5.struct.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | @[export: 'PI'] 5 | const PI = 314 6 | 7 | struct User { 8 | name &i8 9 | age int 10 | } 11 | 12 | // lots of structs are typedef'ed in C 13 | struct TUser { 14 | name &i8 15 | age int 16 | capitalizedField f32 17 | // fields in V must be lower case 18 | } 19 | 20 | // struct names have to be capitalized in V 21 | struct Small { 22 | foo int 23 | } 24 | 25 | struct Small3 { 26 | foo int 27 | } 28 | 29 | struct Small2 { 30 | struct_field Small 31 | // make sure field types are capitalized 32 | struct_field_ptr &Small 33 | struct_field_ptr2 &&Small3 34 | } 35 | 36 | fn small_fn(param Small) { 37 | // make sure arg types are capitalized 38 | } 39 | 40 | type Angle_t = u32 41 | 42 | enum Color { 43 | red 44 | green 45 | blue 46 | } 47 | 48 | fn handle_user(user User) { 49 | } 50 | 51 | fn handle_tuser(user TUser) { 52 | } 53 | 54 | fn multi_assign() { 55 | aa := 0 56 | bb := 10 57 | cc := 20 58 | aa = cc 59 | bb = aa 60 | } 61 | 62 | fn x(pi int) { 63 | } 64 | 65 | @[export: 'weapon_keys'] 66 | const weapon_keys = [0, 0, 0]! 67 | 68 | fn sizeof_array() { 69 | x := 10 70 | c := sizeof(x) 71 | n := (sizeof(weapon_keys) / sizeof(*weapon_keys)) 72 | } 73 | 74 | @[export: 'checkcoord'] 75 | const checkcoord = [[3, 0, 2, 1]!, [3, 0, 2, 0]!, [3, 1, 2, 0]!, 76 | [0, 0, 0, 0]!, [2, 0, 2, 1]!, [0, 0, 0, 0]!, [3, 1, 3, 0]!, 77 | [0, 0, 0, 0]!, [2, 0, 3, 1]!, [2, 1, 3, 1]!, [2, 1, 3, 0]!]! 78 | 79 | @[c2v_variadic] 80 | fn i_error(s ...&i8) { 81 | C.puts(s) 82 | } 83 | 84 | fn sixtyfour() i64 { 85 | return 64 86 | } 87 | 88 | union MyUnion { 89 | a int 90 | b i8 91 | } 92 | 93 | struct AnonStructTest { 94 | age int 95 | foo struct { 96 | bar int 97 | baz &i8 98 | } 99 | 100 | last_field f32 101 | } 102 | 103 | struct AnonStruct_105 { 104 | fff int 105 | sss &i8 106 | } 107 | 108 | @[weak] 109 | __global global_state_using_anon_struct AnonStruct_105 110 | 111 | fn main() { 112 | user := User{} 113 | user.age = 20 114 | user.name = c'Bob' 115 | C.printf(c'age=%d', user.age) 116 | handle_user(user) 117 | sf := sixtyfour() 118 | C.printf(c'sixtyfour=%lld', sf) 119 | // TODO 120 | // struct User user2 = { .age = 30, .name = "Peter" }; 121 | user2 := TUser{} 122 | user2.age = 30 123 | user2.name = c'Peter' 124 | handle_tuser(user2) 125 | // 126 | s := Small{} 127 | // make sure struct inits are capitalized 128 | s2 := Small{ 129 | foo: 10 130 | } 131 | 132 | x(PI) 133 | // make sure cap consts stay capitalized 134 | return 135 | } 136 | -------------------------------------------------------------------------------- /tests/6.types.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // standard types should be lower-cased 6 | typedef unsigned short v_u16; 7 | typedef float v_f32; 8 | typedef size_t v_usize; 9 | typedef void *v_voidptr; 10 | typedef bool v_bool; 11 | 12 | // disabled for macOS/Linux compatibility 13 | //#include 14 | //typedef ptrdiff_t v_isize; 15 | 16 | // not sure how this is supposed to work 17 | typedef intptr_t c_intptr_t; 18 | 19 | int main() 20 | { 21 | void *pointers[8]; 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /tests/6.types.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | // standard types should be lower-cased 5 | type V_u16 = u16 6 | type V_f32 = f32 7 | type V_usize = usize 8 | type V_voidptr = voidptr 9 | type V_bool = bool 10 | 11 | // disabled for macOS/Linux compatibility 12 | //#include 13 | // typedef ptrdiff_t v_isize; 14 | // not sure how this is supposed to work 15 | type C_intptr_t = C.intptr_t 16 | 17 | fn main() { 18 | pointers := [8]voidptr{} 19 | return 20 | } -------------------------------------------------------------------------------- /tests/7.api_types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | // Standard types and macros that are always available. 8 | 9 | // Types 10 | 11 | // Represents a 2D vector. 12 | typedef struct tm_vec2_t 13 | { 14 | float x, y; 15 | } tm_vec2_t; 16 | 17 | // Represents a 3D vector. 18 | typedef struct tm_vec3_t 19 | { 20 | float x, y, z; 21 | } tm_vec3_t; 22 | 23 | // Represents a 3D vector in double precision. 24 | typedef struct tm_vec3d_t 25 | { 26 | double x, y, z; 27 | } tm_vec3d_t; 28 | 29 | // Represents a 4D vector. 30 | typedef struct tm_vec4_t 31 | { 32 | float x, y, z, w; 33 | } tm_vec4_t; 34 | 35 | // Represents a 4x4 matrix. 36 | typedef struct tm_mat44_t 37 | { 38 | float xx, xy, xz, xw; 39 | float yx, yy, yz, yw; 40 | float zx, zy, zz, zw; 41 | float wx, wy, wz, ww; 42 | } tm_mat44_t; 43 | 44 | // Represents a transform in TRS form. 45 | typedef struct tm_transform_t 46 | { 47 | tm_vec3_t pos; 48 | tm_vec4_t rot; 49 | tm_vec3_t scl; 50 | } tm_transform_t; 51 | 52 | // Represents a rectangle. 53 | typedef struct tm_rect_t 54 | { 55 | float x, y, w, h; 56 | } tm_rect_t; 57 | 58 | // Used to represent a string slice with pointer and length. 59 | // 60 | // This lets you reason about parts of a string, which you are not able to do with standard 61 | // NULL-terminated strings. 62 | typedef struct tm_str_t 63 | { 64 | // Pointer to string bytes. 65 | const char *data; 66 | 67 | // Length of the string. 68 | uint32_t size; 69 | 70 | // If set to *true*, indicates that there is an allocated NULL-byte after the string data. I.e. 71 | // `data[size] == 0`. This means that `data` can be used immediately as a C string without 72 | // needing to copy it to a separate memory area. 73 | // 74 | // If *false*, there may or may not be a NULL-byte at the end of the string and accessing 75 | // `data[size]` may cause an access violation, so if you want to use it as a C-string you have 76 | // to copy it to a new memory area and append a NULL byte. 77 | // 78 | // Note that the NULL-byte is never included in the `size`. 79 | uint32_t null_terminated; 80 | } tm_str_t; 81 | 82 | // Creates a [[tm_str_t]] from a `char *` `s`. 83 | #define tm_str(s) (TM_LITERAL(tm_str_t){ (s), s ? (uint32_t)strlen(s) : 0, true }) 84 | 85 | // Creates a [[tm_str_t]] from a static string `s`. As [[tm_str()]], but uses `sizeof()` instead of 86 | // `strlen()` to determine the length of the string. This means it avoids the `strlen()` overhead 87 | // and can be used to initialize static data, but it can only be used with static strings. 88 | #define TM_STR(s) (TM_LITERAL(tm_str_t){ ("" s ""), (uint32_t)(sizeof("" s "") - 1), true }) 89 | 90 | // Creates a [[tm_str_t]] from a start pointer `s` and end pointer `e`. 91 | #define tm_str_range(s, e) (e > s ? TM_LITERAL(tm_str_t){ (s), (uint32_t)((e) - (s)), false } : TM_LITERAL(tm_str_t){ 0 }) 92 | 93 | // Represents a time from the system clock. 94 | // 95 | // You can assume the clock to be monotonically increasing, i.e. a larger `opaque` value represents 96 | // a later time, but you shouldn't assume anything else about what the `opaque` value represents or 97 | // the resolution of the timer. Instead, use [[tm_os_time_api->delta()]] to convert elapsed time to 98 | // seconds. 99 | typedef struct tm_clock_o 100 | { 101 | uint64_t opaque; 102 | } tm_clock_o; 103 | 104 | // Represents a unique 128-bit identifier. 105 | typedef struct tm_uuid_t 106 | { 107 | uint64_t a; 108 | uint64_t b; 109 | } tm_uuid_t; 110 | 111 | // Represents an 8-bit per channel RGBA color in sRGB color space (Note: alpha is always linear.) 112 | typedef struct tm_color_srgb_t 113 | { 114 | uint8_t r, g, b, a; 115 | } tm_color_srgb_t; 116 | 117 | // Converts an `uint32_t` to an [[tm_color_srgb_t]] color. 118 | // 119 | // The nibbles in the `uint32_t` hex representation specify TRGB, where T is transparancy (0x00 120 | // means fully opaque and 0xff fully transparent, i.e. it is the invert of alpha). This lets you 121 | // leave the highest nibble out for an opaque color (the most common case), but specify it if 122 | // you want transparency. 123 | // 124 | // Hex | Color 125 | // ---------- | ------------------- 126 | // 0x00 | Black 127 | // 0xff0000 | Red 128 | // 0xff000000 | Transparent black 129 | // 0x80ffff00 | 50 % transparent yellow 130 | #define TM_RGB(c) (TM_LITERAL(tm_color_srgb_t){ 0xff & (c >> 16), 0xff & (c >> 8), 0xff & (c >> 0), 0xff - (0xff & (c >> 24)) }) 131 | 132 | // Type representing a type in The Truth. 133 | typedef struct tm_tt_type_t 134 | { 135 | uint64_t u64; 136 | } tm_tt_type_t; 137 | 138 | // ID representing an object in The Truth. 139 | typedef struct tm_tt_id_t 140 | { 141 | union 142 | { 143 | // Used for comparing objects or storing them in hash tables. 144 | uint64_t u64; 145 | 146 | struct 147 | { 148 | // Type of the object. 149 | uint64_t type : 10; 150 | // Generation of the object, used to distinguish objects created at the same index. 151 | uint64_t generation : 22; 152 | // Index of the object. 153 | uint64_t index : 32; 154 | }; 155 | }; 156 | } tm_tt_id_t; 157 | 158 | // Returns the type of `id`. 159 | static inline tm_tt_type_t tm_tt_type(tm_tt_id_t id) 160 | { 161 | tm_tt_type_t res = { id.type }; 162 | return res; 163 | } 164 | 165 | // Type representing an undo scope in The Truth. 166 | typedef struct tm_tt_undo_scope_t 167 | { 168 | uint64_t u64; 169 | } tm_tt_undo_scope_t; 170 | 171 | // Used to represent API versions. 172 | // 173 | // Version numbers follow the SemVer 2.0.0 specification: 174 | // 175 | // * The major version is bumped for breaking API changes. 176 | // * The minor version is bumped when new functionality is added in a backwards-compatible manner. 177 | // * The patch version is bumped for backwards-compatible bug fixes. 178 | // * If the major version is 0, the API is considered unstable and under development. In this case, 179 | // nothing should be assumed about backwards compatibility. 180 | // 181 | // See: https://semver.org/spec/v2.0.0.html 182 | // 183 | // !!! WARNING: Be careful about backwards compatibility 184 | // The default action should be to bump the major version whenever you change something in the 185 | // API. If you are considering just bumping the minor or patch version, you must make 100 % 186 | // sure that your changes are backwards compatible, since otherwise you will break existing 187 | // plugins without any warning. 188 | typedef struct tm_version_t 189 | { 190 | // Bumped when breaking changes are made to the API. For example: 191 | // 192 | // * Adding functions in the middle of the API. 193 | // * Changing the number of parameters to a function or their types. 194 | // * Changing the return type of a function. 195 | // * Changing the fields of a struct. 196 | uint32_t major; 197 | 198 | // Bumped when new functionality is added to the API in a backwards-compatible manner. 199 | // Changes are backwards compatible if a caller using an old version of the header file can 200 | // still call into the new version of the ABI without errors. Examples of backwards-compatible 201 | // changes are: 202 | // 203 | // * Adding new functions to the end of the API. 204 | // * Repurposing unused bits in structs. 205 | // 206 | // If you want to change an API and only bump the minor version you should make sure to take 207 | // special care that your changes are really backwards compatible. 208 | uint32_t minor; 209 | 210 | // Bumped for backwards-compatible bug fixes. 211 | uint32_t patch; 212 | } tm_version_t; 213 | 214 | // Creates a [[tm_version_t]] literal. 215 | #define TM_VERSION(major, minor, patch) (TM_LITERAL(tm_version_t){ major, minor, patch }) 216 | 217 | // The [[TM_VERSION()]] macro cannot be used to initialize constant objects in Visual Studio. 218 | // (It will give the error "initializer not constant".) This macro can be used as an alternative 219 | // for constant initializations. 220 | // 221 | // !!! TODO: TODO 222 | // Having two separate macros for this is not very elegant. See if we can find a better 223 | // solution. 224 | #define TM_VERSION_INITIALIZER(major, minor, patch) \ 225 | { \ 226 | major, minor, patch \ 227 | } 228 | 229 | // Build configuration 230 | // 231 | // These macros are defined in the build file `premake5.lua`, but listed here for documentation 232 | // purposes. 233 | 234 | #if 0 235 | 236 | // Defined for Windows builds. 237 | #define TM_OS_WINDOWS 238 | 239 | // Defined for OS X builds. 240 | #define TM_OS_MACOSX 241 | 242 | // Defined for Linux builds. 243 | #define TM_OS_LINUX 244 | 245 | // Defined for POSIX builds (OS X or Linux). 246 | #define TM_OS_POSIX 247 | 248 | // If defined, the main job runs on a thread, not a fiber. 249 | #define TM_NO_MAIN_FIBER 250 | 251 | // Defined for debug builds. 252 | #define TM_CONFIGURATION_DEBUG 253 | 254 | // Defined for release builds. 255 | #define TM_CONFIGURATION_RELEASE 256 | 257 | #endif 258 | 259 | // String hashes 260 | 261 | #if defined(_MSC_VER) && !defined(__clang__) 262 | 263 | // `#define TM_USE_STRHASH_TYPE` controls whether we should use a custom type [[tm_strhash_t]] for 264 | // string hashes, or if they should just be `uint64_t`. Currently, it is set to `0` when compiling 265 | // using MSVC and `1` otherwise. 266 | // 267 | // We cannot use the [[tm_strhash_t]] type with the Visual Studio compiler, because it doesn't see 268 | // our [[TM_STATIC_HASH()]] macro as a constant, and thus will generate 269 | // [C2099](https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/compiler-error-c2099?view=msvc-160) 270 | // compiler error. errors whenever it is used to initialize a global variable. This is unfortunate, 271 | // because it means we can't get type safe string hashes in Visual Studio. 272 | // 273 | // Hopefully, this will be fixed in a future Visual Studio release and we can transition fully to 274 | // the [[tm_strhash_t]] type. 275 | #define TM_USE_STRHASH_TYPE 0 276 | 277 | #else 278 | 279 | // tm_docgen ignore 280 | #define TM_USE_STRHASH_TYPE 1 281 | 282 | #endif 283 | 284 | #if TM_USE_STRHASH_TYPE 285 | 286 | // Type-safe representation of a hashed string. 287 | // 288 | // !!! WARNING: WARNING 289 | // In Visual Studio, string hashes won't use this string type, instead 290 | // [[tm_strhash_t]] will be typedefed to `uint64_t`. The reason for this is that the 291 | // [[TM_STATIC_HASH()]] macro is not seen as a constant by the MSVC compiler and thus using it 292 | // to initialize global variables yields the 293 | // [C2099](https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/compiler-error-c2099?view=msvc-160) 294 | // compiler error. 295 | // 296 | // This means that the type safety of string hashes won't be checked when compiling with MSVC. 297 | // Make sure you build your code under clang too, with `tmbuild --clang` to check the type 298 | // safety of string hashes. Also, always use the macros [[TM_STRHASH()]] and 299 | // [[TM_STRHASH_U64()]] to convert between [[tm_strhash_t]] and `uint64_t`. This ensures that 300 | // the conversions work on all platforms. 301 | typedef struct tm_strhash_t 302 | { 303 | uint64_t u64; 304 | } tm_strhash_t; 305 | 306 | // Converts a `uint64_t` to a [[tm_strhash_t]]. 307 | #define TM_STRHASH(x) (TM_LITERAL(tm_strhash_t){ x }) 308 | 309 | // Extracts the `uint64_t` of a [[tm_strhash_t]] value `x`. 310 | #define TM_STRHASH_U64(x) ((x).u64) 311 | 312 | #else 313 | 314 | // tm_docgen ignore 315 | typedef uint64_t tm_strhash_t; 316 | 317 | // tm_docgen ignore 318 | #define TM_STRHASH(x) (x) 319 | 320 | // tm_docgen ignore 321 | #define TM_STRHASH_U64(x) (x) 322 | 323 | #endif 324 | 325 | // Returns true if the the two [[tm_strhash_t]] are equal. 326 | #define TM_STRHASH_EQUAL(a, b) (TM_STRHASH_U64(a) == TM_STRHASH_U64(b)) 327 | 328 | // Used for static string hashes. The `hash.exe` utility checks the entire source code and makes 329 | // sure that wherever you use [[TM_STATIC_HASH()]], the numeric value `v` matches the actual hash of the 330 | // string `s` (if not, the code is updated). 331 | // 332 | // When you create a new static hash, don't enter the numeric value, just the string: 333 | // `TM_STATIC_HASH("bla")`. 334 | // 335 | // This ensures that the macro fails to compile until you run `hash.exe` to generate a numeric 336 | // value. 337 | // 338 | // [[TM_STATIC_HASH()]] returns a constant value of type [[tm_strhash_t]]. 339 | // 340 | // 344 | #define TM_STATIC_HASH(s, v) TM_STRHASH(sizeof("" s "") > 0 ? v : v) 345 | 346 | // Macros 347 | 348 | #ifdef __cplusplus 349 | 350 | // tm_docgen ignore 351 | #define TM_LITERAL(T) T 352 | 353 | #else 354 | 355 | // Macro for creating a struct literal of type `T` that works both in C and C++. Use as: 356 | // 357 | // ~~~c 358 | // x = TM_LITERAL(tm_vec2_t) {x, y} 359 | // ~~~ 360 | // 361 | // In C, this turns into `(tm_vec2_t){0, 0}` and in C++ to `tm_vec2_t{0, 0}`. 362 | // 363 | // Note that use of [[TM_LITERAL()]] is only needed in .h and .inl files that might be included from 364 | // both C and C++. In .c and .cpp file you should just use the native literal format instead of 365 | // relying on [[TM_LITERAL()]]. 366 | #define TM_LITERAL(T) (T) 367 | 368 | #endif 369 | 370 | #if defined(_MSC_VER) 371 | 372 | // Marks a function to be exported to DLLs. 373 | #define TM_DLL_EXPORT __declspec(dllexport) 374 | 375 | #else 376 | 377 | // tm_docgen ignore 378 | #define TM_DLL_EXPORT __attribute__((visibility("default"))) 379 | 380 | #endif 381 | 382 | #if defined(TM_OS_MACOSX) 383 | #ifndef __restrict 384 | 385 | // tm_docgen ignore 386 | // 387 | // This is not ideal -- preferably we would want to use `restrict` rather than `__restrict` as our 388 | // `restrict` keyword, since that is what the C standard specifies. However, VS does not support 389 | // this, and if we try `#define restrict __restrict` we run into trouble, because some of the 390 | // windows headers actually use `restrict` already. 391 | #define __restrict restrict 392 | 393 | #endif 394 | #endif 395 | 396 | #if defined(_MSC_VER) && !defined(__clang__) 397 | 398 | // Mark struct fields in header files as atomic. 399 | #define TM_ATOMIC 400 | 401 | #else 402 | 403 | // tm_docgen ignore 404 | #define TM_ATOMIC _Atomic 405 | 406 | #endif 407 | 408 | // tm_docgen off 409 | 410 | // Generate an error if this file was included in a C++ file, without wrapping the include in extern 411 | // "C". If you forget extern "C", the first declaration will get C++ linkage and you will then get a 412 | // conflict on the second declaration. 413 | #ifdef __cplusplus 414 | void use_extern_c_wrapper_to_include_the_machinery_headers_in_cpp_files(void); 415 | extern "C" void use_extern_c_wrapper_to_include_the_machinery_headers_in_cpp_files(void); 416 | #endif 417 | 418 | // tm_docgen on 419 | 420 | // Returns the `name` as a string. 421 | #define TM_STRINGIFY(name) #name 422 | 423 | // tm_docgen ignore 424 | #define TM_CONCAT_IMPL(a, b) a##b 425 | 426 | // Concatenates `a` and `b` , allowing you to expand macros before doing the concatenation. This is 427 | // useful when used with builtin macros like `__LINE__` or `__COUNTER__`. `x##__COUNTER__` doesn't 428 | // expand to `x1` since a macro is not expanded if preceded by `#` or `##`, but `TM_CONCAT(x, 429 | // __COUNTER__)` works. 430 | #define TM_CONCAT(a, b) TM_CONCAT_IMPL(a, b) 431 | 432 | // Generates a unique name for a macro variable, based on `name`. 433 | #define TM_MACRO_VAR(name) TM_CONCAT(name, __LINE__) 434 | 435 | // Declares a field that pads a struct with the specified number of bytes. To ensure that structs 436 | // are completely zero-initialized by designated initializers, we require all struct padding to be 437 | // explicitly declared using this macro. (We enable warnings that trigger if there is undeclared 438 | // padding in a struct.) 439 | // 440 | // Example: 441 | // 442 | // ~~~c 443 | // struct x { 444 | // uint32_t a; 445 | // // This padding is needed since `b` needs to be aligned to a 64-bit boundary. 446 | // TM_PAD(4); 447 | // uint64_t b; 448 | // }; 449 | // ~~~ 450 | // 451 | // Note that in situations where types have different sizes on different platforms you may need to 452 | // pad with different amounts: 453 | // 454 | // ~~~c 455 | // TM_PAD(8 - sizeof(x)); 456 | // ~~~ 457 | #define TM_PAD(n) char TM_MACRO_VAR(_padding_)[n] 458 | 459 | #if defined(TM_OS_WINDOWS) 460 | 461 | // Disable warnings about padding inserted into structs. Use this before including external headers 462 | // that do not explicitly declare padding. Restore the padding warning afterwards with 463 | // [[TM_RESTORE_PADDING_WARNINGS]]. 464 | #define TM_DISABLE_PADDING_WARNINGS \ 465 | __pragma(warning(push)) \ 466 | __pragma(warning(disable : 4121 4820)) 467 | 468 | // Restore padding warnings disabled by [[TM_DISABLE_PADDING_WARNINGS]]. 469 | #define TM_RESTORE_PADDING_WARNINGS \ 470 | __pragma(warning(pop)) 471 | 472 | #elif defined(__clang__) 473 | // tm_docgen ignore 474 | #define TM_DISABLE_PADDING_WARNINGS \ 475 | _Pragma("clang diagnostic push") \ 476 | _Pragma("clang diagnostic ignored \"-Wpadded\"") 477 | // tm_docgen ignore 478 | #define TM_RESTORE_PADDING_WARNINGS \ 479 | _Pragma("clang diagnostic pop") 480 | #elif defined(__GNUC__) || defined(__GNUG__) 481 | // tm_docgen ignore 482 | #define TM_DISABLE_PADDING_WARNINGS \ 483 | _Pragma("GCC diagnostic push") \ 484 | _Pragma("GCC diagnostic ignored \"-Wpadded\"") 485 | // tm_docgen ignore 486 | #define TM_RESTORE_PADDING_WARNINGS \ 487 | _Pragma("GCC diagnostic pop") 488 | #endif 489 | 490 | #if !defined(__cplusplus) 491 | 492 | // Used to implement "inheritance" -- inserting the members of one struct into another, with a 493 | // construct like: 494 | // 495 | // ~~~c 496 | // struct tm_class_t { 497 | // TM_INHERITS(struct tm_super_t); 498 | // ... 499 | // } 500 | // ~~~ 501 | // 502 | // In a compiler that supports anonymous structs, (`-Wno-microsoft-anon-tag`, `-fms-extensions`), 503 | // this will be expanded to just `struct tm_super_t;`, otherwise to `struct tm_super_t super;`. 504 | // 505 | // !!! note 506 | // A struct should never have more than one [[TM_INHERITS()]] and it should always be placed 507 | // at the top of the struct. 508 | #define TM_INHERITS(TYPE) TYPE 509 | 510 | #else 511 | // tm_docgen ignore 512 | #define TM_INHERITS(TYPE) TYPE super 513 | #endif 514 | 515 | #if defined(TM_OS_MACOSX) && defined(TM_CPU_ARM) 516 | // tm_docgen ignore 517 | #define TM_PAGE_SIZE 16384 518 | #else 519 | #define TM_PAGE_SIZE 4096 520 | #endif -------------------------------------------------------------------------------- /tests/7.api_types.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module tests 3 | 4 | // Standard types and macros that are always available. 5 | // Types 6 | // Represents a 2D vector. 7 | struct Tm_vec2_t { 8 | x f32 9 | y f32 10 | } 11 | 12 | // Represents a 3D vector. 13 | struct Tm_vec3_t { 14 | x f32 15 | y f32 16 | z f32 17 | } 18 | 19 | // Represents a 3D vector in double precision. 20 | struct Tm_vec3d_t { 21 | x f64 22 | y f64 23 | z f64 24 | } 25 | 26 | // Represents a 4D vector. 27 | struct Tm_vec4_t { 28 | x f32 29 | y f32 30 | z f32 31 | w f32 32 | } 33 | 34 | // Represents a 4x4 matrix. 35 | struct Tm_mat44_t { 36 | xx f32 37 | xy f32 38 | xz f32 39 | xw f32 40 | yx f32 41 | yy f32 42 | yz f32 43 | yw f32 44 | zx f32 45 | zy f32 46 | zz f32 47 | zw f32 48 | wx f32 49 | wy f32 50 | wz f32 51 | ww f32 52 | } 53 | 54 | // Represents a transform in TRS form. 55 | struct Tm_transform_t { 56 | pos Tm_vec3_t 57 | rot Tm_vec4_t 58 | scl Tm_vec3_t 59 | } 60 | 61 | // Represents a rectangle. 62 | struct Tm_rect_t { 63 | x f32 64 | y f32 65 | w f32 66 | h f32 67 | } 68 | 69 | // Used to represent a string slice with pointer and length. 70 | // 71 | // This lets you reason about parts of a string, which you are not able to do with standard 72 | // NULL-terminated strings. 73 | struct Tm_str_t { 74 | // Pointer to string bytes. 75 | data &i8 76 | // Length of the string. 77 | size u32 78 | // If set to *true*, indicates that there is an allocated NULL-byte after the string data. I.e. 79 | // `data[size] == 0`. This means that `data` can be used immediately as a C string without 80 | // needing to copy it to a separate memory area. 81 | // 82 | // If *false*, there may or may not be a NULL-byte at the end of the string and accessing 83 | // `data[size]` may cause an access violation, so if you want to use it as a C-string you have 84 | // to copy it to a new memory area and append a NULL byte. 85 | // 86 | // Note that the NULL-byte is never included in the `size`. 87 | null_terminated u32 88 | } 89 | 90 | // Creates a [[tm_str_t]] from a `char *` `s`. 91 | // Creates a [[tm_str_t]] from a static string `s`. As [[tm_str()]], but uses `sizeof()` instead of 92 | // `strlen()` to determine the length of the string. This means it avoids the `strlen()` overhead 93 | // and can be used to initialize static data, but it can only be used with static strings. 94 | // Creates a [[tm_str_t]] from a start pointer `s` and end pointer `e`. 95 | // Represents a time from the system clock. 96 | // 97 | // You can assume the clock to be monotonically increasing, i.e. a larger `opaque` value represents 98 | // a later time, but you shouldn't assume anything else about what the `opaque` value represents or 99 | // the resolution of the timer. Instead, use [[tm_os_time_api->delta()]] to convert elapsed time to 100 | // seconds. 101 | struct Tm_clock_o { 102 | opaque u64 103 | } 104 | 105 | // Represents a unique 128-bit identifier. 106 | struct Tm_uuid_t { 107 | a u64 108 | b u64 109 | } 110 | 111 | // Represents an 8-bit per channel RGBA color in sRGB color space (Note: alpha is always linear.) 112 | struct Tm_color_srgb_t { 113 | r u8 114 | g u8 115 | b u8 116 | a u8 117 | } 118 | 119 | // Converts an `uint32_t` to an [[tm_color_srgb_t]] color. 120 | // 121 | // The nibbles in the `uint32_t` hex representation specify TRGB, where T is transparancy (0x00 122 | // means fully opaque and 0xff fully transparent, i.e. it is the invert of alpha). This lets you 123 | // leave the highest nibble out for an opaque color (the most common case), but specify it if 124 | // you want transparency. 125 | // 126 | // Hex | Color 127 | // ---------- | ------------------- 128 | // 0x00 | Black 129 | // 0xff0000 | Red 130 | // 0xff000000 | Transparent black 131 | // 0x80ffff00 | 50 % transparent yellow 132 | // Type representing a type in The Truth. 133 | struct Tm_tt_type_t { 134 | u64 u64 135 | } 136 | 137 | // ID representing an object in The Truth. 138 | struct Tm_tt_id_t { 139 | } 140 | 141 | // Returns the type of `id`. 142 | // Type representing an undo scope in The Truth. 143 | struct Tm_tt_undo_scope_t { 144 | u64 u64 145 | } 146 | 147 | // Used to represent API versions. 148 | // 149 | // Version numbers follow the SemVer 2.0.0 specification: 150 | // 151 | // * The major version is bumped for breaking API changes. 152 | // * The minor version is bumped when new functionality is added in a backwards-compatible manner. 153 | // * The patch version is bumped for backwards-compatible bug fixes. 154 | // * If the major version is 0, the API is considered unstable and under development. In this case, 155 | // nothing should be assumed about backwards compatibility. 156 | // 157 | // See: https://semver.org/spec/v2.0.0.html 158 | // 159 | // !!! WARNING: Be careful about backwards compatibility 160 | // The default action should be to bump the major version whenever you change something in the 161 | // API. If you are considering just bumping the minor or patch version, you must make 100 % 162 | // sure that your changes are backwards compatible, since otherwise you will break existing 163 | // plugins without any warning. 164 | struct Tm_version_t { 165 | // Bumped when breaking changes are made to the API. For example: 166 | // 167 | // * Adding functions in the middle of the API. 168 | // * Changing the number of parameters to a function or their types. 169 | // * Changing the return type of a function. 170 | // * Changing the fields of a struct. 171 | major u32 172 | // Bumped when new functionality is added to the API in a backwards-compatible manner. 173 | // Changes are backwards compatible if a caller using an old version of the header file can 174 | // still call into the new version of the ABI without errors. Examples of backwards-compatible 175 | // changes are: 176 | // 177 | // * Adding new functions to the end of the API. 178 | // * Repurposing unused bits in structs. 179 | // 180 | // If you want to change an API and only bump the minor version you should make sure to take 181 | // special care that your changes are really backwards compatible. 182 | minor u32 183 | // Bumped for backwards-compatible bug fixes. 184 | patch u32 185 | } 186 | 187 | // Creates a [[tm_version_t]] literal. 188 | // The [[TM_VERSION()]] macro cannot be used to initialize constant objects in Visual Studio. 189 | // (It will give the error "initializer not constant".) This macro can be used as an alternative 190 | // for constant initializations. 191 | // 192 | // !!! TODO: TODO 193 | // Having two separate macros for this is not very elegant. See if we can find a better 194 | // solution. 195 | // Build configuration 196 | // 197 | // These macros are defined in the build file `premake5.lua`, but listed here for documentation 198 | // purposes. 199 | // Defined for Windows builds. 200 | // Defined for OS X builds. 201 | // Defined for Linux builds. 202 | // Defined for POSIX builds (OS X or Linux). 203 | // If defined, the main job runs on a thread, not a fiber. 204 | // Defined for debug builds. 205 | // Defined for release builds. 206 | // String hashes 207 | // `#define TM_USE_STRHASH_TYPE` controls whether we should use a custom type [[tm_strhash_t]] for 208 | // string hashes, or if they should just be `uint64_t`. Currently, it is set to `0` when compiling 209 | // using MSVC and `1` otherwise. 210 | // 211 | // We cannot use the [[tm_strhash_t]] type with the Visual Studio compiler, because it doesn't see 212 | // our [[TM_STATIC_HASH()]] macro as a constant, and thus will generate 213 | // [C2099](https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/compiler-error-c2099?view=msvc-160) 214 | // compiler error. errors whenever it is used to initialize a global variable. This is unfortunate, 215 | // because it means we can't get type safe string hashes in Visual Studio. 216 | // 217 | // Hopefully, this will be fixed in a future Visual Studio release and we can transition fully to 218 | // the [[tm_strhash_t]] type. 219 | // tm_docgen ignore 220 | // Type-safe representation of a hashed string. 221 | // 222 | // !!! WARNING: WARNING 223 | // In Visual Studio, string hashes won't use this string type, instead 224 | // [[tm_strhash_t]] will be typedefed to `uint64_t`. The reason for this is that the 225 | // [[TM_STATIC_HASH()]] macro is not seen as a constant by the MSVC compiler and thus using it 226 | // to initialize global variables yields the 227 | // [C2099](https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/compiler-error-c2099?view=msvc-160) 228 | // compiler error. 229 | // 230 | // This means that the type safety of string hashes won't be checked when compiling with MSVC. 231 | // Make sure you build your code under clang too, with `tmbuild --clang` to check the type 232 | // safety of string hashes. Also, always use the macros [[TM_STRHASH()]] and 233 | // [[TM_STRHASH_U64()]] to convert between [[tm_strhash_t]] and `uint64_t`. This ensures that 234 | // the conversions work on all platforms. 235 | struct Tm_strhash_t { 236 | u64 u64 237 | } 238 | 239 | // Converts a `uint64_t` to a [[tm_strhash_t]]. 240 | // Extracts the `uint64_t` of a [[tm_strhash_t]] value `x`. 241 | // tm_docgen ignore 242 | // tm_docgen ignore 243 | // tm_docgen ignore 244 | // Returns true if the the two [[tm_strhash_t]] are equal. 245 | // Used for static string hashes. The `hash.exe` utility checks the entire source code and makes 246 | // sure that wherever you use [[TM_STATIC_HASH()]], the numeric value `v` matches the actual hash of the 247 | // string `s` (if not, the code is updated). 248 | // 249 | // When you create a new static hash, don't enter the numeric value, just the string: 250 | // `TM_STATIC_HASH("bla")`. 251 | // 252 | // This ensures that the macro fails to compile until you run `hash.exe` to generate a numeric 253 | // value. 254 | // 255 | // [[TM_STATIC_HASH()]] returns a constant value of type [[tm_strhash_t]]. 256 | // 257 | // 261 | // Macros 262 | // tm_docgen ignore 263 | // Macro for creating a struct literal of type `T` that works both in C and C++. Use as: 264 | // 265 | // ~~~c 266 | // x = TM_LITERAL(tm_vec2_t) {x, y} 267 | // ~~~ 268 | // 269 | // In C, this turns into `(tm_vec2_t){0, 0}` and in C++ to `tm_vec2_t{0, 0}`. 270 | // 271 | // Note that use of [[TM_LITERAL()]] is only needed in .h and .inl files that might be included from 272 | // both C and C++. In .c and .cpp file you should just use the native literal format instead of 273 | // relying on [[TM_LITERAL()]]. 274 | // Marks a function to be exported to DLLs. 275 | // tm_docgen ignore 276 | // tm_docgen ignore 277 | // 278 | // This is not ideal -- preferably we would want to use `restrict` rather than `__restrict` as our 279 | // `restrict` keyword, since that is what the C standard specifies. However, VS does not support 280 | // this, and if we try `#define restrict __restrict` we run into trouble, because some of the 281 | // windows headers actually use `restrict` already. 282 | // Mark struct fields in header files as atomic. 283 | // tm_docgen ignore 284 | // tm_docgen off 285 | // Generate an error if this file was included in a C++ file, without wrapping the include in extern 286 | // "C". If you forget extern "C", the first declaration will get C++ linkage and you will then get a 287 | // conflict on the second declaration. 288 | // tm_docgen on 289 | // Returns the `name` as a string. 290 | // tm_docgen ignore 291 | // Concatenates `a` and `b` , allowing you to expand macros before doing the concatenation. This is 292 | // useful when used with builtin macros like `__LINE__` or `__COUNTER__`. `x##__COUNTER__` doesn't 293 | // expand to `x1` since a macro is not expanded if preceded by `#` or `##`, but `TM_CONCAT(x, 294 | // __COUNTER__)` works. 295 | // Generates a unique name for a macro variable, based on `name`. 296 | // Declares a field that pads a struct with the specified number of bytes. To ensure that structs 297 | // are completely zero-initialized by designated initializers, we require all struct padding to be 298 | // explicitly declared using this macro. (We enable warnings that trigger if there is undeclared 299 | // padding in a struct.) 300 | // 301 | // Example: 302 | // 303 | // ~~~c 304 | // struct x { 305 | // uint32_t a; 306 | // // This padding is needed since `b` needs to be aligned to a 64-bit boundary. 307 | // TM_PAD(4); 308 | // uint64_t b; 309 | // }; 310 | // ~~~ 311 | // 312 | // Note that in situations where types have different sizes on different platforms you may need to 313 | // pad with different amounts: 314 | // 315 | // ~~~c 316 | // TM_PAD(8 - sizeof(x)); 317 | // ~~~ 318 | // Disable warnings about padding inserted into structs. Use this before including external headers 319 | // that do not explicitly declare padding. Restore the padding warning afterwards with 320 | // [[TM_RESTORE_PADDING_WARNINGS]]. 321 | // Restore padding warnings disabled by [[TM_DISABLE_PADDING_WARNINGS]]. 322 | // tm_docgen ignore 323 | // tm_docgen ignore 324 | // tm_docgen ignore 325 | // tm_docgen ignore 326 | // Used to implement "inheritance" -- inserting the members of one struct into another, with a 327 | // construct like: 328 | // 329 | // ~~~c 330 | // struct tm_class_t { 331 | // TM_INHERITS(struct tm_super_t); 332 | // ... 333 | // } 334 | // ~~~ 335 | // 336 | // In a compiler that supports anonymous structs, (`-Wno-microsoft-anon-tag`, `-fms-extensions`), 337 | // this will be expanded to just `struct tm_super_t;`, otherwise to `struct tm_super_t super;`. 338 | // 339 | // !!! note 340 | // A struct should never have more than one [[TM_INHERITS()]] and it should always be placed 341 | // at the top of the struct. 342 | // tm_docgen ignore 343 | // tm_docgen ignore -------------------------------------------------------------------------------- /tests/8.simple_func_header.h: -------------------------------------------------------------------------------- 1 | void testFunc() { 2 | 3 | } 4 | 5 | void testFunc2(int remove) { 6 | 7 | } 8 | 9 | void testFunc3(int shared) { 10 | 11 | } 12 | 13 | void testFunc4(int select) { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /tests/8.simple_func_header.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module tests 3 | 4 | fn C.testFunc() 5 | 6 | pub fn test_func() { 7 | C.testFunc() 8 | } 9 | 10 | fn C.testFunc2(remove int) 11 | 12 | pub fn test_func2(remove int) { 13 | C.testFunc2(remove) 14 | } 15 | 16 | fn C.testFunc3(shared_ int) 17 | 18 | pub fn test_func3(shared_ int) { 19 | C.testFunc3(shared_) 20 | } 21 | 22 | fn C.testFunc4(select_ int) 23 | 24 | pub fn test_func4(select_ int) { 25 | C.testFunc4(select_) 26 | } 27 | -------------------------------------------------------------------------------- /tests/9.func_declaration.h: -------------------------------------------------------------------------------- 1 | void testFunc(); 2 | -------------------------------------------------------------------------------- /tests/9.func_declaration.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module tests 3 | 4 | fn C.testFunc() 5 | 6 | pub fn test_func() { 7 | C.testFunc() 8 | } 9 | -------------------------------------------------------------------------------- /tests/IGNORE_header_duplicate_type_declaration_2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef int dup_typ; 4 | -------------------------------------------------------------------------------- /tests/run_doom_tests.vsh: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Alexander Medvednikov. All rights reserved. 2 | // Use of this source code is governed by a GPL license that can 3 | // be found in the LICENSE file. 4 | import term 5 | import os 6 | import runtime 7 | 8 | struct App { 9 | mut: 10 | idx atomic int 11 | } 12 | 13 | const files = [ 14 | 'g_game', 15 | 'd_main', 16 | 'm_menu', 17 | 'p_enemy' 18 | //'wi_stuff' 19 | 'p_saveg' 20 | //'st_stuff', 21 | 'p_spec', 22 | 'p_map', 23 | 'am_map', 24 | 'r_things', 25 | 'r_draw', 26 | 'p_mobj', 27 | 'r_segs', 28 | 'r_data', 29 | 'p_setup', 30 | 'p_pspr', 31 | 'p_maputl', 32 | 'p_inter', 33 | 's_sound', 34 | 'r_main', 35 | 'p_switch', 36 | 'hu_stuff', 37 | 'statdump', 38 | 'r_plane', 39 | 'r_bsp', 40 | 'p_sight', 41 | 'p_floor', 42 | 'deh_bexstr', 43 | 'st_lib' 44 | //'sounds', 45 | 'p_user', 46 | 'p_plats', 47 | 'p_lights', 48 | 'hu_lib', 49 | 'f_wipe', 50 | 'r_sky', 51 | 'p_tick', 52 | 'p_telept', 53 | 'm_random', 54 | 'dstrings', 55 | 'doomdef' 56 | //'deh_weapon., 57 | //'deh_thing.c, 58 | //'deh_sound.c, 59 | //'deh_ptr.c / deh_frame.c, 60 | //'deh_doom.c, 61 | //'deh_cheat.c, 62 | //'deh_ammo.c, 63 | 'd_items', 64 | ] 65 | 66 | const exe = executable() 67 | const tests_dir = dir(exe) 68 | const c2v_dir = dir(tests_dir) 69 | const doom_dir = join_path(dir(c2v_dir), 'doom') 70 | 71 | const src_dir = join_path(doom_dir, 'src/doom') 72 | 73 | fn main() { 74 | println(src_dir) 75 | 76 | mut app := &App{ 77 | idx: 0 78 | } 79 | 80 | for file in files { 81 | app.run(0) 82 | } 83 | /* 84 | nr_cpus := runtime.nr_cpus() 85 | mut threads := []thread{} 86 | for x in 0 .. nr_cpus { 87 | threads << go app.run(x) 88 | } 89 | threads.wait() 90 | */ 91 | println(term.green('ALL GOOD')) 92 | } 93 | 94 | fn (mut app App) run(x int) { 95 | if app.idx >= files.len { 96 | return 97 | } 98 | file := files[app.idx] 99 | app.idx++ 100 | // for file in files { 101 | println('\nTranslating ${file}... (thread ${x})') 102 | cmd := 'v run ${c2v_dir}/tools/build_doom_file.vsh doom/${file}' 103 | ret := os.system('${cmd} > /dev/null') 104 | if ret != 0 { 105 | println(term.red('FAILED')) 106 | os.system(cmd) // re-run it to print the error 107 | exit(1) 108 | } 109 | println(term.green('OK')) 110 | //} 111 | } 112 | -------------------------------------------------------------------------------- /tests/run_tests.vsh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S v 2 | 3 | // Copyright (c) 2022 Alexander Medvednikov. All rights reserved. 4 | // Use of this source code is governed by a GPL license that can 5 | // be found in the LICENSE file. 6 | import term 7 | import os 8 | 9 | const c2v_dir = @VMODROOT 10 | const tests_dir = join_path(c2v_dir, 'tests') 11 | const exe_path = join_path(c2v_dir, $if windows { 12 | 'c2v.exe' 13 | } $else { 14 | 'c2v' 15 | }) 16 | 17 | fn replace_file_extension(file_path string, old_extension string, new_extension string) string { 18 | // NOTE: It can't be just `file_path.replace(old_extenstion, new_extension)`, because it will replace all occurencies of old_extenstion string. 19 | // Path '/dir/dir/dir.c.c.c.c.c.c/kalle.c' will become '/dir/dir/dir.json.json.json.json.json.json/kalle.json'. 20 | return file_path.trim_string_right(old_extension) + new_extension 21 | } 22 | 23 | fn try_process_filter_argument() string { 24 | second_argument := os.args[1] 25 | 26 | if second_argument == '-h' { 27 | println('Usage: v run tests/run_tests.vsh ([testname])') 28 | exit(0) 29 | } else { 30 | return second_argument 31 | } 32 | 33 | return '' 34 | } 35 | 36 | fn build_c2v() { 37 | chdir(c2v_dir) or { 38 | eprintln('Cannot change directory to ' + c2v_dir) 39 | exit(1) 40 | } 41 | 42 | println('building c2v...') 43 | c2v_build_command_result := execute('v -o c2v -experimental -w .') 44 | 45 | if !exists(exe_path) || c2v_build_command_result.exit_code != 0 { 46 | eprintln('c2v compilation failed:') 47 | eprintln(c2v_build_command_result.output) 48 | eprintln('c2vdir="${c2v_dir}"') 49 | 50 | eprintln(ls(c2v_dir) or { 51 | eprintln('Cannot list c2v directory') 52 | exit(1) 53 | }) 54 | 55 | exit(1) 56 | } 57 | 58 | println('done') 59 | } 60 | 61 | fn start_testing_process(filter string) { 62 | if run_tests('.c', '', filter) == false || run_tests('.h', 'wrapper', filter) == false { 63 | exit(1) 64 | } 65 | 66 | os.chdir(tests_dir) or { 67 | panic('Failed to switch folder to tests folder for testing translation for relative paths - ${err}') 68 | } 69 | 70 | if run_tests('.c', '', filter) == false || run_tests('.h', 'wrapper', filter) == false { 71 | exit(1) 72 | } 73 | } 74 | 75 | fn run_tests(test_file_extension string, c2v_opts string, filter string) bool { 76 | mut files := get_test_files(test_file_extension).filter(it.all_after_last('/').starts_with('IGNORE_') == false) 77 | 78 | files.sort() 79 | 80 | current_platform := os.user_os() 81 | next_file: for file in files { 82 | // skip all platform dependent .c/.out pairs, on non matching platforms: 83 | for platform in ['linux', 'macos', 'windows'] { 84 | if file.ends_with('_${platform}.c') && current_platform != platform { 85 | println(' >>>>> skipping `${file}` on ${current_platform} .') 86 | continue next_file 87 | } 88 | } 89 | 90 | print(file + '... ') 91 | 92 | if filter != '' { 93 | file.index(filter) or { continue } 94 | } 95 | 96 | if try_compile_test_file(file) == false { 97 | return false 98 | } 99 | 100 | c2v_cmd := '${exe_path} ${c2v_opts} ${file}' 101 | c2v_res := execute(c2v_cmd) 102 | if c2v_res.exit_code != 0 { 103 | eprintln(c2v_res.output) 104 | eprintln('command: ${c2v_cmd}') 105 | return false 106 | } 107 | 108 | generated_file := try_get_generated_file(file, test_file_extension) or { 109 | eprintln(term.red('FAIL')) 110 | return false 111 | } 112 | 113 | format_generated_file(generated_file) 114 | 115 | expected := get_expected_file_content(file, test_file_extension) 116 | result := get_result_file_content(generated_file, test_file_extension) 117 | 118 | if expected != result { 119 | print_test_fail_details(expected, result, c2v_cmd) 120 | return false 121 | } else { 122 | do_post_test_cleanup(generated_file) 123 | println(term.green('OK')) 124 | } 125 | } 126 | 127 | return true 128 | } 129 | 130 | fn get_test_files(extension string) []string { 131 | return walk_ext(tests_dir, extension) 132 | } 133 | 134 | fn try_compile_test_file(file string) bool { 135 | // Make sure the C test is a correct C program first 136 | o_path := join_path(temp_dir(), file_name(file)) + '.o' 137 | cmd := 'cc -c -w ${file} -o ${o_path}' 138 | res := execute(cmd) 139 | 140 | if res.exit_code != 0 { 141 | eprintln('failed to compile C test `${file}`') 142 | eprintln('command: ${cmd}') 143 | return false 144 | } 145 | 146 | return true 147 | } 148 | 149 | fn try_get_generated_file(file string, test_file_extension string) !string { 150 | generated_file := replace_file_extension(file, test_file_extension, '.v') 151 | println(generated_file) 152 | 153 | if !exists(generated_file) { 154 | return error('Expected generated file `${generated_file}` does not exist') 155 | } 156 | 157 | return generated_file 158 | } 159 | 160 | fn format_generated_file(file string) { 161 | system('v fmt -w ${file}') 162 | } 163 | 164 | fn get_expected_file_content(file string, test_file_extension string) string { 165 | file_content := read_file(replace_file_extension(file, test_file_extension, '.out')) or { '' } 166 | return file_content.trim_space() 167 | } 168 | 169 | fn get_result_file_content(file string, test_file_extension string) string { 170 | file_content := read_file(file) or { '' } 171 | return file_content.after('// vstart').trim_space() 172 | } 173 | 174 | fn print_test_fail_details(expected string, got string, cmd string) { 175 | eprintln(term.red('\nFAIL')) 176 | eprintln('expected:') 177 | eprintln(expected) 178 | eprintln('\n===got:') 179 | eprintln(got) 180 | 181 | eprintln('\n====diff=====') 182 | expected_file_form := join_path(temp_dir(), 'expected.txt') 183 | got_file_form := join_path(temp_dir(), 'got.txt') 184 | 185 | write_file(expected_file_form, expected) or { eprintln('Cannot write expected file') } 186 | write_file(got_file_form, got) or { eprintln('Cannot write got file') } 187 | 188 | diff := execute('diff -u ${expected_file_form} ${got_file_form}') 189 | eprintln(diff.output) 190 | eprintln('>>>>>>>>>>>>>>>>>> Failed cmd: ${cmd}') 191 | } 192 | 193 | fn do_post_test_cleanup(generated_file string) { 194 | os.rm(generated_file) or {} 195 | } 196 | 197 | mut filter := '' 198 | 199 | if os.args.len > 1 { 200 | filter = try_process_filter_argument() 201 | } 202 | 203 | build_c2v() 204 | start_testing_process(filter) 205 | -------------------------------------------------------------------------------- /tests/test.c/1.hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | printf("hello world!"); 5 | return 0; 6 | } 7 | 8 | typedef struct Foo { 9 | int bar; 10 | } Foo; 11 | 12 | void implicit_inits() { 13 | int num; 14 | Foo foo; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /tests/test.c/1.hello.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | fn main() { 5 | C.printf(c'hello world!') 6 | return 7 | } 8 | 9 | struct Foo { 10 | bar int 11 | } 12 | 13 | fn implicit_inits() { 14 | num := 0 15 | foo := Foo{} 16 | } 17 | -------------------------------------------------------------------------------- /tests_todo/5.if_paren_call.c: -------------------------------------------------------------------------------- 1 | main() { 2 | int a; 3 | if ((a = puts ("Hello World"))) { 4 | puts ("noes"); 5 | } 6 | if ((a = puts ("Hello World")) != 0) { 7 | puts ("noes"); 8 | } 9 | int cacatua; 10 | if ((cacatua = puts ("Hello World"))) { 11 | puts ("noes"); 12 | } 13 | /* 14 | if ((1 > 0 && (3 < 20) && 1 < 10)) { 15 | puts ("noes"); 16 | } 17 | */ 18 | } 19 | -------------------------------------------------------------------------------- /tests_todo/5.if_paren_call.out: -------------------------------------------------------------------------------- 1 | @[translated] 2 | module main 3 | 4 | fn main() { 5 | a := 0 6 | a = C.puts(c'Hello World') 7 | if a { 8 | C.puts(c'noes') 9 | } 10 | a = C.puts(c'Hello World') 11 | if a != 0 { 12 | C.puts(c'noes') 13 | } 14 | cacatua := 0 15 | cacatua = C.puts(c'Hello World') 16 | if cacatua { 17 | C.puts(c'noes') 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tools/build_doom_file.vsh: -------------------------------------------------------------------------------- 1 | import os 2 | import term 3 | 4 | const doom_src = home_dir() + '/code/doom/chocolate-doom/src/' 5 | 6 | const c2v_src = os.dir(os.dir(@FILE)) 7 | 8 | const verbose = os.getenv('VVERBOSE') != '' 9 | 10 | const sdl_cflags = os.execute('sdl2-config --cflags').output.trim_space() 11 | 12 | fn cprintln(s string) { 13 | println(term.colorize(term.bold, term.colorize(term.green, s))) 14 | } 15 | 16 | fn run(s string) { 17 | println(' execute: ${term.colorize(term.green, s)}') 18 | ret := os.execute(s) 19 | if ret.exit_code != 0 { 20 | eprintln('Failed command: ${s}') 21 | eprintln(ret.output) 22 | eprintln('Exiting.') 23 | exit(1) 24 | } 25 | if verbose { 26 | println(ret.output) 27 | } 28 | } 29 | 30 | file := os.args[1] 31 | 32 | os.mkdir('/tmp/doom') or {} 33 | 34 | if !exists(join_path(doom_src, '${file}.c')) { 35 | eprintln(join_path(doom_src, '${file}.c') + ' does not exist') 36 | exit(1) 37 | } 38 | 39 | cur_dir := os.getwd() 40 | cprintln('Current folder: ${cur_dir} ; change to folder: ${doom_src}') 41 | chdir(doom_src)! 42 | 43 | if os.args.len < 2 { 44 | println('usage: v run build_doom_file.vsh doom/p_enemy') 45 | exit(1) 46 | } 47 | 48 | cprintln('Cleanup previous build artefacts') 49 | run('make clean') 50 | 51 | if os.args.contains('-g') { 52 | f := file.replace('doom/', 'doom.dir/') 53 | run('cc -g -I. -I.. -I../.. ${sdl_cflags} -w -ferror-limit=100 -c -I ${doom_src} -o ' + 54 | '${doom_src}/doom/CMakeFiles/${f}.c.o ${file}.c') 55 | run('make -j 6 chocolate-doom') 56 | println('-g done') 57 | exit(0) 58 | } else if os.args.contains('-prod') { 59 | f := file.replace('doom/', 'doom.dir/') 60 | run('cc -O2 -I. -I.. -I../.. ${sdl_cflags} -w -ferror-limit=100 -c -I ${doom_src} -o ' + 61 | '/var/tmp/${f}.c.o2.o ${file}.c') 62 | println('-o2 done') 63 | exit(0) 64 | } 65 | 66 | // ast_file := join_path(doom_src, '${file}.json') 67 | v_file := join_path(doom_src, '${file}.v') 68 | 69 | /* 70 | if !exists(ast_file) { 71 | println('${file}.json is missing, generating it...') 72 | // run('clang -v ${file}.c') 73 | run('clang -fparse-all-comments -I. -I.. -I../.. $sdl_cflags -w ' + 74 | '-Xclang -ast-dump=json -fno-diagnostics-color ' + '-c ${file}.c > ${file}.json') 75 | } 76 | 77 | if !exists(ast_file) { 78 | eprintln('failed to generate $ast_file') 79 | exit(1) 80 | } 81 | */ 82 | 83 | println('> change folder to: ${c2v_src}') 84 | chdir(c2v_src)! 85 | 86 | cprintln('Converting C to V...') 87 | c_file := join_path(doom_src, '${file}.c') 88 | run('./c2v -keep_ast ${c_file}') 89 | 90 | if !exists(v_file) { 91 | eprintln('failed to generate v file ${v_file}') 92 | exit(1) 93 | } 94 | 95 | // cprintln('Formatting translated v file...') 96 | // run('v -w fmt -translated -w $v_file') 97 | 98 | cprintln('Building translated v file...') 99 | run('v -cc clang -d 4bytebool -showcc -w -cg -keepc -gc none -translated ' + 100 | '-cflags "-fPIE -w -ferror-limit=100 -I ${doom_src} ${sdl_cflags} -c" -o /tmp/${file}.o ${v_file}') 101 | 102 | chdir(os.dir(doom_src))! 103 | if file.starts_with('doom/') { 104 | f := file.replace('doom/', 'doom.dir/') 105 | source_file := '/tmp/${file}.o' 106 | target_file := '${doom_src}/doom/CMakeFiles/${f}.c.o' 107 | cprintln('Move by copying: ${source_file} => ${target_file}') 108 | os.mv_by_cp('/tmp/${file}.o', target_file)! 109 | 110 | cprintln('Remake chocolate-doom') 111 | run('make -j 6 chocolate-doom') 112 | } 113 | 114 | println('Done. You can run doom with: `src/chocolate-doom -width 640`') 115 | -------------------------------------------------------------------------------- /tools/node_kind_gen/gen_node_kind_code.v: -------------------------------------------------------------------------------- 1 | // This code implements a small tool that can be used to generate a NodeKind and str_to_node_kind_map constructions, 2 | // used in the node_kind.v. Since there can be pretty big list of AST node types, making this by hand is not the most 3 | // optimal way to do it. 4 | // 5 | // To use this tool, simply put a list of node type names into the 'types' file, and place in next to this file. 6 | // Content in this file should look like this: 7 | // AccessSpecDecl 8 | // AcquireCapabilityAttr 9 | // AddrLabelExpr 10 | import os 11 | import artemkakun.textproc.src.case 12 | 13 | // Generates node kind related code, based on the 'types' file. 14 | // 15 | // Example: 16 | // Content of 'types' file: 17 | // AccessSpecDecl 18 | // AcquireCapabilityAttr 19 | // AddrLabelExpr 20 | // 21 | // Generated code: 22 | // enum NodeKind { 23 | // acces_spec_decl, 24 | // acquire_capability_attr, 25 | // addr_label_expr, 26 | // } 27 | // 28 | // const str_to_node_kind_map = { 29 | // 'AccessSpecDecl': .acces_spec_decl, 30 | // 'AcquireCapabilityAttr': .acquire_capability_attr, 31 | // 'AddrLabelExpr': .addr_label_expr, 32 | // } 33 | fn main() { 34 | types_file := 'types' 35 | 36 | lines := os.read_lines(types_file) or { 37 | println('{types_file} file not found') 38 | return 39 | } 40 | 41 | println('enum NodeKind {') 42 | println('bad') 43 | 44 | for line in lines { 45 | node_kind_name := line.trim_space() 46 | println(case.string_to_snake_case(node_kind_name)) 47 | } 48 | 49 | println('}') 50 | 51 | print('\n') 52 | 53 | println('const str_to_node_kind_map = {') 54 | print_map_pair('BAD', 'NodeKind.bad') 55 | 56 | for line in lines { 57 | node_kind_name := line.trim_space() 58 | print_map_pair(node_kind_name, '.${case.string_to_snake_case(node_kind_name)}') 59 | } 60 | 61 | println('}') 62 | } 63 | 64 | fn print_map_pair(key string, value string) { 65 | println('\'${key}\': ${value}') 66 | } 67 | -------------------------------------------------------------------------------- /tools/node_kind_gen/types: -------------------------------------------------------------------------------- 1 | AccessSpecDecl 2 | AcquireCapabilityAttr 3 | AddrLabelExpr 4 | AlignedAttr 5 | AllocSizeAttr 6 | AlwaysInlineAttr 7 | AnalyzerNoReturnAttr 8 | ArrayFiller 9 | ArraySubscriptExpr 10 | AsmLabelAttr 11 | AssertExclusiveLockAttr 12 | AtomicExpr 13 | AvailabilityAttr 14 | BinaryOperator 15 | BlockCommandComment 16 | BlockExpr 17 | BreakStmt 18 | BuiltinTemplateDecl 19 | BuiltinType 20 | CallExpr 21 | CapabilityAttr 22 | CaseStmt 23 | CharacterLiteral 24 | ClassDecl 25 | ClassTemplate 26 | ClassTemplateDecl 27 | ClassTemplatePartialSpecialization 28 | ClassTemplatePartialSpecializationDecl 29 | ClassTemplateSpecialization 30 | ClassTemplateSpecializationDecl 31 | ColdAttr 32 | CompoundAssignOperator 33 | CompoundLiteralExpr 34 | CompoundStmt 35 | ConditionalOperator 36 | ConstantArrayType 37 | ConstantExpr 38 | ConstAttr 39 | ContinueStmt 40 | CStyleCastExpr 41 | CXCursorKind 42 | CXX 43 | CXXAccessSpecifier 44 | CXXBindTemporaryExpr 45 | CXXBoolLiteralExpr 46 | CXXCatchStmt 47 | CXXConstCastExpr 48 | CXXConstructExpr 49 | CXXConstructor 50 | CXXConstructorDecl 51 | CXXConversion 52 | CXXConversionDecl 53 | CXXCtorInitializer 54 | CXXDefaultArgExpr 55 | CXXDefaultInitExpr 56 | CXXDeleteExpr 57 | CXXDependentScopeMemberExpr 58 | CXXDestructor 59 | CXXDestructorDecl 60 | CXXDynamicCastExpr 61 | CXXForRangeStmt 62 | CXXFunctionalCastExpr 63 | CXXMemberCallExpr 64 | CXXMethod 65 | CXXMethodDecl 66 | CXXNewExpr 67 | CXXNoexceptExpr 68 | CXXNullPtrLiteralExpr 69 | CXXOperatorCallExpr 70 | CXXPseudoDestructorExpr 71 | CXXRecord 72 | CXXRecordDecl 73 | CXXReinterpretCastExpr 74 | CXXScalarValueInitExpr 75 | CXXStaticCastExpr 76 | CXXTemporaryObjectExpr 77 | CXXThisExpr 78 | CXXThrowExpr 79 | CXXTryStmt 80 | CXXTypeidExpr 81 | CXXUnresolvedConstructExpr 82 | DecayedType 83 | DeclRefExpr 84 | DeclStmt 85 | DecltypeType 86 | DefaultStmt 87 | DependentNameType 88 | DependentScopeDeclRefExpr 89 | DependentTemplateSpecializationType 90 | DeprecatedAttr 91 | DiagnoseIfAttr 92 | DisableTailCallsAttr 93 | DoStmt 94 | ElaboratedType 95 | EnableIfAttr 96 | Enum 97 | EnumConstantDecl 98 | EnumDecl 99 | EnumType 100 | ExprWithCleanups 101 | Field 102 | FieldDecl 103 | FixedPointLiteral 104 | FloatingLiteral 105 | FormatArgAttr 106 | FormatAttr 107 | ForStmt 108 | FriendDecl 109 | FullComment 110 | Function 111 | FunctionDecl 112 | FunctionNoProtoType 113 | FunctionProtoType 114 | FunctionTemplate 115 | FunctionTemplateDecl 116 | GCCAsmStmt 117 | GenericSelectionExpr 118 | GNUNullExpr 119 | GotoStmt 120 | GuardedByAttr 121 | HTMLEndTagComment 122 | HTMLStartTagComment 123 | IfStmt 124 | ImaginaryLiteral 125 | ImplicitCastExpr 126 | ImplicitValueInitExpr 127 | IncompleteArrayType 128 | IndirectFieldDecl 129 | IndirectGotoStmt 130 | InitListExpr 131 | InjectedClassNameType 132 | InlineCommandComment 133 | IntegerLiteral 134 | InvalidCode 135 | InvalidFile 136 | LabelRef 137 | LabelStmt 138 | LambdaExpr 139 | LinkageSpec 140 | LinkageSpecDecl 141 | LValueReferenceType 142 | MaterializeTemporaryExpr 143 | MaxFieldAlignmentAttr 144 | MemberExpr 145 | MemberPointerType 146 | MemberRef 147 | MemberRefExpr 148 | ModuleImport 149 | MSAsmStmt 150 | Namespace 151 | NamespaceAlias 152 | NamespaceDecl 153 | NamespaceRef 154 | NoDeclFound 155 | NoEscapeAttr 156 | NoInlineAttr 157 | NonTypeTemplateParameter 158 | NonTypeTemplateParmDecl 159 | NoSanitizeAttr 160 | NoThrowAttr 161 | NotImplemented 162 | Null 163 | NullStmt 164 | ObjCAtCatchStmt 165 | ObjCAtFinallyStmt 166 | ObjCAtSynchronizedStmt 167 | ObjCAtThrowStmt 168 | ObjCAtTryStmt 169 | ObjCAutoreleasePoolStmt 170 | ObjCAvailabilityCheckExpr 171 | ObjCBoolLiteralExpr 172 | ObjCBridgedCastExpr 173 | ObjCCategoryDecl 174 | ObjCCategoryImplDecl 175 | ObjCClassMethodDecl 176 | ObjCClassRef 177 | ObjCDynamicDecl 178 | ObjCEncodeExpr 179 | ObjCForCollectionStmt 180 | ObjCImplementationDecl 181 | ObjCInstanceMethodDecl 182 | ObjCInterfaceDecl 183 | ObjCIvarDecl 184 | ObjCMessageExpr 185 | ObjCPropertyDecl 186 | ObjCProtocolDecl 187 | ObjCProtocolExpr 188 | ObjCProtocolRef 189 | ObjCSelectorExpr 190 | ObjCSelfExpr 191 | ObjCStringLiteral 192 | ObjCSuperClassRef 193 | ObjCSynthesizeDecl 194 | OffsetOfExpr 195 | OMPArraySectionExpr 196 | OMPAtomicDirective 197 | OMPBarrierDirective 198 | OMPCancelDirective 199 | OMPCancellationPointDirective 200 | OMPCriticalDirective 201 | OMPDistributeDirective 202 | OMPDistributeParallelForDirective 203 | OMPDistributeParallelForSimdDirective 204 | OMPDistributeSimdDirective 205 | OMPFlushDirective 206 | OMPForDirective 207 | OMPForSimdDirective 208 | OMPMasterDirective 209 | OMPOrderedDirective 210 | OMPParallelDirective 211 | OMPParallelForDirective 212 | OMPParallelForSimdDirective 213 | OMPParallelSectionsDirective 214 | OMPSectionDirective 215 | OMPSectionsDirective 216 | OMPSimdDirective 217 | OMPSingleDirective 218 | OMPTargetDataDirective 219 | OMPTargetDirective 220 | OMPTargetEnterDataDirective 221 | OMPTargetExitDataDirective 222 | OMPTargetParallelDirective 223 | OMPTargetParallelForDirective 224 | OMPTargetParallelForSimdDirective 225 | OMPTargetSimdDirective 226 | OMPTargetTeamsDirective 227 | OMPTargetTeamsDistributeDirective 228 | OMPTargetTeamsDistributeParallelForDirective 229 | OMPTargetTeamsDistributeParallelForSimdDirective 230 | OMPTargetTeamsDistributeSimdDirective 231 | OMPTargetUpdateDirective 232 | OMPTaskDirective 233 | OMPTaskgroupDirective 234 | OMPTaskLoopDirective 235 | OMPTaskLoopSimdDirective 236 | OMPTaskwaitDirective 237 | OMPTaskyieldDirective 238 | OMPTeamsDirective 239 | OMPTeamsDistributeDirective 240 | OMPTeamsDistributeParallelForDirective 241 | OMPTeamsDistributeParallelForSimdDirective 242 | OMPTeamsDistributeSimdDirective 243 | OpaqueValueExpr 244 | original 245 | OverloadCandidate 246 | OverloadedDeclRef 247 | OverrideAttr 248 | Overrides 249 | PackedAttr 250 | PackExpansionExpr 251 | PackExpansionType 252 | ParagraphComment 253 | ParenExpr 254 | ParenListExpr 255 | ParenType 256 | ParmDecl 257 | ParmVarDecl 258 | PointerType 259 | PredefinedExpr 260 | private 261 | protected 262 | public 263 | PureAttr 264 | QualType 265 | Record 266 | RecordDecl 267 | RecordType 268 | ReleaseCapabilityAttr 269 | RequiresCapabilityAttr 270 | RestrictAttr 271 | ReturnStmt 272 | ReturnsTwiceAttr 273 | ruct 274 | RValueReferenceType 275 | ScopedLockableAttr 276 | SEHExceptStmt 277 | SEHFinallyStmt 278 | SEHLeaveStmt 279 | SEHTryStmt 280 | SizeOfPackExpr 281 | StaticAssert 282 | StaticAssertDecl 283 | StmtExpr 284 | StringLiteral 285 | StructDecl 286 | SubstNonTypeTemplateParmExpr 287 | SubstTemplateTypeParmType 288 | SwitchStmt 289 | TemplateArgument 290 | TemplateRef 291 | TemplateSpecializationType 292 | TemplateTemplateParameter 293 | TemplateTemplateParmDecl 294 | TemplateTypeParameter 295 | TemplateTypeParm 296 | TemplateTypeParmDecl 297 | TemplateTypeParmType 298 | TextComment 299 | TranslationUnit 300 | TranslationUnitDecl 301 | TypeAliasDecl 302 | TypeAliasTemplateDecl 303 | Typedef 304 | TypedefDecl 305 | TypedefType 306 | TypeRef 307 | TypeVisibilityAttr 308 | UnaryExpr 309 | UnaryExprOrTypeTraitExpr 310 | UnaryOperator 311 | UnaryTransformType 312 | UnexposedAttr 313 | UnexposedDecl 314 | UnexposedExpr 315 | UnexposedStmt 316 | Unhandled 317 | UnionDecl 318 | UnresolvedLookupExpr 319 | UnresolvedMemberExpr 320 | UnusedAttr 321 | UsingDecl 322 | UsingDeclaration 323 | UsingDirective 324 | UsingDirectiveDecl 325 | UsingShadowDecl 326 | VAArgExpr 327 | VarDecl 328 | VariableRef 329 | virtual 330 | VisibilityAttr 331 | WarnUnusedResultAttr 332 | WhileStmt 333 | -------------------------------------------------------------------------------- /v.mod: -------------------------------------------------------------------------------- 1 | Module { 2 | name: 'c2v' 3 | description: 'Tool for translation/wrapper generation from C to V' 4 | version: '0.4.1' 5 | license: 'GPLv3' 6 | dependencies: ['ArtemkaKun.textproc'] 7 | } 8 | --------------------------------------------------------------------------------