Repository: vlang/v Branch: master Commit: cdfc0bba9081 Files: 10542 Total size: 52.7 MB Directory structure: gitextract_hyl3qslc/ ├── .editorconfig ├── .git/ │ ├── HEAD │ ├── config │ ├── description │ ├── hooks/ │ │ ├── applypatch-msg.sample │ │ ├── commit-msg.sample │ │ ├── fsmonitor-watchman.sample │ │ ├── post-update.sample │ │ ├── pre-applypatch.sample │ │ ├── pre-commit.sample │ │ ├── pre-merge-commit.sample │ │ ├── pre-push.sample │ │ ├── pre-rebase.sample │ │ ├── pre-receive.sample │ │ ├── prepare-commit-msg.sample │ │ ├── push-to-checkout.sample │ │ ├── sendemail-validate.sample │ │ └── update.sample │ ├── index │ ├── info/ │ │ └── exclude │ ├── logs/ │ │ ├── HEAD │ │ └── refs/ │ │ ├── heads/ │ │ │ └── master │ │ └── remotes/ │ │ └── origin/ │ │ └── HEAD │ ├── objects/ │ │ └── pack/ │ │ ├── pack-4c5eb4b01e8d20d1b77462674426e18b34b3eb8d.idx │ │ ├── pack-4c5eb4b01e8d20d1b77462674426e18b34b3eb8d.pack │ │ ├── pack-4c5eb4b01e8d20d1b77462674426e18b34b3eb8d.promisor │ │ ├── pack-4c5eb4b01e8d20d1b77462674426e18b34b3eb8d.rev │ │ ├── pack-a119d32135c98d4d3e4374ad1ecd525e9b537c4c.idx │ │ ├── pack-a119d32135c98d4d3e4374ad1ecd525e9b537c4c.pack │ │ ├── pack-a119d32135c98d4d3e4374ad1ecd525e9b537c4c.promisor │ │ └── pack-a119d32135c98d4d3e4374ad1ecd525e9b537c4c.rev │ ├── packed-refs │ ├── refs/ │ │ ├── heads/ │ │ │ └── master │ │ └── remotes/ │ │ └── origin/ │ │ └── HEAD │ └── shallow ├── .gitattributes ├── .github/ │ ├── .prettierrc │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── config.yml │ │ ├── documentation.yml │ │ └── feature-request.yml │ ├── PULL_REQUEST_TEMPLATE │ ├── actions/ │ │ └── cache-apt-packages-action/ │ │ └── action.yml │ ├── dependabot.yml │ ├── problem-matchers/ │ │ ├── register_all.vsh │ │ └── v.json │ └── workflows/ │ ├── Dockerfile.ci_alpine_local │ ├── add-voting-info.yml │ ├── alpine.build.sh │ ├── alpine.test.sh │ ├── android_cross_compile.vsh │ ├── benchmark_footprint_json_decode.yml │ ├── benchmark_footprint_json_encode.yml │ ├── bootstrapping_ci.yml │ ├── build_on_ubuntu_25_ci.yml │ ├── build_vinix_locally.sh │ ├── c2v_ci.yml │ ├── compare_pr_to_master.v │ ├── compile_discordv.sh │ ├── compile_herolib.sh │ ├── compile_shaders_in_examples.sh │ ├── compile_v_with_vtcc.sh │ ├── compile_vlang_gui_examples.sh │ ├── cross_ci.yml │ ├── debug.yml │ ├── disable_azure_mirror.sh │ ├── docker_ci.yml │ ├── docs_ci.yml │ ├── download_full_toml_test_suites.sh │ ├── find_openssl.bat │ ├── freebsd_ci.yml │ ├── gen_vc_ci.yml │ ├── gg_regressions_ci.yml │ ├── gh_restart_failed.v │ ├── hub_docker_ci.yml │ ├── linux_ci.yml │ ├── macos_ci.yml │ ├── make_sure_ci_run_with_32bit_compiler_test.v │ ├── make_sure_ci_run_with_64bit_compiler_test.v │ ├── module_docs_ci.yml │ ├── module_docs_lint.yml │ ├── more_extensive_but_slower_tests_ci.yml │ ├── native_backend_ci.yml │ ├── openbsd_ci.yml │ ├── other_ci.yml │ ├── paths_ci.yml │ ├── periodic_ci.yml │ ├── prebuilt.yml │ ├── puzzle_vibes_ci.yml │ ├── release_ci.yml │ ├── retry.sh │ ├── riscv64_linux_ci.yml │ ├── run_sanitizers.sh │ ├── run_sanitizers_leak.suppressions │ ├── run_sanitizers_thread.suppressions │ ├── run_sanitizers_undefined.suppressions │ ├── s390x_linux_ci.yml │ ├── sanitized_ci.yml │ ├── sdl_ci.yml │ ├── show_manual_release_cmd.vsh │ ├── ssa_backends_ci.yml.disabled │ ├── symlink_ci.yml │ ├── termux_ci.yml │ ├── time_ci.yml │ ├── toml_ci.yml │ ├── tools_ci.yml │ ├── v_apps_and_modules_compile_ci.yml │ ├── vab_ci.yml │ ├── vinix_ci.yml │ ├── vpm_ci.yml │ ├── vsl_and_vtl_compile_ci.yml │ ├── vup_works.yml │ ├── wasm_backend_ci.yml │ ├── websockets_ci.yml │ ├── windows-install-sdl.bat │ ├── windows-install-sqlite.bat │ ├── windows_ci_gcc.yml │ ├── windows_ci_msvc.yml │ ├── windows_ci_tcc.yml │ └── workflow_lint.yml ├── .gitignore ├── AGENTS.md ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── Dockerfile.alpine ├── Dockerfile.cross ├── GNUmakefile ├── LICENSE ├── Makefile ├── README.md ├── ROADMAP.md ├── TESTS.md ├── bench/ │ ├── README.md │ ├── bench_closure.v │ ├── bench_gc.v │ ├── bench_string_dedup.v │ ├── crypto/ │ │ └── ecdsa/ │ │ ├── ecdsa.c │ │ ├── ecdsa.go │ │ └── ecdsa.v │ └── vectors/ │ ├── README.md │ ├── vectors.cs │ ├── vectors.csproj │ ├── vectors.runtimeconfig.json │ └── vectors.v ├── changelogs0.x/ │ ├── 0.4.md │ └── 0.5.md ├── ci/ │ ├── common/ │ │ └── runner.v │ ├── freebsd_ci.vsh │ ├── linux_ci.vsh │ ├── macos_ci.vsh │ └── openbsd_ci.vsh ├── cmd/ │ ├── tools/ │ │ ├── amalgamate.v │ │ ├── bench/ │ │ │ ├── map_clear.v │ │ │ ├── map_clear_runner.vsh │ │ │ └── wyhash.v │ │ ├── builders/ │ │ │ ├── c_builder.v │ │ │ ├── golang_builder.v │ │ │ ├── interpret_builder.v │ │ │ ├── js_builder.v │ │ │ ├── native_builder.v │ │ │ └── wasm_builder.v │ │ ├── cc_compilation_failed_non_windows.sh │ │ ├── cc_compilation_failed_windows.sh │ │ ├── changelog_helper.v │ │ ├── check_os_api_parity.v │ │ ├── check_retry.vsh │ │ ├── detect_tcc.v │ │ ├── find_doc_comments_with_no_dots.v │ │ ├── fuzz/ │ │ │ ├── fuzz.sh │ │ │ ├── fuzz_v_parser_with_radamsa.sh │ │ │ └── map_fuzz.v │ │ ├── gen1m.v │ │ ├── gen_vc.v │ │ ├── gg_split_memdump_to_frames.vsh │ │ ├── git_pre_commit_hook.vsh │ │ ├── install_binaryen.vsh │ │ ├── install_wabt.vsh │ │ ├── measure/ │ │ │ ├── file_lists/ │ │ │ │ └── expand.v │ │ │ ├── fmt_speed.v │ │ │ ├── parser_speed.v │ │ │ └── scanner_speed.v │ │ ├── modules/ │ │ │ ├── scripting/ │ │ │ │ └── scripting.v │ │ │ ├── testing/ │ │ │ │ ├── common.v │ │ │ │ ├── output.v │ │ │ │ ├── output_dump.v │ │ │ │ ├── output_normal.v │ │ │ │ └── output_teamcity.v │ │ │ └── vgit/ │ │ │ └── vgit.v │ │ ├── oldv.v │ │ ├── performance_compare.v │ │ ├── regress.v │ │ ├── report_v_module_folders_without_tests.v │ │ ├── show_ancient_deprecations.v │ │ ├── test_if_v_test_system_works.v │ │ ├── test_os_args.v │ │ ├── test_os_process.v │ │ ├── translate.v │ │ ├── vast/ │ │ │ ├── cjson.v │ │ │ ├── test/ │ │ │ │ ├── .gitignore │ │ │ │ └── demo.v │ │ │ └── vast.v │ │ ├── vast2/ │ │ │ └── vast2.v │ │ ├── vbin2v.v │ │ ├── vbug.v │ │ ├── vbuild-examples.v │ │ ├── vbuild-tools.v │ │ ├── vbuild-vbinaries.v │ │ ├── vbump.v │ │ ├── vbump_test.v │ │ ├── vcheck-md.v │ │ ├── vcheck_test.v │ │ ├── vcomplete.v │ │ ├── vcomplete_test.v │ │ ├── vcompress.v │ │ ├── vcover/ │ │ │ ├── cover_test.v │ │ │ ├── data.v │ │ │ ├── main.v │ │ │ └── testdata/ │ │ │ ├── example1/ │ │ │ │ ├── abc.v │ │ │ │ ├── internal_abc01_test.v │ │ │ │ ├── internal_abc10_abc30_test.v │ │ │ │ ├── internal_abc20_abc25_test.v │ │ │ │ └── v.mod │ │ │ ├── example2/ │ │ │ │ ├── condition.v │ │ │ │ ├── condition_test.v │ │ │ │ ├── runtime_condition.v │ │ │ │ ├── runtime_condition_test.v │ │ │ │ └── v.mod │ │ │ └── simple/ │ │ │ ├── simple.v │ │ │ ├── t1_test.v │ │ │ ├── t2_test.v │ │ │ └── v.mod │ │ ├── vcreate/ │ │ │ ├── project_model_bin.v │ │ │ ├── project_model_lib.v │ │ │ ├── project_model_web.v │ │ │ ├── tests/ │ │ │ │ ├── init.expect │ │ │ │ ├── init_in_dir_with_invalid_mod_name.expect │ │ │ │ ├── init_with_model_arg.expect │ │ │ │ ├── new_with_model_arg.expect │ │ │ │ ├── new_with_name_arg.expect │ │ │ │ └── new_with_no_arg.expect │ │ │ ├── vcreate.v │ │ │ ├── vcreate_init_test.v │ │ │ ├── vcreate_new_test.v │ │ │ └── vcreate_windows_sqlite_note_test.v │ │ ├── vdiff.v │ │ ├── vdoc/ │ │ │ ├── .gitattributes │ │ │ ├── document/ │ │ │ │ ├── comment.v │ │ │ │ ├── doc.v │ │ │ │ ├── doc_private_fn_test.v │ │ │ │ ├── doc_test.v │ │ │ │ ├── module.v │ │ │ │ ├── node.v │ │ │ │ └── utils.v │ │ │ ├── files.v │ │ │ ├── highlight.v │ │ │ ├── html.v │ │ │ ├── main.v │ │ │ ├── markdown.v │ │ │ ├── run_examples.v │ │ │ ├── testdata/ │ │ │ │ ├── basic/ │ │ │ │ │ ├── basic.comments.out │ │ │ │ │ ├── basic.out │ │ │ │ │ └── basic.v │ │ │ │ ├── comments/ │ │ │ │ │ ├── main.comments.out │ │ │ │ │ ├── main.out │ │ │ │ │ └── main.v │ │ │ │ ├── multiline/ │ │ │ │ │ ├── main.comments.out │ │ │ │ │ ├── main.out │ │ │ │ │ └── main.v │ │ │ │ ├── newlines/ │ │ │ │ │ ├── main.comments.out │ │ │ │ │ ├── main.out │ │ │ │ │ └── main.v │ │ │ │ ├── output_formats/ │ │ │ │ │ ├── README.md │ │ │ │ │ ├── main.ansi │ │ │ │ │ ├── main.html │ │ │ │ │ ├── main.md │ │ │ │ │ ├── main.text │ │ │ │ │ └── main.v │ │ │ │ ├── readme_in_project_root/ │ │ │ │ │ ├── README.md │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── main.comments.out │ │ │ │ │ │ ├── main.readme.comments.out │ │ │ │ │ │ └── main.v │ │ │ │ │ └── v.mod │ │ │ │ ├── run_examples_bad/ │ │ │ │ │ ├── .v.mod.stop │ │ │ │ │ ├── main.comments.out │ │ │ │ │ ├── main.out │ │ │ │ │ └── main.v │ │ │ │ ├── run_examples_good/ │ │ │ │ │ ├── .v.mod.stop │ │ │ │ │ ├── main.comments.out │ │ │ │ │ ├── main.out │ │ │ │ │ └── main.v │ │ │ │ └── unsorted/ │ │ │ │ ├── main.out │ │ │ │ ├── main.unsorted.out │ │ │ │ └── main.v │ │ │ ├── theme/ │ │ │ │ ├── .prettierrc │ │ │ │ ├── dark-mode.js │ │ │ │ ├── doc.css │ │ │ │ ├── doc.js │ │ │ │ ├── favicons/ │ │ │ │ │ ├── browserconfig.xml │ │ │ │ │ └── site.webmanifest │ │ │ │ ├── index.html │ │ │ │ └── normalize.css │ │ │ ├── utils.v │ │ │ ├── v.mod │ │ │ ├── vdoc.v │ │ │ ├── vdoc_file_test.v │ │ │ ├── vdoc_run_examples_test.v │ │ │ └── vdoc_test.v │ │ ├── vdoctor.v │ │ ├── vdownload.v │ │ ├── vfmt.v │ │ ├── vgit-fmt-hook.v │ │ ├── vgit-fmt-hook_test.v │ │ ├── vgret.defaults.toml │ │ ├── vgret.v │ │ ├── vls.v │ │ ├── vmissdoc.v │ │ ├── vpm/ │ │ │ ├── args_test.v │ │ │ ├── common.v │ │ │ ├── dependency_test.v │ │ │ ├── expect/ │ │ │ │ ├── accept_reinstall_mod_with_version_installation.expect │ │ │ │ └── decline_reinstall_mod_with_version_installation.expect │ │ │ ├── install.v │ │ │ ├── install_local_test.v │ │ │ ├── install_test.v │ │ │ ├── install_version_input_test.v │ │ │ ├── install_version_test.v │ │ │ ├── link.v │ │ │ ├── link_test.v │ │ │ ├── outdated.v │ │ │ ├── outdated_test.v │ │ │ ├── parse.v │ │ │ ├── remove_test.v │ │ │ ├── search.v │ │ │ ├── search_test.v │ │ │ ├── settings.v │ │ │ ├── settings_test.v │ │ │ ├── test_utils/ │ │ │ │ └── utils.v │ │ │ ├── update.v │ │ │ ├── update_test.v │ │ │ ├── vcs.v │ │ │ ├── vcs_test.v │ │ │ └── vpm.v │ │ ├── vquest.v │ │ ├── vreduce.v │ │ ├── vrepeat.v │ │ ├── vrepl.v │ │ ├── vretry.v │ │ ├── vretry_test.v │ │ ├── vrun │ │ ├── vscan.v │ │ ├── vschannel_16kb_httpbin_probe.v │ │ ├── vself.v │ │ ├── vsetup-freetype.v │ │ ├── vshader.v │ │ ├── vshare.v │ │ ├── vshould-compile-all.v │ │ ├── vsymlink/ │ │ │ ├── vsymlink.v │ │ │ ├── vsymlink_nix.c.v │ │ │ └── vsymlink_windows.c.v │ │ ├── vtest-all.v │ │ ├── vtest-cleancode.v │ │ ├── vtest-fmt.v │ │ ├── vtest-parser.v │ │ ├── vtest-self.v │ │ ├── vtest.v │ │ ├── vtest_test.v │ │ ├── vtime.v │ │ ├── vtimeout.v │ │ ├── vtimeout_test.v │ │ ├── vtracev.v │ │ ├── vup.v │ │ ├── vvet/ │ │ │ ├── analyze.v │ │ │ ├── errors.v │ │ │ ├── filter.v │ │ │ ├── tests/ │ │ │ │ ├── accept_multi_expression_with_comments.out │ │ │ │ ├── accept_multi_expression_with_comments.vv │ │ │ │ ├── array_init_one_val.out │ │ │ │ ├── array_init_one_val.vv │ │ │ │ ├── brackets_in_documentation_comment_no_warn.out │ │ │ │ ├── brackets_in_documentation_comment_no_warn.vv │ │ │ │ ├── const_dynamic_array_notice.out │ │ │ │ ├── const_dynamic_array_notice.vv │ │ │ │ ├── documentation_for_generic_methods.out │ │ │ │ ├── documentation_for_generic_methods.vv │ │ │ │ ├── empty_fn_decl.out │ │ │ │ ├── empty_fn_decl.vv │ │ │ │ ├── empty_string.out │ │ │ │ ├── empty_string.vv │ │ │ │ ├── indent_with_space.out │ │ │ │ ├── indent_with_space.vv │ │ │ │ ├── module_file_test.out │ │ │ │ ├── module_file_test.vv │ │ │ │ ├── no_warn_about_missing.out │ │ │ │ ├── no_warn_about_missing.vv │ │ │ │ ├── prog_without_main_fn.out │ │ │ │ ├── prog_without_main_fn.vv │ │ │ │ ├── repeated_assign.out │ │ │ │ ├── repeated_assign.vv │ │ │ │ ├── repeated_code.out │ │ │ │ ├── repeated_code.vv │ │ │ │ ├── trailing_space.out │ │ │ │ └── trailing_space.vv │ │ │ ├── vet_test.v │ │ │ └── vvet.v │ │ ├── vwatch.v │ │ ├── vwhere/ │ │ │ ├── finder.v │ │ │ ├── finder_utils.v │ │ │ ├── test/ │ │ │ │ ├── file_common.v │ │ │ │ ├── file_one.v │ │ │ │ ├── file_two.v │ │ │ │ └── nested_mod/ │ │ │ │ └── nested_file.v │ │ │ ├── vwhere.v │ │ │ └── vwhere_test.v │ │ └── vwipe-cache.v │ ├── v/ │ │ ├── v.v │ │ ├── vvm.v │ │ └── vvm_test.v │ └── v2/ │ ├── .gitignore │ ├── README.md │ ├── guiprof/ │ │ ├── draw.v │ │ ├── events.v │ │ ├── main.v │ │ └── state.v │ ├── test.v │ ├── test_all.sh │ ├── test_ssa_backends.v │ ├── test_sumtype.v │ ├── test_sumtype2.v │ ├── test_sumtype3.v │ ├── test_sumtype4.v │ ├── test_sumtype_data.v │ ├── test_sumtype_global.v │ ├── test_sumtype_ifexpr.v │ ├── test_sumtype_many.v │ ├── test_sumtype_nested.v │ ├── test_sumtype_pos.v │ ├── test_v2_self.sh │ └── v2.v ├── doc/ │ ├── c_and_v_type_interoperability.md │ ├── docs.md │ ├── packaging_v_for_distributions.md │ ├── upcoming.md │ └── vscode.md ├── editors/ │ └── vim/ │ ├── README.md │ ├── ftdetect/ │ │ └── v.vim │ ├── ftplugin/ │ │ └── v.vim │ └── syntax/ │ └── v.vim ├── examples/ │ ├── .gitignore │ ├── 1brc/ │ │ ├── README.md │ │ ├── make-samples/ │ │ │ ├── cities.txt │ │ │ └── main.v │ │ └── solution/ │ │ └── main.v │ ├── animated_help_text.v │ ├── archive/ │ │ └── tar_gz_reader.v │ ├── asm.v │ ├── assets/ │ │ ├── fonts/ │ │ │ ├── LICENSE │ │ │ └── OFL.txt │ │ └── v.six │ ├── binary_search_tree.v │ ├── brainvuck.v │ ├── bst_map.v │ ├── buf_reader.v │ ├── build_system/ │ │ ├── .gitignore │ │ ├── build.vsh │ │ └── main.v │ ├── c_interop_wkhtmltopdf.v │ ├── call_c_from_v/ │ │ └── main.c.v │ ├── call_v_from_c/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── v_test_math.v │ │ └── v_test_print.v │ ├── call_v_from_python/ │ │ ├── README.md │ │ ├── test.py │ │ └── test.v │ ├── call_v_from_ruby/ │ │ ├── README.md │ │ ├── test.rb │ │ └── test.v │ ├── cli.v │ ├── clock/ │ │ └── clock.v │ ├── compiletime/ │ │ ├── d_compile_value.v │ │ ├── methods.v │ │ └── reflection.v │ ├── concurrency/ │ │ ├── concurrency.v │ │ ├── concurrency_http.v │ │ └── concurrency_returns.v │ ├── control_thread_stack_size.v │ ├── coroutines/ │ │ ├── .skip_should_compile_all │ │ ├── coroutines_bench.v │ │ └── simple_coroutines.v │ ├── cpu_features/ │ │ └── SSE_and_MMX_Extensions/ │ │ ├── README.md │ │ ├── mmx.v │ │ ├── sse.v │ │ ├── sse2.v │ │ ├── sse3.v │ │ ├── sse4_1.v │ │ └── ssse3.v │ ├── custom_error.v │ ├── database/ │ │ ├── mysql.v │ │ ├── mysql_pool.v │ │ ├── orm.v │ │ ├── psql/ │ │ │ ├── .gitignore │ │ │ ├── customer.v │ │ │ └── mydb.sql │ │ └── sqlite.v │ ├── diff.v │ ├── dump_factorial.v │ ├── dynamic_library_loader/ │ │ ├── modules/ │ │ │ └── library/ │ │ │ └── library.v │ │ ├── use_shared_library.v │ │ └── use_test.v │ ├── dynamic_library_loading/ │ │ ├── modules/ │ │ │ └── library/ │ │ │ └── library.v │ │ ├── use_dl_module.v │ │ └── use_library_test.v │ ├── errors.v │ ├── euler.v │ ├── eventbus/ │ │ ├── eventbus.v │ │ └── modules/ │ │ └── some_module/ │ │ └── some_module.v │ ├── fasthttp/ │ │ ├── README.md │ │ ├── controllers.v │ │ ├── main.v │ │ └── v.mod │ ├── fetch.v │ ├── fetch_ip.v │ ├── fibonacci.v │ ├── file_list.v │ ├── fireworks/ │ │ ├── fireworks.v │ │ └── modules/ │ │ └── objects/ │ │ ├── color.v │ │ ├── constants.v │ │ ├── particle.v │ │ ├── rocket.v │ │ └── vector.v │ ├── fizz_buzz.v │ ├── flag_layout_editor.v │ ├── flappylearning/ │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── README.md │ │ ├── game.v │ │ └── modules/ │ │ └── neuroevolution/ │ │ └── neuronevolution.v │ ├── function_types.v │ ├── game_of_life/ │ │ ├── README.md │ │ ├── life.v │ │ ├── life_gg.v │ │ └── modules/ │ │ └── automaton/ │ │ └── automaton.v │ ├── get_raw_line.v │ ├── get_weather/ │ │ ├── README.md │ │ └── get_weather.v │ ├── gg/ │ │ ├── additive.v │ │ ├── arcs_and_slices.v │ │ ├── bezier.v │ │ ├── bezier_anim.v │ │ ├── bouncing_balls.v │ │ ├── cursor.v │ │ ├── digital_rain.v │ │ ├── drag_n_drop.v │ │ ├── draw_pixels.v │ │ ├── draw_unicode_text_with_gg.v │ │ ├── easing_animation.v │ │ ├── expanding_rect.v │ │ ├── fire.v │ │ ├── grid_of_rectangles.v │ │ ├── mandelbrot.v │ │ ├── many_thousands_of_circles.v │ │ ├── many_thousands_of_circles_overriding_max_vertices.v │ │ ├── memory.v │ │ ├── minesweeper.v │ │ ├── minimal.v │ │ ├── moving_square.v │ │ ├── path_finding_algorithm_visualizer/ │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ └── aStar.v │ │ ├── polygons.v │ │ ├── pong/ │ │ │ ├── README.md │ │ │ └── pong.v │ │ ├── random.v │ │ ├── random_stars.v │ │ ├── raven_text_rendering.v │ │ ├── raycaster.v │ │ ├── rectangles.v │ │ ├── rotating_textured_quad.v │ │ ├── sample_count.v │ │ ├── spirograph.v │ │ ├── stars.v │ │ ├── worker_thread.v │ │ └── x_y_frame.v │ ├── graphs/ │ │ ├── bellman-ford.v │ │ ├── bfs.v │ │ ├── bfs2.v │ │ ├── bfs3.v │ │ ├── dfs.v │ │ ├── dfs2.v │ │ ├── dijkstra.v │ │ ├── minimal_spann_tree_prim.v │ │ ├── topological_sorting_dfs.v │ │ └── topological_sorting_greedy.v │ ├── hanoi.v │ ├── hello_world.v │ ├── hot_reload/ │ │ ├── .gitignore │ │ ├── bounce.v │ │ ├── graph.v │ │ ├── message.v │ │ └── tunnel.v │ ├── http_server.v │ ├── js_dom_cube/ │ │ ├── README.md │ │ ├── cube.js.v │ │ └── index.html │ ├── js_dom_draw/ │ │ ├── README.md │ │ ├── draw.js.v │ │ └── index.html │ ├── js_dom_draw_benchmark_chart/ │ │ ├── README.md │ │ ├── chart/ │ │ │ ├── .gitignore │ │ │ ├── Dockerfile │ │ │ ├── README.md │ │ │ ├── draw.js.v │ │ │ ├── main.v │ │ │ └── templates/ │ │ │ └── controller/ │ │ │ └── get/ │ │ │ └── all/ │ │ │ └── task.html │ │ ├── typescript_vanilla_typeorm/ │ │ │ ├── .gitignore │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── index.ts │ │ │ │ └── server.js │ │ │ └── tsconfig.json │ │ └── v_vweb_orm/ │ │ └── src/ │ │ └── main.v │ ├── js_hello_world.v │ ├── json.v │ ├── jsonrpc/ │ │ ├── client.v │ │ └── server.v │ ├── lander.v │ ├── linear_regression/ │ │ └── simple_linear_regression.v │ ├── links_scraper.v │ ├── log.v │ ├── logfatal.v │ ├── lorem.v │ ├── macos_tray/ │ │ ├── .skip_should_compile_all │ │ ├── tray.m │ │ ├── tray.v │ │ └── v.mod │ ├── mini_calculator.v │ ├── mini_calculator_recursive_descent.v │ ├── minimal_c_like_program_using_puts.v │ ├── native/ │ │ └── hello_world.v │ ├── nbody.v │ ├── net_failconnect.v │ ├── net_peer_ip.v │ ├── net_raw_http.v │ ├── net_resolve.v │ ├── net_t.v │ ├── net_udp_server_and_client.v │ ├── news_fetcher.v │ ├── orm/ │ │ ├── orm_func.v │ │ └── orm_sql.v │ ├── password/ │ │ ├── password.v │ │ ├── password_test.v │ │ └── tests/ │ │ ├── correct.expect │ │ ├── incorrect.expect │ │ └── output_from_expect_arg.expect │ ├── path_tracing.v │ ├── pendulum-simulation/ │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── README.md │ │ ├── animation.v │ │ ├── full.v │ │ ├── modules/ │ │ │ └── sim/ │ │ │ ├── anim/ │ │ │ │ ├── app.v │ │ │ │ └── worker.v │ │ │ ├── args/ │ │ │ │ └── parser.v │ │ │ ├── img/ │ │ │ │ ├── ppm.v │ │ │ │ ├── worker.v │ │ │ │ └── writer.v │ │ │ ├── log.v │ │ │ ├── params.v │ │ │ ├── params_test.v │ │ │ ├── runner.v │ │ │ ├── sim.v │ │ │ ├── sim_test.v │ │ │ ├── vec.v │ │ │ ├── vec_test.v │ │ │ ├── worker.v │ │ │ └── worker_test.v │ │ ├── parallel.v │ │ ├── parallel_with_iw.v │ │ └── sequential.v │ ├── pico/ │ │ ├── pico.v │ │ └── raw_callback.v │ ├── pidigits.v │ ├── poll_coindesk_bitcoin_vs_usd_rate.v │ ├── primes.v │ ├── process/ │ │ ├── command.v │ │ ├── execve.v │ │ ├── monitor_for_file_changes_with_inotifywait.v │ │ ├── process_script.v │ │ ├── wrapping_interactive_python.v │ │ └── write_and_read_from_a_bash_child_process.v │ ├── quadtree_demo/ │ │ └── quadtree_demo.v │ ├── quick_sort.v │ ├── random_ips.v │ ├── readdir.v │ ├── readline/ │ │ ├── readline.v │ │ ├── readline_test.v │ │ └── tests/ │ │ ├── readline.expect │ │ └── readline_from_expect_arg.expect │ ├── regex/ │ │ ├── pcre.v │ │ ├── readme.md │ │ ├── regex_example.v │ │ └── regex_with_memoization.v │ ├── rule110.v │ ├── rune.v │ ├── sha256sum_with_io_cp.v │ ├── smtp/ │ │ └── mail.v │ ├── snek/ │ │ ├── README.md │ │ ├── index.html │ │ ├── snek.js.v │ │ └── snek.v │ ├── sokol/ │ │ ├── .gitignore │ │ ├── 01_cubes/ │ │ │ └── cube.v │ │ ├── 02_cubes_glsl/ │ │ │ ├── cube_glsl.glsl │ │ │ ├── cube_glsl.v │ │ │ └── v.mod │ │ ├── 03_march_tracing_glsl/ │ │ │ ├── rt_glsl.glsl │ │ │ ├── rt_glsl.v │ │ │ └── v.mod │ │ ├── 04_multi_shader_glsl/ │ │ │ ├── rt_glsl.v │ │ │ ├── rt_glsl_march.glsl │ │ │ ├── rt_glsl_puppy.glsl │ │ │ └── v.mod │ │ ├── 05_instancing_glsl/ │ │ │ ├── rt_glsl.v │ │ │ ├── rt_glsl_instancing.glsl │ │ │ └── v.mod │ │ ├── 06_obj_viewer/ │ │ │ ├── assets/ │ │ │ │ └── models/ │ │ │ │ ├── apple.mtl │ │ │ │ ├── donut.mtl │ │ │ │ └── v.mtl │ │ │ ├── gouraud.glsl │ │ │ ├── modules/ │ │ │ │ └── obj/ │ │ │ │ ├── obj.v │ │ │ │ ├── rend.v │ │ │ │ ├── struct.v │ │ │ │ └── util.v │ │ │ ├── show_obj.v │ │ │ └── v.mod │ │ ├── 07_simple_shader_glsl/ │ │ │ ├── .gitignore │ │ │ ├── simple_shader.glsl │ │ │ ├── simple_shader.v │ │ │ └── v.mod │ │ ├── 08_sdf/ │ │ │ ├── .gitignore │ │ │ ├── sdf.glsl │ │ │ ├── sdf.v │ │ │ └── v.mod │ │ ├── clear.v │ │ ├── drawing.v │ │ ├── fonts.v │ │ ├── freetype_raven.v │ │ ├── particles/ │ │ │ ├── modules/ │ │ │ │ └── particle/ │ │ │ │ ├── LICENSE │ │ │ │ ├── color.v │ │ │ │ ├── particle.v │ │ │ │ └── system.v │ │ │ └── particles.v │ │ └── sounds/ │ │ ├── melody.v │ │ ├── ogg_player.v │ │ ├── pickup.ogg │ │ ├── simple_bytebeat.v │ │ ├── simple_keyboard_synth.v │ │ ├── simple_sin_tone_using_audio_push.v │ │ ├── simple_sin_tones.v │ │ └── wav_player.v │ ├── spectral.v │ ├── ssl_server/ │ │ ├── cert/ │ │ │ ├── ca.crt │ │ │ ├── client.crt │ │ │ ├── client.key │ │ │ ├── makecerts.sh │ │ │ ├── server.crt │ │ │ └── server.key │ │ ├── client.v │ │ ├── server.v │ │ ├── server_sni.v │ │ └── server_sni_advanced.v │ ├── submodule/ │ │ ├── main.v │ │ ├── mymodules/ │ │ │ ├── main_functions.v │ │ │ └── submodule/ │ │ │ └── sub_functions.v │ │ └── v.mod │ ├── sudoku.v │ ├── sync_pool.v │ ├── tcp_echo_server.v │ ├── tcp_notify_echo_server.v │ ├── templates/ │ │ ├── data.json │ │ ├── readme.md │ │ ├── template.md │ │ └── templates.v │ ├── term.ui/ │ │ ├── README.md │ │ ├── cursor_chaser.v │ │ ├── event_viewer.v │ │ ├── pong.v │ │ ├── rectangles.v │ │ ├── term_drawing.v │ │ ├── text_editor.v │ │ └── vyper.v │ ├── term_display_sixel.v │ ├── term_key_pressed.v │ ├── terminal_control.v │ ├── thread_safety/ │ │ ├── .gitignore │ │ ├── atomic_counter.v │ │ ├── concurrent_shared_data.v │ │ ├── queue.v │ │ └── readme.md │ ├── toml.v │ ├── tree_of_nodes.v │ ├── ttf_font/ │ │ ├── draw_static_text.txt │ │ ├── draw_static_text.v │ │ └── example_ttf.v │ ├── v_script.vsh │ ├── vascii.v │ ├── vcasino/ │ │ ├── README.md │ │ └── vcasino.v │ ├── veb/ │ │ ├── cors/ │ │ │ └── veb_cors_example.v │ │ ├── custom.html │ │ ├── file_transform/ │ │ │ ├── file_transform.v │ │ │ ├── index.html │ │ │ ├── sample_input.txt │ │ │ └── upload.html │ │ ├── file_upload/ │ │ │ ├── file_uploading.v │ │ │ ├── index.html │ │ │ ├── submit.html │ │ │ └── upload.html │ │ ├── footer.html │ │ ├── header.html │ │ ├── index.html │ │ ├── middleware/ │ │ │ ├── templates/ │ │ │ │ ├── base.html │ │ │ │ ├── early.html │ │ │ │ ├── index.html │ │ │ │ └── secret.html │ │ │ └── using_middleware.v │ │ ├── server_sent_events/ │ │ │ ├── assets/ │ │ │ │ └── site.css │ │ │ ├── index.html │ │ │ └── server.v │ │ ├── static_website/ │ │ │ ├── README.md │ │ │ ├── dist/ │ │ │ │ ├── another.html │ │ │ │ └── index.html │ │ │ └── server.v │ │ ├── todo/ │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── assets/ │ │ │ │ └── main.css │ │ │ ├── main.v │ │ │ └── templates/ │ │ │ └── index.html │ │ ├── veb_assets/ │ │ │ ├── assets/ │ │ │ │ └── index.css │ │ │ ├── index.html │ │ │ └── vweb_assets.v │ │ ├── veb_example.v │ │ └── websocket/ │ │ ├── assets/ │ │ │ └── style.css │ │ ├── index.html │ │ └── server.v │ ├── viewer/ │ │ ├── LICENSE │ │ ├── README.md │ │ ├── file_scan.v │ │ ├── v.mod │ │ ├── view.v │ │ └── zip_container.v │ ├── vmatrix.v │ ├── vmod.v │ ├── vpwgen.v │ ├── vtail.v │ ├── vwatch/ │ │ ├── cli_clock/ │ │ │ └── main.v │ │ └── web_server/ │ │ ├── .gitignore │ │ └── main.v │ ├── vweb_fullstack/ │ │ ├── .editorconfig │ │ ├── .gitattributes │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── readme.md │ │ └── src/ │ │ ├── auth_controllers.v │ │ ├── auth_dto.v │ │ ├── auth_services.v │ │ ├── databases/ │ │ │ └── config_databases_sqlite.v │ │ ├── index.html │ │ ├── main.v │ │ ├── product_controller.v │ │ ├── product_entities.v │ │ ├── product_service.v │ │ ├── product_view.v │ │ ├── product_view_api.v │ │ ├── templates/ │ │ │ ├── header_component.html │ │ │ ├── products.css │ │ │ └── products.html │ │ ├── user_controllers.v │ │ ├── user_entities.v │ │ ├── user_services.v │ │ ├── user_view_api.v │ │ └── v.mod │ ├── vweb_orm_jwt/ │ │ ├── .editorconfig │ │ ├── .gitattributes │ │ ├── .gitignore │ │ └── src/ │ │ ├── auth_controllers.v │ │ ├── auth_dto.v │ │ ├── auth_services.v │ │ ├── databases/ │ │ │ └── config_databases_sqlite.v │ │ ├── main.v │ │ ├── user_controllers.v │ │ ├── user_entities.v │ │ ├── user_services.v │ │ └── v.mod │ ├── wasm/ │ │ ├── .gitignore │ │ ├── change_color_by_id/ │ │ │ ├── README.md │ │ │ ├── change_color_by_id.html │ │ │ ├── change_color_by_id.wasm.v │ │ │ └── serve_folder.v │ │ ├── functions.v │ │ ├── hello_world.v │ │ └── mandelbrot/ │ │ ├── README.md │ │ ├── mandelbrot.html │ │ ├── mandelbrot.wasm.v │ │ └── serve_folder.v │ ├── wasm_codegen/ │ │ ├── add.v │ │ ├── bf_compiler.v │ │ ├── control_flow.v │ │ ├── factorial.v │ │ ├── functions.v │ │ ├── hello_wasi.v │ │ └── memory.v │ ├── web_crawler/ │ │ ├── README.md │ │ └── web_crawler.v │ ├── websocket/ │ │ ├── client-server/ │ │ │ ├── client.v │ │ │ └── server.v │ │ └── ping.v │ └── word_counter/ │ ├── README.md │ ├── cinderella.txt │ └── word_counter.v ├── make.bat ├── thirdparty/ │ ├── .gitignore │ ├── android/ │ │ └── android.h │ ├── build_scripts/ │ │ ├── README.md │ │ ├── thirdparty-freebsd-amd64_bdwgc.sh │ │ ├── thirdparty-freebsd-amd64_tcc.sh │ │ ├── thirdparty-linux-amd64_bdwgc.sh │ │ ├── thirdparty-linux-amd64_tcc.sh │ │ ├── thirdparty-linux-armv7_bdwgc.sh │ │ ├── thirdparty-macos-arm64_bdwgc.sh │ │ ├── thirdparty-macos-arm64_tcc.sh │ │ └── thirdparty-openbsd-amd64_tcc.sh │ ├── cJSON/ │ │ ├── README.md │ │ ├── cJSON.c │ │ └── cJSON.h │ ├── fontstash/ │ │ ├── fontstash.h │ │ └── stb_truetype.h │ ├── ios/ │ │ └── ios.m │ ├── libatomic_ops/ │ │ ├── LICENSE │ │ ├── atomic_ops/ │ │ │ ├── ao_version.h │ │ │ ├── generalize-arithm.h │ │ │ ├── generalize-arithm.template │ │ │ ├── generalize-small.h │ │ │ ├── generalize-small.template │ │ │ ├── generalize.h │ │ │ └── sysdeps/ │ │ │ ├── all_acquire_release_volatile.h │ │ │ ├── all_aligned_atomic_load_store.h │ │ │ ├── all_atomic_load_store.h │ │ │ ├── all_atomic_only_load.h │ │ │ ├── ao_t_is_int.h │ │ │ ├── ao_t_is_int.template │ │ │ ├── armcc/ │ │ │ │ └── arm_v6.h │ │ │ ├── emul_cas.h │ │ │ ├── gcc/ │ │ │ │ ├── aarch64.h │ │ │ │ ├── alpha.h │ │ │ │ ├── arm.h │ │ │ │ ├── avr32.h │ │ │ │ ├── cris.h │ │ │ │ ├── e2k.h │ │ │ │ ├── generic-arithm.h │ │ │ │ ├── generic-arithm.template │ │ │ │ ├── generic-small.h │ │ │ │ ├── generic-small.template │ │ │ │ ├── generic.h │ │ │ │ ├── hexagon.h │ │ │ │ ├── hppa.h │ │ │ │ ├── ia64.h │ │ │ │ ├── m68k.h │ │ │ │ ├── mips.h │ │ │ │ ├── powerpc.h │ │ │ │ ├── riscv.h │ │ │ │ ├── s390.h │ │ │ │ ├── sh.h │ │ │ │ ├── sparc.h │ │ │ │ ├── tile.h │ │ │ │ └── x86.h │ │ │ ├── generic_pthread.h │ │ │ ├── hpc/ │ │ │ │ ├── hppa.h │ │ │ │ └── ia64.h │ │ │ ├── ibmc/ │ │ │ │ └── powerpc.h │ │ │ ├── icc/ │ │ │ │ └── ia64.h │ │ │ ├── loadstore/ │ │ │ │ ├── acquire_release_volatile.h │ │ │ │ ├── acquire_release_volatile.template │ │ │ │ ├── atomic_load.h │ │ │ │ ├── atomic_load.template │ │ │ │ ├── atomic_store.h │ │ │ │ ├── atomic_store.template │ │ │ │ ├── char_acquire_release_volatile.h │ │ │ │ ├── char_atomic_load.h │ │ │ │ ├── char_atomic_store.h │ │ │ │ ├── double_atomic_load_store.h │ │ │ │ ├── int_acquire_release_volatile.h │ │ │ │ ├── int_atomic_load.h │ │ │ │ ├── int_atomic_store.h │ │ │ │ ├── ordered_loads_only.h │ │ │ │ ├── ordered_loads_only.template │ │ │ │ ├── ordered_stores_only.h │ │ │ │ ├── ordered_stores_only.template │ │ │ │ ├── short_acquire_release_volatile.h │ │ │ │ ├── short_atomic_load.h │ │ │ │ └── short_atomic_store.h │ │ │ ├── msftc/ │ │ │ │ ├── arm.h │ │ │ │ ├── arm64.h │ │ │ │ ├── common32_defs.h │ │ │ │ ├── x86.h │ │ │ │ └── x86_64.h │ │ │ ├── ordered.h │ │ │ ├── ordered_except_wr.h │ │ │ ├── read_ordered.h │ │ │ ├── standard_ao_double_t.h │ │ │ ├── sunc/ │ │ │ │ ├── sparc.S │ │ │ │ ├── sparc.h │ │ │ │ └── x86.h │ │ │ ├── test_and_set_t_is_ao_t.h │ │ │ └── test_and_set_t_is_char.h │ │ ├── atomic_ops.c │ │ ├── atomic_ops.h │ │ ├── atomic_ops_malloc.c │ │ ├── atomic_ops_malloc.h │ │ └── atomic_ops_sysdeps.S │ ├── libbacktrace/ │ │ ├── amalgamation.txt │ │ ├── backtrace.c │ │ ├── backtrace.h │ │ ├── base.c │ │ ├── darwin.c │ │ ├── linux.c │ │ └── windows.c │ ├── libgc/ │ │ ├── amalgamation.txt │ │ ├── gc.c │ │ └── include/ │ │ ├── gc/ │ │ │ ├── cord.h │ │ │ ├── cord_pos.h │ │ │ ├── ec.h │ │ │ ├── gc.h │ │ │ ├── gc_allocator.h │ │ │ ├── gc_backptr.h │ │ │ ├── gc_config_macros.h │ │ │ ├── gc_disclaim.h │ │ │ ├── gc_gcj.h │ │ │ ├── gc_inline.h │ │ │ ├── gc_mark.h │ │ │ ├── gc_pthread_redirects.h │ │ │ ├── gc_tiny_fl.h │ │ │ ├── gc_typed.h │ │ │ ├── gc_version.h │ │ │ ├── javaxfc.h │ │ │ └── leak_detector.h │ │ └── gc.h │ ├── mbedtls/ │ │ ├── 3rdparty/ │ │ │ ├── everest/ │ │ │ │ ├── README.md │ │ │ │ ├── include/ │ │ │ │ │ └── everest/ │ │ │ │ │ ├── Hacl_Curve25519.h │ │ │ │ │ ├── everest.h │ │ │ │ │ ├── kremlib/ │ │ │ │ │ │ ├── FStar_UInt128.h │ │ │ │ │ │ └── FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8.h │ │ │ │ │ ├── kremlib.h │ │ │ │ │ ├── kremlin/ │ │ │ │ │ │ ├── c_endianness.h │ │ │ │ │ │ └── internal/ │ │ │ │ │ │ ├── builtin.h │ │ │ │ │ │ ├── callconv.h │ │ │ │ │ │ ├── compat.h │ │ │ │ │ │ ├── debug.h │ │ │ │ │ │ ├── target.h │ │ │ │ │ │ ├── types.h │ │ │ │ │ │ └── wasmsupport.h │ │ │ │ │ ├── vs2013/ │ │ │ │ │ │ └── Hacl_Curve25519.h │ │ │ │ │ └── x25519.h │ │ │ │ └── library/ │ │ │ │ ├── Hacl_Curve25519.c │ │ │ │ ├── Hacl_Curve25519_joined.c │ │ │ │ ├── everest.c │ │ │ │ ├── kremlib/ │ │ │ │ │ ├── FStar_UInt128_extracted.c │ │ │ │ │ └── FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8.c │ │ │ │ ├── legacy/ │ │ │ │ │ └── Hacl_Curve25519.c │ │ │ │ └── x25519.c │ │ │ └── p256-m/ │ │ │ ├── README.md │ │ │ ├── p256-m/ │ │ │ │ ├── README.md │ │ │ │ ├── p256-m.c │ │ │ │ └── p256-m.h │ │ │ ├── p256-m_driver_entrypoints.c │ │ │ └── p256-m_driver_entrypoints.h │ │ ├── LICENSE │ │ ├── README.md │ │ ├── fix.md │ │ ├── include/ │ │ │ ├── mbedtls/ │ │ │ │ ├── aes.h │ │ │ │ ├── aria.h │ │ │ │ ├── asn1.h │ │ │ │ ├── asn1write.h │ │ │ │ ├── base64.h │ │ │ │ ├── bignum.h │ │ │ │ ├── block_cipher.h │ │ │ │ ├── build_info.h │ │ │ │ ├── camellia.h │ │ │ │ ├── ccm.h │ │ │ │ ├── chacha20.h │ │ │ │ ├── chachapoly.h │ │ │ │ ├── check_config.h │ │ │ │ ├── cipher.h │ │ │ │ ├── cmac.h │ │ │ │ ├── compat-2.x.h │ │ │ │ ├── config_adjust_legacy_crypto.h │ │ │ │ ├── config_adjust_legacy_from_psa.h │ │ │ │ ├── config_adjust_psa_from_legacy.h │ │ │ │ ├── config_adjust_psa_superset_legacy.h │ │ │ │ ├── config_adjust_ssl.h │ │ │ │ ├── config_adjust_x509.h │ │ │ │ ├── config_psa.h │ │ │ │ ├── constant_time.h │ │ │ │ ├── ctr_drbg.h │ │ │ │ ├── debug.h │ │ │ │ ├── des.h │ │ │ │ ├── dhm.h │ │ │ │ ├── ecdh.h │ │ │ │ ├── ecdsa.h │ │ │ │ ├── ecjpake.h │ │ │ │ ├── ecp.h │ │ │ │ ├── entropy.h │ │ │ │ ├── error.h │ │ │ │ ├── gcm.h │ │ │ │ ├── hkdf.h │ │ │ │ ├── hmac_drbg.h │ │ │ │ ├── lms.h │ │ │ │ ├── mbedtls_config.h │ │ │ │ ├── md.h │ │ │ │ ├── md5.h │ │ │ │ ├── memory_buffer_alloc.h │ │ │ │ ├── net_sockets.h │ │ │ │ ├── nist_kw.h │ │ │ │ ├── oid.h │ │ │ │ ├── pem.h │ │ │ │ ├── pk.h │ │ │ │ ├── pkcs12.h │ │ │ │ ├── pkcs5.h │ │ │ │ ├── pkcs7.h │ │ │ │ ├── platform.h │ │ │ │ ├── platform_time.h │ │ │ │ ├── platform_util.h │ │ │ │ ├── poly1305.h │ │ │ │ ├── private_access.h │ │ │ │ ├── psa_util.h │ │ │ │ ├── ripemd160.h │ │ │ │ ├── rsa.h │ │ │ │ ├── sha1.h │ │ │ │ ├── sha256.h │ │ │ │ ├── sha3.h │ │ │ │ ├── sha512.h │ │ │ │ ├── ssl.h │ │ │ │ ├── ssl_cache.h │ │ │ │ ├── ssl_ciphersuites.h │ │ │ │ ├── ssl_cookie.h │ │ │ │ ├── ssl_ticket.h │ │ │ │ ├── threading.h │ │ │ │ ├── timing.h │ │ │ │ ├── version.h │ │ │ │ ├── x509.h │ │ │ │ ├── x509_crl.h │ │ │ │ ├── x509_crt.h │ │ │ │ └── x509_csr.h │ │ │ └── psa/ │ │ │ ├── build_info.h │ │ │ ├── crypto.h │ │ │ ├── crypto_adjust_auto_enabled.h │ │ │ ├── crypto_adjust_config_dependencies.h │ │ │ ├── crypto_adjust_config_key_pair_types.h │ │ │ ├── crypto_adjust_config_synonyms.h │ │ │ ├── crypto_builtin_composites.h │ │ │ ├── crypto_builtin_key_derivation.h │ │ │ ├── crypto_builtin_primitives.h │ │ │ ├── crypto_compat.h │ │ │ ├── crypto_config.h │ │ │ ├── crypto_driver_common.h │ │ │ ├── crypto_driver_contexts_composites.h │ │ │ ├── crypto_driver_contexts_key_derivation.h │ │ │ ├── crypto_driver_contexts_primitives.h │ │ │ ├── crypto_extra.h │ │ │ ├── crypto_legacy.h │ │ │ ├── crypto_platform.h │ │ │ ├── crypto_se_driver.h │ │ │ ├── crypto_sizes.h │ │ │ ├── crypto_struct.h │ │ │ ├── crypto_types.h │ │ │ └── crypto_values.h │ │ ├── library/ │ │ │ ├── aes.c │ │ │ ├── aesce.c │ │ │ ├── aesce.h │ │ │ ├── aesni.c │ │ │ ├── aesni.h │ │ │ ├── alignment.h │ │ │ ├── aria.c │ │ │ ├── asn1parse.c │ │ │ ├── asn1write.c │ │ │ ├── base64.c │ │ │ ├── base64_internal.h │ │ │ ├── bignum.c │ │ │ ├── bignum_core.c │ │ │ ├── bignum_core.h │ │ │ ├── bignum_core_invasive.h │ │ │ ├── bignum_internal.h │ │ │ ├── bignum_mod.c │ │ │ ├── bignum_mod.h │ │ │ ├── bignum_mod_raw.c │ │ │ ├── bignum_mod_raw.h │ │ │ ├── bignum_mod_raw_invasive.h │ │ │ ├── block_cipher.c │ │ │ ├── block_cipher_internal.h │ │ │ ├── bn_mul.h │ │ │ ├── camellia.c │ │ │ ├── ccm.c │ │ │ ├── chacha20.c │ │ │ ├── chachapoly.c │ │ │ ├── check_crypto_config.h │ │ │ ├── cipher.c │ │ │ ├── cipher_invasive.h │ │ │ ├── cipher_wrap.c │ │ │ ├── cipher_wrap.h │ │ │ ├── cmac.c │ │ │ ├── common.h │ │ │ ├── constant_time.c │ │ │ ├── constant_time_impl.h │ │ │ ├── constant_time_internal.h │ │ │ ├── ctr.h │ │ │ ├── ctr_drbg.c │ │ │ ├── debug.c │ │ │ ├── debug_internal.h │ │ │ ├── des.c │ │ │ ├── dhm.c │ │ │ ├── ecdh.c │ │ │ ├── ecdsa.c │ │ │ ├── ecjpake.c │ │ │ ├── ecp.c │ │ │ ├── ecp_curves.c │ │ │ ├── ecp_curves_new.c │ │ │ ├── ecp_internal_alt.h │ │ │ ├── ecp_invasive.h │ │ │ ├── entropy.c │ │ │ ├── entropy_poll.c │ │ │ ├── entropy_poll.h │ │ │ ├── error.c │ │ │ ├── gcm.c │ │ │ ├── hkdf.c │ │ │ ├── hmac_drbg.c │ │ │ ├── lmots.c │ │ │ ├── lmots.h │ │ │ ├── lms.c │ │ │ ├── md.c │ │ │ ├── md5.c │ │ │ ├── md_psa.h │ │ │ ├── md_wrap.h │ │ │ ├── memory_buffer_alloc.c │ │ │ ├── mps_common.h │ │ │ ├── mps_error.h │ │ │ ├── mps_reader.c │ │ │ ├── mps_reader.h │ │ │ ├── mps_trace.c │ │ │ ├── mps_trace.h │ │ │ ├── net_sockets.c │ │ │ ├── nist_kw.c │ │ │ ├── oid.c │ │ │ ├── padlock.c │ │ │ ├── padlock.h │ │ │ ├── pem.c │ │ │ ├── pk.c │ │ │ ├── pk_ecc.c │ │ │ ├── pk_internal.h │ │ │ ├── pk_wrap.c │ │ │ ├── pk_wrap.h │ │ │ ├── pkcs12.c │ │ │ ├── pkcs5.c │ │ │ ├── pkcs7.c │ │ │ ├── pkparse.c │ │ │ ├── pkwrite.c │ │ │ ├── pkwrite.h │ │ │ ├── platform.c │ │ │ ├── platform_util.c │ │ │ ├── poly1305.c │ │ │ ├── psa_crypto.c │ │ │ ├── psa_crypto_aead.c │ │ │ ├── psa_crypto_aead.h │ │ │ ├── psa_crypto_cipher.c │ │ │ ├── psa_crypto_cipher.h │ │ │ ├── psa_crypto_client.c │ │ │ ├── psa_crypto_core.h │ │ │ ├── psa_crypto_core_common.h │ │ │ ├── psa_crypto_driver_wrappers.h │ │ │ ├── psa_crypto_driver_wrappers_no_static.c │ │ │ ├── psa_crypto_driver_wrappers_no_static.h │ │ │ ├── psa_crypto_ecp.c │ │ │ ├── psa_crypto_ecp.h │ │ │ ├── psa_crypto_ffdh.c │ │ │ ├── psa_crypto_ffdh.h │ │ │ ├── psa_crypto_hash.c │ │ │ ├── psa_crypto_hash.h │ │ │ ├── psa_crypto_invasive.h │ │ │ ├── psa_crypto_its.h │ │ │ ├── psa_crypto_mac.c │ │ │ ├── psa_crypto_mac.h │ │ │ ├── psa_crypto_pake.c │ │ │ ├── psa_crypto_pake.h │ │ │ ├── psa_crypto_random_impl.h │ │ │ ├── psa_crypto_rsa.c │ │ │ ├── psa_crypto_rsa.h │ │ │ ├── psa_crypto_se.c │ │ │ ├── psa_crypto_se.h │ │ │ ├── psa_crypto_slot_management.c │ │ │ ├── psa_crypto_slot_management.h │ │ │ ├── psa_crypto_storage.c │ │ │ ├── psa_crypto_storage.h │ │ │ ├── psa_its_file.c │ │ │ ├── psa_util.c │ │ │ ├── psa_util_internal.h │ │ │ ├── ripemd160.c │ │ │ ├── rsa.c │ │ │ ├── rsa_alt_helpers.c │ │ │ ├── rsa_alt_helpers.h │ │ │ ├── rsa_internal.h │ │ │ ├── sha1.c │ │ │ ├── sha256.c │ │ │ ├── sha3.c │ │ │ ├── sha512.c │ │ │ ├── ssl_cache.c │ │ │ ├── ssl_ciphersuites.c │ │ │ ├── ssl_ciphersuites_internal.h │ │ │ ├── ssl_client.c │ │ │ ├── ssl_client.h │ │ │ ├── ssl_cookie.c │ │ │ ├── ssl_debug_helpers.h │ │ │ ├── ssl_debug_helpers_generated.c │ │ │ ├── ssl_misc.h │ │ │ ├── ssl_msg.c │ │ │ ├── ssl_ticket.c │ │ │ ├── ssl_tls.c │ │ │ ├── ssl_tls12_client.c │ │ │ ├── ssl_tls12_server.c │ │ │ ├── ssl_tls13_client.c │ │ │ ├── ssl_tls13_generic.c │ │ │ ├── ssl_tls13_invasive.h │ │ │ ├── ssl_tls13_keys.c │ │ │ ├── ssl_tls13_keys.h │ │ │ ├── ssl_tls13_server.c │ │ │ ├── threading.c │ │ │ ├── threading_internal.h │ │ │ ├── timing.c │ │ │ ├── version.c │ │ │ ├── version_features.c │ │ │ ├── x509.c │ │ │ ├── x509_create.c │ │ │ ├── x509_crl.c │ │ │ ├── x509_crt.c │ │ │ ├── x509_csr.c │ │ │ ├── x509_internal.h │ │ │ ├── x509write.c │ │ │ ├── x509write_crt.c │ │ │ └── x509write_csr.c │ │ ├── mbedtls.patch │ │ └── update.vsh │ ├── mssql/ │ │ └── include/ │ │ ├── .gitignore │ │ └── mssql.h │ ├── photon/ │ │ └── photonwrapper.h │ ├── picoev/ │ │ ├── picoev.c │ │ └── src/ │ │ ├── README.md │ │ ├── picoev.h │ │ ├── picoev_epoll.c │ │ ├── picoev_kqueue.c │ │ ├── picoev_select.c │ │ └── picoev_w32.h │ ├── picohttpparser/ │ │ ├── README.md │ │ ├── picohttpparser.c │ │ ├── picohttpparser.h │ │ └── src/ │ │ ├── README.md │ │ ├── picohttpparser.c │ │ └── picohttpparser.h │ ├── sokol/ │ │ ├── README.md │ │ ├── cursor-shape-v1-client-protocol.h │ │ ├── cursor-shape-v1-protocol.c │ │ ├── fractional-scale-v1-client-protocol.h │ │ ├── fractional-scale-v1-protocol.c │ │ ├── gen_wayland_protocols.vsh │ │ ├── pointer-constraints-unstable-v1-client-protocol.h │ │ ├── pointer-constraints-unstable-v1-protocol.c │ │ ├── relative-pointer-unstable-v1-client-protocol.h │ │ ├── relative-pointer-unstable-v1-protocol.c │ │ ├── sokol_app.h │ │ ├── sokol_app2.h │ │ ├── sokol_audio.h │ │ ├── sokol_gfx.h │ │ ├── sokol_log.h │ │ ├── sokol_v.post.h │ │ ├── tablet-unstable-v2-client-protocol.h │ │ ├── tablet-unstable-v2-protocol.c │ │ ├── util/ │ │ │ ├── sokol_fontstash.h │ │ │ └── sokol_gl.h │ │ ├── viewporter-client-protocol.h │ │ ├── viewporter-protocol.c │ │ ├── xdg-decoration-unstable-v1-client-protocol.h │ │ ├── xdg-decoration-unstable-v1-protocol.c │ │ ├── xdg-shell-client-protocol.h │ │ ├── xdg-shell-protocol.c │ │ ├── xdg-toplevel-icon-v1-client-protocol.h │ │ └── xdg-toplevel-icon-v1-protocol.c │ ├── stb_image/ │ │ ├── README.md │ │ ├── stb_image.h │ │ ├── stb_image_resize2.h │ │ ├── stb_image_write.h │ │ ├── stb_v_header.h │ │ └── stbi.c │ ├── stb_vorbis/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── stb_vorbis.c │ │ └── stb_vorbis.h │ ├── stdatomic/ │ │ ├── nix/ │ │ │ ├── atomic.S │ │ │ ├── atomic.h │ │ │ ├── atomic_cpp.h │ │ │ └── cpp/ │ │ │ └── gen.v │ │ └── win/ │ │ └── atomic.h │ ├── vgc/ │ │ └── vgc_platform.h │ ├── vschannel/ │ │ ├── vschannel.c │ │ └── vschannel.h │ ├── walloc/ │ │ └── walloc.c │ ├── zip/ │ │ ├── README.md │ │ ├── miniz.h │ │ ├── zip.c │ │ └── zip.h │ └── zstd/ │ ├── README.md │ ├── fix.md │ ├── update.vsh │ ├── zstd.c │ └── zstd_v.patch ├── tutorials/ │ ├── C2V_translating_simple_programs_and_DOOM/ │ │ └── README.md │ └── building_a_simple_web_blog_with_veb/ │ ├── README.md │ └── code/ │ └── blog/ │ ├── .gitignore │ ├── article.v │ ├── blog.v │ ├── index.html │ └── new.html ├── v.mod └── vlib/ ├── .vdocignore ├── README.md ├── archive/ │ ├── README.md │ └── tar/ │ ├── README.md │ ├── reader.v │ ├── reader_test.v │ ├── tar.v │ └── untar.v ├── arrays/ │ ├── README.md │ ├── arrays.v │ ├── arrays_fold_test.v │ ├── arrays_test.v │ ├── diff/ │ │ ├── diff.v │ │ └── diff_test.v │ ├── index_of.v │ ├── map_of.v │ ├── parallel/ │ │ ├── parallel.v │ │ └── parallel_test.v │ ├── reverse_iterator.v │ ├── reverse_iterator_test.v │ ├── uniq.v │ └── uniq_test.v ├── benchmark/ │ ├── README.md │ ├── benchmark.v │ └── benchmark_test.v ├── bitfield/ │ ├── README.md │ ├── bitfield.v │ └── bitfield_test.v ├── build/ │ ├── README.md │ └── build.v ├── builtin/ │ ├── README.md │ ├── allocation.c.v │ ├── array.v │ ├── array_d_gcboehm_opt.v │ ├── array_flags_test.v │ ├── array_notd_gcboehm_opt.v │ ├── array_test.v │ ├── backtraces.c.v │ ├── backtraces_nix.c.v │ ├── backtraces_windows.c.v │ ├── builtin.c.v │ ├── builtin.v │ ├── builtin_android_outside_termux.c.v │ ├── builtin_backtraces_d_musl.c.v │ ├── builtin_backtraces_nix.c.v │ ├── builtin_d_gcboehm.c.v │ ├── builtin_d_use_libbacktrace.c.v │ ├── builtin_d_vgc.c.v │ ├── builtin_ios.c.v │ ├── builtin_nix.c.v │ ├── builtin_notd_gcboehm.c.v │ ├── builtin_notd_use_libbacktrace.c.v │ ├── builtin_test.c.v │ ├── builtin_unbuffer_stdout_test.v │ ├── builtin_windows.c.v │ ├── byte_test.v │ ├── cfns.c.v │ ├── cfns_wrapper.c.v │ ├── chan_option_result.v │ ├── character_inout.c.v │ ├── character_inout_test.v │ ├── closure/ │ │ ├── README.md │ │ ├── closure.c.v │ │ ├── closure.v │ │ ├── closure_nix.c.v │ │ └── closure_windows.c.v │ ├── fixed_array_test.v │ ├── float.c.v │ ├── float_test.v │ ├── gated_array_string_test.v │ ├── hex_test.v │ ├── input_rune_iterator.v │ ├── input_rune_iterator_test.v │ ├── int.v │ ├── int_notd_new_int.v │ ├── int_test.v │ ├── isnil_test.v │ ├── js/ │ │ ├── array.js.v │ │ ├── array_test.js.v │ │ ├── builtin.js.v │ │ ├── builtin.v │ │ ├── byte.js.v │ │ ├── float.js.v │ │ ├── int.js.v │ │ ├── int_test.js.v │ │ ├── jsfns.js.v │ │ ├── jsfns_browser.js.v │ │ ├── jsfns_node.js.v │ │ ├── map.js.v │ │ ├── map_test.js.v │ │ ├── promise.js.v │ │ ├── rune.js.v │ │ ├── string.js.v │ │ ├── string_test.js.v │ │ └── utf8.js.v │ ├── lambda_expr_array_test.v │ ├── linux_bare/ │ │ ├── libc_impl.v │ │ ├── linux_syscalls.v │ │ ├── memory_managment.v │ │ └── old/ │ │ ├── .checks/ │ │ │ ├── .gitignore │ │ │ ├── checks.v │ │ │ ├── consts/ │ │ │ │ └── consts.v │ │ │ ├── forkedtest/ │ │ │ │ └── forkedtest.v │ │ │ ├── linuxsys/ │ │ │ │ └── linuxsys.v │ │ │ ├── readme.md │ │ │ ├── sample_text1.txt │ │ │ ├── string/ │ │ │ │ └── string.v │ │ │ └── structs/ │ │ │ └── structs.v │ │ ├── array_bare.v │ │ ├── builtin_bare.v │ │ ├── linuxsys_bare.v │ │ ├── mm_bare.v │ │ ├── string_bare.v │ │ └── syscallwrapper_test.v │ ├── map.c.v │ ├── map.v │ ├── map_d_gcboehm_opt.v │ ├── map_notd_gcboehm_opt.v │ ├── map_of_floats_test.v │ ├── map_test.v │ ├── meta_assert.v │ ├── meta_attribute.v │ ├── meta_enum.v │ ├── meta_function.v │ ├── meta_struct.v │ ├── meta_variant.v │ ├── option.c.v │ ├── overflow/ │ │ └── overflow.v │ ├── panicing.c.v │ ├── prealloc.c.v │ ├── printing.c.v │ ├── reuse.v │ ├── reuse_test.v │ ├── rune.v │ ├── rune_map.v │ ├── rune_test.v │ ├── sorted_lambda_expr_test.v │ ├── sorted_map.v │ ├── sorting_test.v │ ├── string.v │ ├── string_charptr_byteptr_helpers.v │ ├── string_int_test.v │ ├── string_interpolation.v │ ├── string_iterator_test.v │ ├── string_match_glob_test.v │ ├── string_strip_margin_test.v │ ├── string_test.v │ ├── string_trim_indent_test.v │ ├── utf8.c.v │ ├── utf8.v │ ├── utf8_test.v │ ├── vgc_d_vgc.c.v │ ├── vgc_gc_d_vgc.c.v │ ├── vgc_notd_vgc.c.v │ ├── wasm/ │ │ ├── alloc.v │ │ ├── browser/ │ │ │ └── builtin_notd_no_imports.v │ │ ├── builtin.v │ │ ├── string.v │ │ └── wasi/ │ │ ├── builtin_notd_no_imports.v │ │ ├── int_notd_no_imports.v │ │ ├── string_notd_no_imports.v │ │ └── wasi_notd_no_imports.v │ ├── wasm_bare/ │ │ ├── libc_impl.c.v │ │ └── memory_management.v │ └── wchar/ │ ├── wchar.c.v │ └── wchar_test.v ├── cli/ │ ├── README.md │ ├── cli_test.v │ ├── command.v │ ├── command_test.v │ ├── flag.v │ ├── flag_test.v │ ├── help.v │ ├── help_test.v │ ├── man.v │ ├── man_test.v │ ├── testdata/ │ │ ├── default_command_flag.out │ │ ├── default_command_flag.vv │ │ ├── default_command_no_flag_err.out │ │ ├── default_command_no_flag_err.vv │ │ ├── default_help.out │ │ ├── default_help.vv │ │ ├── default_help_flag_no_command.out │ │ ├── default_help_flag_no_command.vv │ │ ├── default_version_flag_no_command.out │ │ ├── default_version_flag_no_command.vv │ │ ├── long_description.out │ │ ├── long_description.vv │ │ ├── no_execute.out │ │ └── no_execute.vv │ └── version.v ├── clipboard/ │ ├── README.md │ ├── clipboard.v │ ├── clipboard_android.c.v │ ├── clipboard_darwin.c.v │ ├── clipboard_darwin.m │ ├── clipboard_default.c.v │ ├── clipboard_solaris.c.v │ ├── clipboard_test.v │ ├── clipboard_windows.c.v │ ├── dummy/ │ │ └── dummy_clipboard.v │ └── x11/ │ └── clipboard.c.v ├── compress/ │ ├── README.md │ ├── compress.c.v │ ├── deflate/ │ │ ├── README.md │ │ ├── deflate.v │ │ └── deflate_test.v │ ├── gzip/ │ │ ├── README.md │ │ ├── gzip.v │ │ ├── gzip_test.v │ │ └── read_gz_files_test.v │ ├── szip/ │ │ ├── README.md │ │ ├── szip.c.v │ │ └── szip_test.v │ ├── zlib/ │ │ ├── README.md │ │ ├── zlib.v │ │ ├── zlib_miniz_compat_names_collision.h │ │ ├── zlib_miniz_compat_names_collision_test.c.v │ │ └── zlib_test.v │ └── zstd/ │ ├── README.md │ ├── read_zstd_files_test.v │ ├── samples/ │ │ ├── known.zst │ │ ├── readme_level_1.zst │ │ ├── readme_level_10.zst │ │ ├── readme_level_11.zst │ │ ├── readme_level_12.zst │ │ ├── readme_level_13.zst │ │ ├── readme_level_14.zst │ │ ├── readme_level_15.zst │ │ ├── readme_level_16.zst │ │ ├── readme_level_17.zst │ │ ├── readme_level_18.zst │ │ ├── readme_level_19.zst │ │ ├── readme_level_2.zst │ │ ├── readme_level_3.zst │ │ ├── readme_level_4.zst │ │ ├── readme_level_5.zst │ │ ├── readme_level_6.zst │ │ ├── readme_level_7.zst │ │ ├── readme_level_8.zst │ │ └── readme_level_9.zst │ ├── zstd.c.v │ ├── zstd_d_musl.c.v │ └── zstd_test.v ├── context/ │ ├── README.md │ ├── cancel.v │ ├── cancel_test.v │ ├── context.v │ ├── deadline.v │ ├── deadline_test.v │ ├── empty.v │ ├── empty_test.v │ ├── onecontext/ │ │ ├── README.md │ │ ├── onecontext.v │ │ └── onecontext_test.v │ ├── value.v │ └── value_test.v ├── coroutines/ │ ├── README.md │ ├── coroutines.c.v │ └── sp_corrector.c ├── crypto/ │ ├── README.md │ ├── aes/ │ │ ├── aes.v │ │ ├── aes_cbc.v │ │ ├── aes_test.v │ │ ├── block_generic.v │ │ ├── const.v │ │ └── cypher_generic.v │ ├── bcrypt/ │ │ ├── base64.v │ │ ├── bcrypt.v │ │ └── bcrypt_test.v │ ├── blake2b/ │ │ ├── blake2b.v │ │ ├── blake2b_block_generic.v │ │ ├── blake2b_block_test.v │ │ ├── blake2b_test.v │ │ └── testdata/ │ │ ├── README │ │ ├── blake2b.awk │ │ ├── blake2b_test_vectors.json │ │ └── test_vectors.v │ ├── blake2s/ │ │ ├── blake2s.v │ │ ├── blake2s_block_generic.v │ │ ├── blake2s_block_test.v │ │ ├── blake2s_test.v │ │ └── testdata/ │ │ ├── README │ │ ├── blake2s.awk │ │ ├── blake2s_test_vectors.json │ │ └── test_vectors.v │ ├── blake3/ │ │ ├── blake3.v │ │ ├── blake3_block_generic.v │ │ ├── blake3_block_test.v │ │ ├── blake3_chunk.v │ │ ├── blake3_chunk_test.v │ │ ├── blake3_test.v │ │ └── testdata/ │ │ ├── README │ │ └── test_vectors.json │ ├── blowfish/ │ │ ├── block.v │ │ ├── blowfish.v │ │ ├── blowfish_test.v │ │ └── const.v │ ├── cipher/ │ │ ├── aes_cbc_test.v │ │ ├── aes_cfb_test.v │ │ ├── aes_ctr_test.v │ │ ├── aes_ofb_test.v │ │ ├── cbc.v │ │ ├── cfb.v │ │ ├── cfb_test.v │ │ ├── cipher.v │ │ ├── ctr.v │ │ ├── ctr_test.v │ │ ├── des_cbc_test.v │ │ ├── des_cfb_test.v │ │ ├── des_ctr_test.v │ │ ├── des_ofb_test.v │ │ ├── ofb.v │ │ ├── ofb_test.v │ │ └── xor_generic.v │ ├── crypto.v │ ├── des/ │ │ ├── block.v │ │ ├── const.v │ │ ├── des.v │ │ └── des_test.v │ ├── ecdsa/ │ │ ├── README.md │ │ ├── ecdsa.c.v │ │ ├── ecdsa.v │ │ ├── ecdsa_test.v │ │ ├── example/ │ │ │ ├── ecdsa_seed_test.v │ │ │ ├── ensure_compatibility_with_net_openssl_test.v │ │ │ └── example1.v │ │ ├── util.v │ │ └── util_test.v │ ├── ed25519/ │ │ ├── LICENSE │ │ ├── README.md │ │ ├── ed25519.v │ │ ├── examples/ │ │ │ └── example.v │ │ └── internal/ │ │ ├── ed25519_test.v │ │ └── edwards25519/ │ │ ├── README.md │ │ ├── edwards25519.v │ │ ├── element.v │ │ ├── element_test.v │ │ ├── extra.v │ │ ├── extra_test.v │ │ ├── point.v │ │ ├── point_test.v │ │ ├── scalar.v │ │ ├── scalar_alias_test.v │ │ ├── scalar_test.v │ │ ├── scalarmult.v │ │ ├── scalarmult_test.v │ │ ├── table.v │ │ └── table_test.v │ ├── hmac/ │ │ ├── hmac.v │ │ └── hmac_test.v │ ├── internal/ │ │ └── subtle/ │ │ ├── aliasing.v │ │ ├── comparison.v │ │ └── comparison_test.v │ ├── md5/ │ │ ├── md5.v │ │ ├── md5_test.v │ │ └── md5block_generic.v │ ├── pbkdf2/ │ │ ├── pbkdf2.v │ │ └── pbkdf2_test.v │ ├── pem/ │ │ ├── decode.v │ │ ├── encode.v │ │ ├── pem.v │ │ └── pem_test.v │ ├── rand/ │ │ ├── crypto_rand_bytes_test.v │ │ ├── rand.v │ │ ├── rand_darwin.c.v │ │ ├── rand_default.c.v │ │ ├── rand_freebsd.c.v │ │ ├── rand_linux.c.v │ │ ├── rand_openbsd.c.v │ │ ├── rand_solaris.c.v │ │ ├── rand_windows.c.v │ │ ├── utils.v │ │ └── utils_test.v │ ├── rc4/ │ │ ├── rc4.v │ │ └── rc4_test.v │ ├── ripemd160/ │ │ ├── ripemd160.v │ │ ├── ripemd160_test.v │ │ └── ripemd160block.v │ ├── scrypt/ │ │ ├── scrypt.v │ │ └── scrypt_test.v │ ├── sha1/ │ │ ├── sha1.v │ │ ├── sha1_shavs_monte_test.v │ │ ├── sha1_shavs_test.v │ │ ├── sha1_test.v │ │ └── sha1block_generic.v │ ├── sha256/ │ │ ├── sha224_shavs_monte_test.v │ │ ├── sha224_shavs_test.v │ │ ├── sha256.v │ │ ├── sha256_shavs_monte_test.v │ │ ├── sha256_shavs_test.v │ │ ├── sha256_test.v │ │ └── sha256block_generic.v │ ├── sha3/ │ │ ├── sha3.v │ │ ├── sha3_state_generic.v │ │ ├── sha3_state_test.v │ │ ├── sha3_test.v │ │ ├── usage_test.v │ │ ├── xof.v │ │ └── xof_test.v │ └── sha512/ │ ├── sha384_shavs_monte_test.v │ ├── sha384_shavs_test.v │ ├── sha512.v │ ├── sha512_224_shavs_monte_test.v │ ├── sha512_224_shavs_test.v │ ├── sha512_256_shavs_monte_test.v │ ├── sha512_256_shavs_test.v │ ├── sha512_shavs_monte_test.v │ ├── sha512_shavs_test.v │ ├── sha512_test.v │ └── sha512block_generic.v ├── datatypes/ │ ├── README.md │ ├── bloom_filter.v │ ├── bloom_filter_test.v │ ├── bstree.v │ ├── bstree_test.v │ ├── doubly_linked_list.v │ ├── doubly_linked_list_test.v │ ├── fsm/ │ │ ├── README.md │ │ ├── fsm.v │ │ ├── fsm_test.v │ │ └── tools/ │ │ └── fsm_graph.v │ ├── heap.v │ ├── heap_test.v │ ├── linked_list.v │ ├── linked_list_test.v │ ├── lockfree/ │ │ ├── README.md │ │ ├── bench/ │ │ │ ├── bench_channel.v │ │ │ └── bench_ringbuffer.v │ │ ├── counter.v │ │ ├── counter_test.v │ │ ├── lockfree.v │ │ ├── ringbuffer.v │ │ └── ringbuffer_test.v │ ├── quadtree.v │ ├── quadtree_test.v │ ├── queue.v │ ├── queue_test.v │ ├── ringbuffer.v │ ├── ringbuffer_test.v │ ├── set.v │ ├── set_test.v │ ├── stack.v │ └── stack_test.v ├── db/ │ ├── README.md │ ├── mssql/ │ │ ├── README.md │ │ ├── _cdef_nix.c.v │ │ ├── _cdef_windows.c.v │ │ ├── _cdefs.c.v │ │ ├── config.v │ │ ├── mssql.c.v │ │ ├── result.v │ │ └── stmt_handle.c.v │ ├── mysql/ │ │ ├── README.md │ │ ├── _cdefs.c.v │ │ ├── _cdefs_nix.c.v │ │ ├── _cdefs_windows.c.v │ │ ├── consts.c.v │ │ ├── enums.v │ │ ├── mysql.c.v │ │ ├── mysql_orm_test.v │ │ ├── mysql_test.v │ │ ├── orm.c.v │ │ ├── pool.v │ │ ├── prepared_stmt_test.v │ │ ├── result.c.v │ │ ├── stmt.c.v │ │ └── utils.c.v │ ├── pg/ │ │ ├── README.md │ │ ├── compatibility.h │ │ ├── oid.v │ │ ├── orm.v │ │ ├── pg.c.v │ │ ├── pg_double_test.v │ │ ├── pg_orm_test.v │ │ ├── pg_result_test.v │ │ ├── pg_test.v │ │ └── pool.v │ ├── redis/ │ │ ├── README.md │ │ ├── redis.v │ │ └── redis_test.v │ └── sqlite/ │ ├── README.md │ ├── install_thirdparty_sqlite.vsh │ ├── orm.v │ ├── parent_child_test.v │ ├── pool.v │ ├── result_code.v │ ├── sqlite.c.v │ ├── sqlite_comptime_field_test.v │ ├── sqlite_f32_test.v │ ├── sqlite_orm_option_field_test.v │ ├── sqlite_orm_test.v │ ├── sqlite_test.v │ ├── sqlite_vfs_lowlevel_test.v │ ├── stmt.c.v │ └── vfs_lowlevel.c.v ├── dl/ │ ├── README.md │ ├── dl.v │ ├── dl_nix.c.v │ ├── dl_test.v │ ├── dl_windows.c.v │ ├── loader/ │ │ ├── README.md │ │ ├── loader.v │ │ └── loader_test.v │ └── rtld_next_test.v ├── dlmalloc/ │ ├── dlmalloc.v │ ├── dlmalloc_sys_nix.c.v │ ├── dlmalloc_sys_windows.c.v │ └── global.v ├── encoding/ │ ├── README.md │ ├── base32/ │ │ ├── base32.v │ │ └── base32_test.v │ ├── base58/ │ │ ├── alphabet.v │ │ ├── base58.v │ │ ├── base58_test.v │ │ └── base58_usage_test.v │ ├── base64/ │ │ ├── base64.c.v │ │ ├── base64.v │ │ ├── base64_memory_test.v │ │ └── base64_test.v │ ├── binary/ │ │ ├── README.md │ │ ├── big_endian.v │ │ ├── big_endian_fixed.v │ │ ├── big_endian_fixed_test.v │ │ ├── big_endian_test.v │ │ ├── little_endian.v │ │ ├── little_endian_fixed.v │ │ ├── little_endian_fixed_test.v │ │ ├── little_endian_test.v │ │ ├── serialize.v │ │ ├── serialize_test.v │ │ └── unions.v │ ├── csv/ │ │ ├── README.md │ │ ├── README_csv_reader.md │ │ ├── csv_reader_eol_test.v │ │ ├── csv_reader_random_access.v │ │ ├── csv_reader_sequential.v │ │ ├── csv_reader_test.v │ │ ├── reader.v │ │ ├── reader_test.v │ │ ├── to_struct_arr.v │ │ ├── utils.v │ │ ├── utils_test.v │ │ ├── writer.v │ │ └── writer_test.v │ ├── hex/ │ │ ├── hex.v │ │ └── hex_test.v │ ├── html/ │ │ ├── escape.v │ │ ├── escape_test.v │ │ └── named_references.v │ ├── iconv/ │ │ ├── iconv.v │ │ ├── iconv_nix.c.v │ │ ├── iconv_test.v │ │ └── iconv_windows.c.v │ ├── leb128/ │ │ ├── leb128.v │ │ └── leb128_test.v │ ├── txtar/ │ │ ├── README.md │ │ ├── pack_unpack.v │ │ ├── txtar.v │ │ └── txtar_test.v │ ├── utf8/ │ │ ├── east_asian/ │ │ │ ├── east_asian_width.v │ │ │ └── east_asian_width_test.v │ │ ├── utf8.v │ │ ├── utf8_is_punct_test.v │ │ ├── utf8_tables.v │ │ ├── utf8_util.v │ │ ├── utf8_util_test.v │ │ └── validate/ │ │ ├── encoding_utf8_test.v │ │ └── validate_utf8.v │ ├── vorbis/ │ │ ├── README.md │ │ ├── link_to_libm.c.v │ │ ├── version.v │ │ ├── vorbis.c.v │ │ ├── vorbis.v │ │ └── vorbis_test.v │ └── xml/ │ ├── README.md │ ├── encoding.v │ ├── encoding_test.v │ ├── entity.v │ ├── entity_test.v │ ├── newline_test.v │ ├── parser.v │ ├── parser_test.v │ ├── query.v │ ├── query_test.v │ ├── reader_util.v │ ├── test/ │ │ ├── gtk/ │ │ │ └── gtk_test.v │ │ ├── local/ │ │ │ ├── 01_mdn_example/ │ │ │ │ ├── hello_world.xml │ │ │ │ └── hello_world_test.v │ │ │ ├── 02_note_message/ │ │ │ │ ├── note.xml │ │ │ │ └── note_test.v │ │ │ ├── 03_cd_catalogue/ │ │ │ │ ├── cd_catalog.xml │ │ │ │ └── cd_test.v │ │ │ ├── 04_empty_file/ │ │ │ │ ├── empty.xml │ │ │ │ └── expected_error.txt │ │ │ ├── 05_single_element/ │ │ │ │ ├── root.xml │ │ │ │ └── root_test.v │ │ │ ├── 06_nested_elements/ │ │ │ │ ├── nested.xml │ │ │ │ └── nested_test.v │ │ │ ├── 07_mixed_contents/ │ │ │ │ ├── mixed.xml │ │ │ │ └── mixed_test.v │ │ │ ├── 08_comments/ │ │ │ │ ├── comment.xml │ │ │ │ └── comment_test.v │ │ │ ├── 09_malformed/ │ │ │ │ ├── expected_error.txt │ │ │ │ └── malformed.xml │ │ │ ├── 10_missing_tag/ │ │ │ │ ├── expected_error.txt │ │ │ │ └── malformed.xml │ │ │ ├── 11_cdata_content/ │ │ │ │ ├── cdata.xml │ │ │ │ └── cdata_test.v │ │ │ ├── 12_doctype_entity/ │ │ │ │ ├── entity.xml │ │ │ │ ├── entity_expected.xml │ │ │ │ └── spec_entity_test.v │ │ │ ├── 13_doctype_element/ │ │ │ │ ├── doctype_test.v │ │ │ │ └── element.xml │ │ │ ├── 14_attributes/ │ │ │ │ ├── attributes.xml │ │ │ │ └── attributes_test.v │ │ │ ├── 15_incomplete_entity_1/ │ │ │ │ ├── entity.xml │ │ │ │ └── expected_error.txt │ │ │ ├── 16_incomplete_entity_2/ │ │ │ │ ├── entity.xml │ │ │ │ └── expected_error.txt │ │ │ ├── 17_incomplete_element_1/ │ │ │ │ ├── element.xml │ │ │ │ └── expected_error.txt │ │ │ ├── 18_incomplete_element_2/ │ │ │ │ ├── element.xml │ │ │ │ └── expected_error.txt │ │ │ ├── 19_single_letter_tag/ │ │ │ │ ├── shared.xml │ │ │ │ └── shared_test.v │ │ │ └── 20_bom_file/ │ │ │ └── bom_test.v │ │ └── spec_test.v │ ├── types.v │ └── validation.v ├── eventbus/ │ ├── README.md │ ├── eventbus.v │ └── eventbus_test.v ├── fasthttp/ │ ├── README.md │ ├── fasthttp.v │ ├── fasthttp_darwin.v │ ├── fasthttp_linux.v │ ├── fasthttp_test.v │ ├── fasthttp_windows.v │ ├── request_parser.v │ └── request_parser_test.v ├── flag/ │ ├── README.md │ ├── cmd_exe_style_flags_test.v │ ├── default_flag_options_test.v │ ├── flag.v │ ├── flag_autofree_test.v │ ├── flag_from_test.v │ ├── flag_parse_test.v │ ├── flag_test.v │ ├── flag_to.v │ ├── flag_to_bool_test.v │ ├── flag_to_doc_test.v │ ├── flag_to_edge_case_1_test.v │ ├── flag_to_misc_test.v │ ├── flag_to_relaxed_test.v │ ├── flag_to_tail_bool_test.v │ ├── flag_to_tail_test.v │ ├── gnu_style_flags_test.v │ ├── go_flag_style_flags_test.v │ ├── posix_style_flags_test.v │ ├── testdata/ │ │ ├── simplest_flag_program.dashdash.help.out │ │ ├── simplest_flag_program.dashdash.version.out │ │ ├── simplest_flag_program.help.out │ │ ├── simplest_flag_program.out │ │ ├── simplest_flag_program.v │ │ ├── simplest_flag_program.version.out │ │ ├── usage_example.help.out │ │ ├── usage_example.out │ │ ├── usage_example.v │ │ └── usage_example.version.out │ ├── usage_example_test.v │ ├── v_flag_parser_style_flags_test.v │ └── v_style_flags_test.v ├── fontstash/ │ ├── README.md │ ├── a_d_use_freetype.v │ ├── fontstash.c.v │ ├── fontstash_enums.v │ ├── fontstash_funcs.c.v │ └── fontstash_structs.c.v ├── gg/ │ ├── README.md │ ├── bezier.c.v │ ├── color.v │ ├── color_test.v │ ├── draw.c.v │ ├── draw_fns_api_test.v │ ├── enums.v │ ├── gg.c.v │ ├── gg.js.v │ ├── gg.v │ ├── gg_android_outside_termux.c.v │ ├── gg_darwin.c.v │ ├── gg_darwin.m │ ├── gg_ui.c.v │ ├── image.c.v │ ├── image.js.v │ ├── image.v │ ├── image_test.v │ ├── keyboard.v │ ├── m4/ │ │ ├── graphic.v │ │ ├── m4_test.v │ │ ├── matrix.v │ │ └── vector.v │ ├── recorder.c.v │ ├── recorder.js.v │ ├── recorder.v │ ├── testdata/ │ │ ├── draw_arcs.vv │ │ ├── draw_circles.vv │ │ ├── draw_elipses.vv │ │ ├── draw_polygons.vv │ │ ├── draw_rectangles.vv │ │ ├── draw_rounded_rect_empty.vv │ │ ├── draw_rounded_rect_filled.vv │ │ ├── draw_simple_polygons.vv │ │ ├── draw_text.vv │ │ ├── remove_image_from_cache.vv │ │ └── tweak_circles.vv │ ├── text_rendering.c.v │ ├── text_rendering.js.v │ └── text_rendering.v ├── goroutines/ │ ├── README.md │ ├── atomic_ops.c.v │ ├── chan.v │ ├── context_nix.c.v │ ├── context_nix.h │ ├── context_windows.c.v │ ├── examples/ │ │ ├── basic_goroutine.v │ │ ├── goroutine_benchmark.go │ │ ├── goroutine_benchmark.v │ │ └── spawn_benchmark.v │ ├── goroutines.v │ ├── goroutines_test.v │ ├── goroutines_tls.h │ ├── init.v │ ├── park.v │ ├── scheduler.v │ └── tls.c ├── gx/ │ ├── README.md │ ├── color.v │ ├── image.v │ ├── text.c.v │ ├── text.js.v │ └── text.v ├── hash/ │ ├── README.md │ ├── crc32/ │ │ ├── crc32.v │ │ └── crc32_test.v │ ├── fnv1a/ │ │ ├── fnv1a.v │ │ └── fnv1a_test.v │ ├── hash.v │ ├── hash_compiles_test.v │ ├── wyhash.c.v │ ├── wyhash.js.v │ └── wyhash.v ├── io/ │ ├── README.md │ ├── buffered_reader.v │ ├── buffered_writer.v │ ├── buffered_writer_test.v │ ├── custom_string_reading_test.v │ ├── io.v │ ├── io_cp_test.v │ ├── io_test.v │ ├── multi_writer.v │ ├── multi_writer_test.v │ ├── os_file_reader_test.v │ ├── reader.v │ ├── reader_test.v │ ├── readerwriter.v │ ├── string_reader/ │ │ ├── string_reader.v │ │ └── string_reader_test.v │ ├── util/ │ │ ├── util.v │ │ └── util_test.v │ └── writer.v ├── js/ │ ├── README.md │ ├── dom/ │ │ ├── dom.js.v │ │ └── dom.v │ ├── js.js.v │ └── js.v ├── json/ │ ├── README.md │ ├── cjson/ │ │ ├── cjson_test.v │ │ └── cjson_wrapper.c.v │ ├── json_primitives.c.v │ └── tests/ │ ├── json_alias_test.v │ ├── json_decode_anon_struct_test.v │ ├── json_decode_arr_ref_test.v │ ├── json_decode_embed_test.v │ ├── json_decode_option_alias_field_test.v │ ├── json_decode_option_alias_test.v │ ├── json_decode_option_enum_test.v │ ├── json_decode_struct_default_test.v │ ├── json_decode_struct_ptr_test.v │ ├── json_decode_struct_with_default_test.v │ ├── json_decode_sumtype_option_test.v │ ├── json_decode_test.v │ ├── json_decode_with_encode_arg_test.v │ ├── json_decode_with_generic_array_test.v │ ├── json_decode_with_generic_test.v │ ├── json_decode_with_option_arg_test.v │ ├── json_decode_with_sumtype_test.v │ ├── json_embed_test.v │ ├── json_encode_default_option_none_test.v │ ├── json_encode_embed_test.v │ ├── json_encode_enum_test.v │ ├── json_encode_map_test.v │ ├── json_encode_primite_test.v │ ├── json_encode_ptr_test.v │ ├── json_encode_recursive_ptr_test.v │ ├── json_encode_struct_with_option_field_test.v │ ├── json_encode_sumtype_test.v │ ├── json_encode_with_mut_test.v │ ├── json_encode_with_ptr_test.v │ ├── json_fixed_array_test.v │ ├── json_generic_array_test.v │ ├── json_i32_test.v │ ├── json_is_null_attr_test.v │ ├── json_mut_map_test.v │ ├── json_omitempty_test.v │ ├── json_omitempty_types_test.v │ ├── json_option_alias_test.v │ ├── json_option_none_test.v │ ├── json_option_raw_test.v │ ├── json_option_struct_test.v │ ├── json_option_test.v │ ├── json_prim_type_validation_test.v │ ├── json_raw_test.v │ ├── json_struct_option_test.v │ ├── json_sumtype_test.v │ └── json_test.v ├── log/ │ ├── README.md │ ├── common.v │ ├── default.c.v │ ├── default.v │ ├── default_test.v │ ├── file_log_test.v │ ├── log.v │ ├── log_test.v │ ├── logger_interface.v │ └── safe_log.v ├── macos/ │ ├── macos_darwin.c.v │ └── objc_bridge.h ├── maps/ │ ├── README.md │ ├── maps.v │ ├── maps_clone_test.v │ └── maps_test.v ├── math/ │ ├── README.md │ ├── ROADMAP.md │ ├── abs.js.v │ ├── big/ │ │ ├── array_ops.v │ │ ├── array_ops_test.v │ │ ├── bench/ │ │ │ └── bench_big_dividing_big_numbers_big_pow.v │ │ ├── big.js.v │ │ ├── big.v │ │ ├── big_division_test.v │ │ ├── big_test.v │ │ ├── consts_test.v │ │ ├── division_array_ops.v │ │ ├── division_array_ops_test.v │ │ ├── exponentiation.v │ │ ├── integer.v │ │ ├── json_custom.v │ │ ├── large_number_power_and_string_conversion_test.v │ │ ├── min_max.v │ │ ├── special_array_ops.v │ │ └── special_array_ops_test.v │ ├── bits/ │ │ ├── bits.amd64.v │ │ ├── bits.arm64.v │ │ ├── bits.c.v │ │ ├── bits.v │ │ ├── bits_tables.v │ │ ├── bits_test.v │ │ ├── unsafe_bits.js.v │ │ └── unsafe_bits.v │ ├── bits.js.v │ ├── bits.v │ ├── cbrt.js.v │ ├── cbrt.v │ ├── complex/ │ │ ├── complex.v │ │ └── complex_test.v │ ├── const.v │ ├── div.v │ ├── easing/ │ │ ├── easing.v │ │ └── easing_test.v │ ├── erf.v │ ├── erf_test.v │ ├── exp.c.v │ ├── exp.js.v │ ├── exp.v │ ├── factorial.v │ ├── factorial_tables.v │ ├── factorial_test.v │ ├── floor.js.v │ ├── floor.v │ ├── floor_test.v │ ├── fractions/ │ │ ├── approximations.v │ │ ├── approximations_test.v │ │ ├── fraction.v │ │ └── fraction_test.v │ ├── gamma.v │ ├── gamma_tables.v │ ├── hypot.v │ ├── internal/ │ │ └── machine.v │ ├── interpolation.v │ ├── interpolation_bezier.v │ ├── interpolation_test.v │ ├── invhyp.v │ ├── invhyp_test.v │ ├── invtrig.js.v │ ├── invtrig.v │ ├── limit.v │ ├── log.c.v │ ├── log.v │ ├── log_test.v │ ├── math.c.v │ ├── math.v │ ├── math_bench_test.v │ ├── math_test.v │ ├── min_max_abs.v │ ├── min_max_abs_test.v │ ├── modf.v │ ├── modulo.v │ ├── modulo_test.v │ ├── nextafter.v │ ├── poly.v │ ├── pow.c.v │ ├── pow.v │ ├── q_rsqrt.v │ ├── scalbn.v │ ├── sin.c.v │ ├── sin.js.v │ ├── sin.v │ ├── sinh.js.v │ ├── sinh.v │ ├── sqrt.c.v │ ├── sqrt.v │ ├── square.v │ ├── square_test.v │ ├── stats/ │ │ ├── stats.v │ │ └── stats_test.v │ ├── tan.c.v │ ├── tan.js.v │ ├── tan.v │ ├── tanh.js.v │ ├── tanh.v │ ├── unsafe.js.v │ ├── unsafe.v │ ├── unsigned/ │ │ ├── uint128.v │ │ ├── uint128_test.v │ │ ├── uint256.v │ │ └── uint256_test.v │ └── vec/ │ ├── vec2.v │ ├── vec2_test.v │ ├── vec3.v │ ├── vec3_test.v │ ├── vec4.v │ └── vec4_test.v ├── net/ │ ├── README.md │ ├── aasocket.c.v │ ├── address.c.v │ ├── address_android.c.v │ ├── address_darwin.c.v │ ├── address_default.c.v │ ├── address_dragonfly.c.v │ ├── address_freebsd.c.v │ ├── address_linux.c.v │ ├── address_netbsd.c.v │ ├── address_openbsd.c.v │ ├── address_test.c.v │ ├── address_windows.c.v │ ├── afunix.h │ ├── common.c.v │ ├── connection.v │ ├── conv/ │ │ ├── README.md │ │ ├── conv.v │ │ └── conv_test.v │ ├── dial_tcp_with_bind_test.v │ ├── dialer.v │ ├── errors.c.v │ ├── ftp/ │ │ ├── ftp.v │ │ └── ftp_test.v │ ├── html/ │ │ ├── README.md │ │ ├── data_structures.v │ │ ├── dom.v │ │ ├── dom_test.v │ │ ├── html.v │ │ ├── html_test.v │ │ ├── parser.v │ │ ├── parser_test.v │ │ ├── tag.v │ │ └── tag_test.v │ ├── http/ │ │ ├── backend.c.v │ │ ├── backend_vschannel_windows.c.v │ │ ├── build_request_headers_test.v │ │ ├── chunked/ │ │ │ ├── dechunk.v │ │ │ └── dechunk_test.v │ │ ├── cookie.v │ │ ├── cookie_test.v │ │ ├── download.v │ │ ├── download_nix.c.v │ │ ├── download_progress.v │ │ ├── download_silent_downloader.v │ │ ├── download_terminal_downloader.v │ │ ├── download_windows.c.v │ │ ├── file/ │ │ │ ├── entity.v │ │ │ ├── folder_index.v │ │ │ └── static_server.v │ │ ├── header.v │ │ ├── header_test.v │ │ ├── http.v │ │ ├── http_httpbin_test.v │ │ ├── http_proxy.v │ │ ├── http_proxy_test.v │ │ ├── http_test.v │ │ ├── method.v │ │ ├── mime/ │ │ │ ├── build.vsh │ │ │ ├── db.v │ │ │ ├── mime.v │ │ │ └── mime_test.v │ │ ├── request.v │ │ ├── request_receive_test.v │ │ ├── request_test.v │ │ ├── response.v │ │ ├── response_test.v │ │ ├── server.v │ │ ├── server_test.v │ │ ├── status.v │ │ ├── status_test.v │ │ ├── util.v │ │ └── version.v │ ├── ipv6_v6only.h │ ├── jsonrpc/ │ │ ├── README.md │ │ ├── client.v │ │ ├── interceptors.v │ │ ├── jsonrpc.v │ │ ├── jsonrpc_test.v │ │ ├── logging.v │ │ ├── server.v │ │ └── server_test.v │ ├── mbedtls/ │ │ ├── mbedtls.c.v │ │ ├── mbedtls_compiles_test.v │ │ ├── mbedtls_sslconn_shutdown_does_not_panic_test.v │ │ └── ssl_connection.c.v │ ├── net_nix.c.v │ ├── net_windows.c.v │ ├── openssl/ │ │ ├── openssl.c.v │ │ ├── openssl_compiles_test.c.v │ │ ├── openssl_import_tcp_accept_test.c.v │ │ ├── openssl_openbsd.c.v │ │ └── ssl_connection.c.v │ ├── raw.c.v │ ├── raw_test.v │ ├── smtp/ │ │ ├── smtp.v │ │ └── smtp_test.v │ ├── socket.c.v │ ├── socket_options.c.v │ ├── socks/ │ │ ├── socks5.v │ │ └── socks5_test.v │ ├── ssl/ │ │ ├── dialer.v │ │ ├── ssl_compiles_test.v │ │ ├── ssl_d_use_openssl.v │ │ └── ssl_notd_use_openssl.v │ ├── tcp.c.v │ ├── tcp_non_blocking_test.v │ ├── tcp_read_line.c.v │ ├── tcp_self_dial_from_many_clients_test.v │ ├── tcp_simple_client_server_test.v │ ├── tcp_test.v │ ├── udp.c.v │ ├── udp_test.v │ ├── unix/ │ │ ├── aasocket.c.v │ │ ├── common.c.v │ │ ├── stream.c.v │ │ ├── unix_socket_test.v │ │ └── use_net_and_net_unix_together_test.v │ ├── urllib/ │ │ ├── urllib.v │ │ ├── urllib_test.v │ │ ├── values.v │ │ └── values_test.v │ ├── util.v │ ├── utils_test.v │ └── websocket/ │ ├── events.v │ ├── handshake.v │ ├── io.v │ ├── message.v │ ├── tests/ │ │ └── autobahn/ │ │ ├── README.md │ │ ├── autobahn_client.v │ │ ├── autobahn_client_wss.v │ │ ├── autobahn_server.v │ │ ├── docker-compose.yml │ │ ├── fuzzing_server/ │ │ │ ├── Dockerfile │ │ │ ├── check_results.py │ │ │ └── config/ │ │ │ ├── fuzzingclient.json │ │ │ └── fuzzingserver.json │ │ ├── fuzzing_server_wss/ │ │ │ ├── Dockerfile │ │ │ ├── check_results.py │ │ │ └── config/ │ │ │ ├── fuzzingserver.json │ │ │ ├── server.crt │ │ │ ├── server.csr │ │ │ ├── server.key │ │ │ └── server.pem │ │ ├── local_run/ │ │ │ ├── Dockerfile │ │ │ ├── autobahn_client.v │ │ │ └── autobahn_client_wss.v │ │ └── ws_test/ │ │ └── Dockerfile │ ├── uri.v │ ├── utils.v │ ├── websocket_client.v │ ├── websocket_nix.c.v │ ├── websocket_server.v │ ├── websocket_test.v │ └── websocket_windows.c.v ├── orm/ │ ├── README.md │ ├── orm.v │ ├── orm_aggregate_test.v │ ├── orm_complex_where_test.v │ ├── orm_create_and_drop_test.v │ ├── orm_custom_operators_test.v │ ├── orm_embed_test.v │ ├── orm_fk_test.v │ ├── orm_fn_calls_test.v │ ├── orm_fn_test.v │ ├── orm_func.v │ ├── orm_func_test.v │ ├── orm_generic_struct_field_test.v │ ├── orm_generic_test.v │ ├── orm_generic_where_shadow_test.v │ ├── orm_insert_reserved_name_test.v │ ├── orm_insert_test.v │ ├── orm_interface_test.v │ ├── orm_join_test.v │ ├── orm_last_id_test.v │ ├── orm_mut_connection_test.v │ ├── orm_mut_db_test.v │ ├── orm_nested_struct_test.v │ ├── orm_null_test.v │ ├── orm_option_array_test.v │ ├── orm_option_subselect_test.v │ ├── orm_option_time_test.v │ ├── orm_order_by_custom_field_test.v │ ├── orm_references_test.v │ ├── orm_result_test.v │ ├── orm_serial_attribute_test.v │ ├── orm_sql_or_blocks_test.v │ ├── orm_string_interpolation_in_where_test.v │ ├── orm_sum_type_insert_test.v │ ├── orm_test.v │ ├── orm_transaction_test.v │ ├── orm_where_in_test.v │ └── transaction.v ├── os/ │ ├── README.md │ ├── args.v │ ├── asset/ │ │ ├── README.md │ │ └── asset.v │ ├── bare/ │ │ └── bare_example_linux.v │ ├── cmdline/ │ │ ├── cmdline.v │ │ └── cmdline_test.v │ ├── command.c.v │ ├── command_test.v │ ├── const.v │ ├── const_nix.c.v │ ├── const_windows.c.v │ ├── debugger_darwin.c.v │ ├── debugger_default.c.v │ ├── debugger_freebsd.c.v │ ├── debugger_linux.c.v │ ├── debugger_openbsd.c.v │ ├── debugger_windows.c.v │ ├── dir_expansions_test.v │ ├── environment.c.v │ ├── environment.js.v │ ├── environment_test.v │ ├── fd.c.v │ ├── file.c.v │ ├── file.js.v │ ├── file_buffering.c.v │ ├── file_buffering_test.v │ ├── file_le_be.c.v │ ├── file_le_be_test.v │ ├── file_test.v │ ├── filelock/ │ │ ├── filelock_test.v │ │ ├── lib.v │ │ ├── lib_nix.c.v │ │ └── lib_windows.c.v │ ├── filepath.v │ ├── filepath_test.v │ ├── filepath_windows.v │ ├── find_abs_path_of_executable_test.v │ ├── font/ │ │ └── font.v │ ├── glob_test.v │ ├── inode.c.v │ ├── inode_test.v │ ├── join_path_test.v │ ├── notify/ │ │ ├── backend_darwin.c.v │ │ ├── backend_default.c.v │ │ ├── backend_linux.c.v │ │ ├── kqueue.h │ │ ├── notify.v │ │ └── notify_test.c.v │ ├── open_and_read_from_file_test.js.v │ ├── open_uri_default.c.v │ ├── open_uri_windows.c.v │ ├── os.c.v │ ├── os.js.v │ ├── os.v │ ├── os_android_outside_termux.c.v │ ├── os_args_autofree_test.v │ ├── os_darwin.c.v │ ├── os_js.js.v │ ├── os_linux.c.v │ ├── os_nix.c.v │ ├── os_stat_default.c.v │ ├── os_stat_test.v │ ├── os_stat_windows.c.v │ ├── os_structs_dirent_default.c.v │ ├── os_structs_sigaction_default.c.v │ ├── os_structs_stat_default.c.v │ ├── os_structs_stat_linux.c.v │ ├── os_structs_stat_windows.c.v │ ├── os_structs_utsname_default.c.v │ ├── os_test.c.v │ ├── os_windows.c.v │ ├── password_nix.c.v │ ├── password_windows.c.v │ ├── pipe.c.v │ ├── pipe_test.c.v │ ├── process.c.v │ ├── process.js.v │ ├── process.v │ ├── process_args_test.v │ ├── process_nix.c.v │ ├── process_test.v │ ├── process_windows.c.v │ ├── signal.c.v │ ├── signal.js.v │ ├── signal.v │ ├── signal_darwin.c.v │ ├── signal_default.c.v │ ├── signal_linux.c.v │ ├── signal_test.v │ ├── signal_windows.c.v │ ├── sleeping.c.v │ ├── sleeping.js.v │ ├── util/ │ │ └── util.v │ └── xdg_test.v ├── picoev/ │ ├── README.md │ ├── constants_default.c.v │ ├── constants_windows.c.v │ ├── logging.v │ ├── loop_default.c.v │ ├── loop_freebsd.c.v │ ├── loop_linux.c.v │ ├── loop_macos.c.v │ ├── loop_openbsd.c.v │ ├── loop_termux.c.v │ ├── picoev.v │ ├── picoev_test.v │ └── socket_util.c.v ├── picohttpparser/ │ ├── README.md │ ├── misc.v │ ├── misc_test.v │ ├── picohttpparser.v │ ├── request.v │ ├── request_test.v │ └── response.c.v ├── pool/ │ ├── README.md │ ├── connection.v │ └── connection_test.v ├── rand/ │ ├── README.md │ ├── buffer/ │ │ └── buffer.v │ ├── config/ │ │ └── config.v │ ├── cuid2/ │ │ ├── cuid2.v │ │ └── cuid2_test.v │ ├── dist_test.v │ ├── fp_test.v │ ├── mini_math.v │ ├── mt19937/ │ │ ├── mt19937.v │ │ └── mt19937_test.v │ ├── musl/ │ │ ├── musl_rng.v │ │ └── musl_rng_test.v │ ├── pcg32/ │ │ ├── pcg32.v │ │ └── pcg32_test.v │ ├── rand.c.v │ ├── rand.js.v │ ├── rand.v │ ├── rand_test.js.v │ ├── random_bytes_test.v │ ├── random_identifiers_test.v │ ├── random_numbers_test.v │ ├── seed/ │ │ └── seed.v │ ├── splitmix64/ │ │ ├── splitmix64.v │ │ └── splitmix64_test.v │ ├── sys/ │ │ ├── system_rng.c.v │ │ ├── system_rng.js.v │ │ └── system_rng_test.v │ ├── wyrand/ │ │ ├── wyrand.js.v │ │ ├── wyrand.v │ │ ├── wyrand_test.v │ │ └── z_wyrand.c.v │ └── xoroshiro128pp/ │ ├── xoros128pp.v │ └── xoros128pp_test.v ├── readline/ │ ├── README.md │ ├── readline.v │ ├── readline_default.c.v │ ├── readline_js.js.v │ ├── readline_nix.c.v │ ├── readline_test.v │ └── readline_windows.c.v ├── regex/ │ ├── README.md │ ├── pcre/ │ │ ├── README.md │ │ ├── regex.v │ │ └── regex_test.v │ ├── regex.v │ ├── regex_anchor_test.v │ ├── regex_complex_test.v │ ├── regex_opt.v │ ├── regex_test.v │ └── regex_util.v ├── runtime/ │ ├── README.md │ ├── free_memory_impl_darwin.c.v │ ├── free_memory_impl_default.c.v │ ├── free_memory_impl_freebsd.c.v │ ├── free_memory_impl_linux.c.v │ ├── free_memory_impl_openbsd.c.v │ ├── runtime.v │ ├── runtime_nix.c.v │ ├── runtime_test.v │ ├── runtime_windows.c.v │ ├── used_memory_darwin.c.v │ ├── used_memory_default.c.v │ ├── used_memory_freebsd.c.v │ ├── used_memory_linux.c.v │ ├── used_memory_openbsd.c.v │ ├── used_memory_test.v │ └── used_memory_windows.c.v ├── semver/ │ ├── LICENSE.md │ ├── README.md │ ├── compare.v │ ├── parse.v │ ├── range.v │ ├── semver.v │ ├── semver_test.v │ └── util.v ├── sokol/ │ ├── README.md │ ├── audio/ │ │ └── audio.c.v │ ├── c/ │ │ └── declaration.c.v │ ├── gfx/ │ │ ├── enums.v │ │ ├── gfx.c.v │ │ ├── gfx_allocator_and_logger.c.v │ │ ├── gfx_funcs.c.v │ │ ├── gfx_structs.c.v │ │ └── gfx_utils.c.v │ ├── memory/ │ │ └── memory.c.v │ ├── sapp/ │ │ ├── enums.v │ │ ├── sapp.v │ │ ├── sapp_egl_linux.v │ │ ├── sapp_funcs.c.v │ │ ├── sapp_linux.c.v │ │ ├── sapp_state.v │ │ ├── sapp_state_linux.v │ │ ├── sapp_structs.c.v │ │ ├── sapp_v.v │ │ ├── sapp_wayland_linux.v │ │ ├── sapp_x11_linux.v │ │ └── screenshot.v │ ├── sfons/ │ │ └── sfons.v │ ├── sgl/ │ │ ├── enums.v │ │ ├── matrix.v │ │ ├── sgl.v │ │ ├── sgl_structs.v │ │ └── shaders.v │ └── sokol.v ├── stbi/ │ ├── README.md │ ├── link_to_libm.c.v │ ├── stbi.c.v │ └── stbi_test.v ├── strconv/ │ ├── README.md │ ├── atof.c.v │ ├── atof.js.v │ ├── atof_test.c.v │ ├── atofq.c.v │ ├── atoi.v │ ├── atoi_test.v │ ├── atou.v │ ├── atou_test.v │ ├── bare/ │ │ └── str_array_example.v │ ├── converter_test.v │ ├── f32_f64_to_string_test.v │ ├── f32_str.c.v │ ├── f32_str.js.v │ ├── f32_str_should_be_different_test.v │ ├── f32_ten_pow_table_range_test.v │ ├── f64_str.c.v │ ├── f64_str.js.v │ ├── f64_str.v │ ├── format.md │ ├── format.v │ ├── format_mem.c.v │ ├── format_mem.js.v │ ├── format_test.v │ ├── ftoa.c.v │ ├── number_to_base.c.v │ ├── number_to_base_test.v │ ├── structs.v │ ├── tables.v │ ├── utilities.c.v │ ├── utilities.v │ └── vprintf.c.v ├── strings/ │ ├── README.md │ ├── builder.c.v │ ├── builder.js.v │ ├── builder_test.js.v │ ├── builder_test.v │ ├── lorem/ │ │ ├── lorem.v │ │ └── lorem_test.v │ ├── similarity.v │ ├── similarity_test.js.v │ ├── similarity_test.v │ ├── strings.c.v │ ├── strings.js.v │ ├── strings.v │ ├── strings_test.js.v │ ├── strings_test.v │ └── textscanner/ │ ├── textscanner.v │ ├── textscanner_test.js.v │ └── textscanner_test.v ├── sync/ │ ├── README.md │ ├── array_rlock_test.v │ ├── bench/ │ │ ├── channel_bench_go.go │ │ ├── channel_bench_v.v │ │ ├── many_writers_and_receivers_on_1_channel.v │ │ ├── results.md │ │ └── run_bench.v │ ├── chan_mod_sync_test.v │ ├── channel_1_test.v │ ├── channel_2_test.v │ ├── channel_3_test.v │ ├── channel_4_test.v │ ├── channel_array_mut_test.v │ ├── channel_close_test.v │ ├── channel_fill_test.v │ ├── channel_opt_propagate_test.v │ ├── channel_polling_test.v │ ├── channel_push_or_1_test.v │ ├── channel_push_or_2_test.v │ ├── channel_select_2_test.v │ ├── channel_select_3_test.v │ ├── channel_select_4_test.v │ ├── channel_select_5_test.v │ ├── channel_select_6_test.v │ ├── channel_select_test.v │ ├── channel_try_buf_test.v │ ├── channel_try_unbuf_test.v │ ├── channels.c.v │ ├── channels.js.v │ ├── common_mutex.v │ ├── cond.v │ ├── cond_test.v │ ├── empty_struct_chan_init_test.v │ ├── many_times.v │ ├── many_times_test.v │ ├── mutex_test.v │ ├── once.v │ ├── once_test.v │ ├── once_with_param_test.v │ ├── pool/ │ │ ├── README.md │ │ ├── pool.c.v │ │ └── pool_test.v │ ├── rwmutex_test.v │ ├── select_close_test.v │ ├── spinlock_test.v │ ├── stdatomic/ │ │ ├── 1.declarations.c.v │ │ ├── atomic.c.v │ │ └── atomic_test.v │ ├── struct_chan_init_test.v │ ├── sync.c.v │ ├── sync_darwin.c.v │ ├── sync_default.c.v │ ├── sync_freebsd.c.v │ ├── sync_windows.c.v │ ├── thread_default.c.v │ ├── thread_test.v │ ├── thread_windows.c.v │ ├── threads/ │ │ ├── threads.c.v │ │ └── threads.v │ ├── tls.v │ ├── tls_default.c.v │ ├── tls_test.v │ ├── tls_windows.c.v │ ├── waitgroup.c.v │ └── waitgroup_test.v ├── term/ │ ├── README.md │ ├── colors.v │ ├── control.v │ ├── declarations_default.c.v │ ├── declarations_linux.c.v │ ├── term.js.v │ ├── term.v │ ├── term_nix.c.v │ ├── term_test.v │ ├── term_windows.c.v │ ├── termios/ │ │ ├── termios_android.c.v │ │ ├── termios_darwin.c.v │ │ ├── termios_default.c.v │ │ ├── termios_dragonfly.c.v │ │ ├── termios_freebsd.c.v │ │ ├── termios_linux.c.v │ │ ├── termios_netbsd.c.v │ │ ├── termios_openbsd.c.v │ │ ├── termios_qnx.c.v │ │ ├── termios_solaris.c.v │ │ ├── termios_test.c.v │ │ └── termios_windows.c.v │ ├── ui/ │ │ ├── 1_term_and_ui_compilation_test.v │ │ ├── 2_term_and_ui_compilation_test.v │ │ ├── README.md │ │ ├── color.v │ │ ├── consoleapi_windows.c.v │ │ ├── input.v │ │ ├── input_nix.c.v │ │ ├── input_windows.c.v │ │ ├── termios_nix.c.v │ │ ├── termios_nix_test.v │ │ ├── ui.c.v │ │ └── ui_test.v │ └── utf8.v ├── time/ │ ├── README.md │ ├── Y2K38_test.v │ ├── bare/ │ │ └── time_now_example.v │ ├── chrono.c.v │ ├── chrono.v │ ├── chrono_test.v │ ├── custom_format_test.v │ ├── date_time_parser.v │ ├── duration.v │ ├── duration_test.v │ ├── format.v │ ├── json_custom.c.v │ ├── misc/ │ │ ├── misc.v │ │ └── misc_test.v │ ├── operator.v │ ├── operator_test.v │ ├── parse.c.v │ ├── parse.js.v │ ├── parse.v │ ├── parse_autofree_test.v │ ├── parse_test.v │ ├── relative_test.v │ ├── stopwatch.v │ ├── stopwatch_test.v │ ├── time.c.v │ ├── time.js.v │ ├── time.v │ ├── time_addition_test.v │ ├── time_darwin.c.v │ ├── time_format_test.v │ ├── time_js.js.v │ ├── time_linux.c.v │ ├── time_nix.c.v │ ├── time_solaris.c.v │ ├── time_test.c.v │ ├── time_test.v │ ├── time_windows.c.v │ ├── unix.v │ ├── unix_test.v │ └── utc_vs_local_time_test.v ├── toml/ │ ├── README.md │ ├── any.v │ ├── ast/ │ │ ├── ast.v │ │ ├── types.v │ │ └── walker/ │ │ └── walker.v │ ├── checker/ │ │ └── checker.v │ ├── decoder/ │ │ └── decoder.v │ ├── input/ │ │ └── input.v │ ├── parser/ │ │ └── parser.v │ ├── scanner/ │ │ ├── scanner.v │ │ └── scanner_test.v │ ├── tests/ │ │ ├── array_of_tables_1_level_test.v │ │ ├── array_of_tables_2_level_test.v │ │ ├── array_of_tables_array_test.v │ │ ├── array_of_tables_edge_case_1_test.v │ │ ├── array_of_tables_edge_case_2_test.v │ │ ├── compact_test.v │ │ ├── crlf_test.v │ │ ├── datetime_test.v │ │ ├── default_to_test.v │ │ ├── default_value_test.v │ │ ├── encode_and_decode_test.v │ │ ├── iarna_toml_spec_test.v │ │ ├── inline_test.v │ │ ├── json_encoding_test.v │ │ ├── json_test.v │ │ ├── key_test.v │ │ ├── large_toml_file_test.v │ │ ├── nested_test.v │ │ ├── quoted_keys_test.v │ │ ├── quoted_string_crlf_test.v │ │ ├── reflect_test.v │ │ ├── spaced_keys_test.v │ │ ├── strings_test.v │ │ ├── table_test.v │ │ ├── testdata/ │ │ │ ├── .gitignore │ │ │ ├── array_of_tables_1_level_test.out │ │ │ ├── array_of_tables_2_level_test.out │ │ │ ├── array_of_tables_array_test.out │ │ │ ├── array_of_tables_edge_case_1_test.out │ │ │ ├── array_of_tables_edge_case_1_test.toml │ │ │ ├── array_of_tables_edge_case_2_test.out │ │ │ ├── array_of_tables_edge_case_2_test.toml │ │ │ ├── json_encoding_test.out │ │ │ ├── json_encoding_test.toml │ │ │ ├── json_test.out │ │ │ ├── json_test.toml │ │ │ ├── key_test.out │ │ │ ├── key_test.toml │ │ │ ├── strings_test.toml │ │ │ ├── toml_test.out │ │ │ ├── toml_test.toml │ │ │ ├── toml_with_utf16_bom.toml │ │ │ ├── toml_with_utf32_bom.toml │ │ │ └── toml_with_utf8_bom.toml │ │ ├── toml_attrs_test.v │ │ ├── toml_bom_test.v │ │ ├── toml_lang_test.v │ │ ├── toml_memory_corruption_test.v │ │ ├── toml_rs_test.v │ │ ├── toml_test.v │ │ ├── toml_types_test.v │ │ └── value_query_test.v │ ├── to/ │ │ └── to.v │ ├── token/ │ │ ├── pos.v │ │ └── token.v │ ├── toml.v │ └── util/ │ └── util.v ├── v/ │ ├── README.md │ ├── TEMPLATES.md │ ├── ast/ │ │ ├── ast.v │ │ ├── attr.v │ │ ├── cflags.v │ │ ├── cflags_test.v │ │ ├── comptime_const_values.v │ │ ├── comptime_valid_idents.v │ │ ├── embed_file.v │ │ ├── init.v │ │ ├── native.v │ │ ├── scope.v │ │ ├── str.v │ │ ├── table.v │ │ ├── table_test.v │ │ ├── type_size_test.v │ │ ├── types.v │ │ ├── types_test.v │ │ └── walker/ │ │ ├── walker.v │ │ └── walker_test.v │ ├── build_constraint/ │ │ ├── ast.v │ │ ├── constraint_test.v │ │ ├── evaluating.v │ │ ├── lexing.v │ │ ├── parsing.v │ │ └── public.v │ ├── builder/ │ │ ├── builder.v │ │ ├── builder_test.v │ │ ├── cbuilder/ │ │ │ ├── cbuilder.v │ │ │ └── parallel_cc.v │ │ ├── cc.v │ │ ├── cc_tcc_retry_test.v │ │ ├── cc_test.v │ │ ├── cc_windows.v │ │ ├── cflags.v │ │ ├── compile.v │ │ ├── dump_lists.v │ │ ├── golangbuilder/ │ │ │ └── golangbuilder.v │ │ ├── interpreterbuilder/ │ │ │ ├── ibuilder.v │ │ │ └── v_interpret_test.v │ │ ├── jsbuilder/ │ │ │ └── jsbuilder.v │ │ ├── msvc.v │ │ ├── msvc_windows.v │ │ ├── nativebuilder/ │ │ │ └── nativebuilder.v │ │ ├── rebuilding.v │ │ └── wasmbuilder/ │ │ └── wasmbuilder.v │ ├── callgraph/ │ │ └── callgraph.v │ ├── cflag/ │ │ └── cflags.v │ ├── checker/ │ │ ├── assign.v │ │ ├── autocomplete.v │ │ ├── check_types.v │ │ ├── checker.v │ │ ├── comptime.v │ │ ├── containers.v │ │ ├── errors.v │ │ ├── fn.v │ │ ├── for.v │ │ ├── if.v │ │ ├── infix.v │ │ ├── interface.v │ │ ├── lambda_expr.v │ │ ├── match.v │ │ ├── orm.v │ │ ├── postfix.v │ │ ├── return.v │ │ ├── str.v │ │ ├── struct.v │ │ ├── tests/ │ │ │ ├── .gitattributes │ │ │ ├── .gitignore │ │ │ ├── a_test_file_with_0_test_fns_test.out │ │ │ ├── a_test_file_with_0_test_fns_test.vv │ │ │ ├── add_op_wrong_type_err.out │ │ │ ├── add_op_wrong_type_err.vv │ │ │ ├── addr.out │ │ │ ├── addr.vv │ │ │ ├── addr_of_invalid_expr.out │ │ │ ├── addr_of_invalid_expr.vv │ │ │ ├── alias_array_unknown_op_overloading_err.out │ │ │ ├── alias_array_unknown_op_overloading_err.vv │ │ │ ├── alias_map_unknown_op_overloading_err.out │ │ │ ├── alias_map_unknown_op_overloading_err.vv │ │ │ ├── alias_to_generic_err.out │ │ │ ├── alias_to_generic_err.vv │ │ │ ├── alias_to_option_err.out │ │ │ ├── alias_to_option_err.vv │ │ │ ├── alias_type_cast_option_result_unhandled_err.out │ │ │ ├── alias_type_cast_option_result_unhandled_err.vv │ │ │ ├── alias_type_unknown.out │ │ │ ├── alias_type_unknown.vv │ │ │ ├── always_true_false_branch.out │ │ │ ├── always_true_false_branch.vv │ │ │ ├── ambiguous_field_method_err.out │ │ │ ├── ambiguous_field_method_err.vv │ │ │ ├── ambiguous_function_call.out │ │ │ ├── ambiguous_function_call.vv │ │ │ ├── amod/ │ │ │ │ └── amod.v │ │ │ ├── anon_arg_redefinition_err.out │ │ │ ├── anon_arg_redefinition_err.vv │ │ │ ├── anon_fn_arg_type_err.out │ │ │ ├── anon_fn_arg_type_err.vv │ │ │ ├── anon_fn_without_body.out │ │ │ ├── anon_fn_without_body.vv │ │ │ ├── anon_missing_generic_err.out │ │ │ ├── anon_missing_generic_err.vv │ │ │ ├── anon_struct_assign_err.out │ │ │ ├── anon_struct_assign_err.vv │ │ │ ├── anon_structs_visibility/ │ │ │ │ ├── amod/ │ │ │ │ │ └── amod.v │ │ │ │ └── main.v │ │ │ ├── anon_structs_visibility.out │ │ │ ├── any_int_float_ban_err.out │ │ │ ├── any_int_float_ban_err.vv │ │ │ ├── any_return_type_err.out │ │ │ ├── any_return_type_err.vv │ │ │ ├── any_type_err.out │ │ │ ├── any_type_err.vv │ │ │ ├── append_err.out │ │ │ ├── append_err.vv │ │ │ ├── array_append_array_type_mismatch_err.out │ │ │ ├── array_append_array_type_mismatch_err.vv │ │ │ ├── array_assign_err.out │ │ │ ├── array_assign_err.vv │ │ │ ├── array_builtin_method_args_err.out │ │ │ ├── array_builtin_method_args_err.vv │ │ │ ├── array_builtin_redefinition.out │ │ │ ├── array_builtin_redefinition.vv │ │ │ ├── array_cmp_err.out │ │ │ ├── array_cmp_err.vv │ │ │ ├── array_contains_args_err.out │ │ │ ├── array_contains_args_err.vv │ │ │ ├── array_count_err.out │ │ │ ├── array_count_err.vv │ │ │ ├── array_declare_element_a.out │ │ │ ├── array_declare_element_a.vv │ │ │ ├── array_declare_element_b.out │ │ │ ├── array_declare_element_b.vv │ │ │ ├── array_declare_element_c.out │ │ │ ├── array_declare_element_c.vv │ │ │ ├── array_delete_arg_mismatch_err.out │ │ │ ├── array_delete_arg_mismatch_err.vv │ │ │ ├── array_delete_imut_err.out │ │ │ ├── array_delete_imut_err.vv │ │ │ ├── array_delete_print_err.out │ │ │ ├── array_delete_print_err.vv │ │ │ ├── array_element_type.out │ │ │ ├── array_element_type.vv │ │ │ ├── array_fancy_sort_err.out │ │ │ ├── array_fancy_sort_err.vv │ │ │ ├── array_filter_arg_mismatch_err.out │ │ │ ├── array_filter_arg_mismatch_err.vv │ │ │ ├── array_filter_fn_err.out │ │ │ ├── array_filter_fn_err.vv │ │ │ ├── array_filter_map_array_expression_as_argument_err.out │ │ │ ├── array_filter_map_array_expression_as_argument_err.vv │ │ │ ├── array_filter_map_option_function_err.out │ │ │ ├── array_filter_map_option_function_err.vv │ │ │ ├── array_fixed_no_free_method_call_err.out │ │ │ ├── array_fixed_no_free_method_call_err.vv │ │ │ ├── array_generic_methods_err.out │ │ │ ├── array_generic_methods_err.vv │ │ │ ├── array_index.out │ │ │ ├── array_index.vv │ │ │ ├── array_index_args_err.out │ │ │ ├── array_index_args_err.vv │ │ │ ├── array_init_decompose_extra_params.out │ │ │ ├── array_init_decompose_extra_params.vv │ │ │ ├── array_init_element_option_mismatch_err.out │ │ │ ├── array_init_element_option_mismatch_err.vv │ │ │ ├── array_init_option_err.out │ │ │ ├── array_init_option_err.vv │ │ │ ├── array_init_ptr_non_ptr_elem_err.out │ │ │ ├── array_init_ptr_non_ptr_elem_err.vv │ │ │ ├── array_init_with_len_cap_err.out │ │ │ ├── array_init_with_len_cap_err.vv │ │ │ ├── array_init_with_void_value_err.out │ │ │ ├── array_init_with_void_value_err.vv │ │ │ ├── array_init_without_init_value_err.out │ │ │ ├── array_init_without_init_value_err.vv │ │ │ ├── array_insert_prepend_args_err.out │ │ │ ├── array_insert_prepend_args_err.vv │ │ │ ├── array_insert_type_mismatch.out │ │ │ ├── array_insert_type_mismatch.vv │ │ │ ├── array_insert_val_err.out │ │ │ ├── array_insert_val_err.vv │ │ │ ├── array_literal_modify_err.out │ │ │ ├── array_literal_modify_err.vv │ │ │ ├── array_map_arg_mismatch.out │ │ │ ├── array_map_arg_mismatch.vv │ │ │ ├── array_map_elements_ref_fields_uninitialized_err.out │ │ │ ├── array_map_elements_ref_fields_uninitialized_err.vv │ │ │ ├── array_map_fn_err.out │ │ │ ├── array_map_fn_err.vv │ │ │ ├── array_map_void_fn_err.out │ │ │ ├── array_map_void_fn_err.vv │ │ │ ├── array_method_call_immutable_err.out │ │ │ ├── array_method_call_immutable_err.vv │ │ │ ├── array_method_invalid_expr.out │ │ │ ├── array_method_invalid_expr.vv │ │ │ ├── array_none_element_err.out │ │ │ ├── array_none_element_err.vv │ │ │ ├── array_of_generic_struct_init_err.out │ │ │ ├── array_of_generic_struct_init_err.vv │ │ │ ├── array_of_refs_insert_non_ref.out │ │ │ ├── array_of_refs_insert_non_ref.vv │ │ │ ├── array_of_refs_mutability.out │ │ │ ├── array_of_refs_mutability.vv │ │ │ ├── array_of_sumtype_append_err.out │ │ │ ├── array_of_sumtype_append_err.vv │ │ │ ├── array_or_map_assign_err.out │ │ │ ├── array_or_map_assign_err.vv │ │ │ ├── array_plus_assign_err.out │ │ │ ├── array_plus_assign_err.vv │ │ │ ├── array_prepend_type_mismatch.out │ │ │ ├── array_prepend_type_mismatch.vv │ │ │ ├── array_sort_err.out │ │ │ ├── array_sort_err.vv │ │ │ ├── array_sort_struct_no_body_err.out │ │ │ ├── array_sort_struct_no_body_err.vv │ │ │ ├── array_sort_with_compare_err.out │ │ │ ├── array_sort_with_compare_err.vv │ │ │ ├── array_sort_with_compare_ref_elem_err.out │ │ │ ├── array_sort_with_compare_ref_elem_err.vv │ │ │ ├── array_sorted_with_compare_err.out │ │ │ ├── array_sorted_with_compare_err.vv │ │ │ ├── array_voidptr_assign_err.out │ │ │ ├── array_voidptr_assign_err.vv │ │ │ ├── arraydecompose_arg2_err.out │ │ │ ├── arraydecompose_arg2_err.vv │ │ │ ├── arraydecompose_arg_err.out │ │ │ ├── arraydecompose_arg_err.vv │ │ │ ├── arrow_op_wrong_left_type_err_a.out │ │ │ ├── arrow_op_wrong_left_type_err_a.vv │ │ │ ├── arrow_op_wrong_left_type_err_b.out │ │ │ ├── arrow_op_wrong_left_type_err_b.vv │ │ │ ├── arrow_op_wrong_right_type_err_a.out │ │ │ ├── arrow_op_wrong_right_type_err_a.vv │ │ │ ├── arrow_op_wrong_right_type_err_b.out │ │ │ ├── arrow_op_wrong_right_type_err_b.vv │ │ │ ├── as_cast_option_result_unhandled_err.out │ │ │ ├── as_cast_option_result_unhandled_err.vv │ │ │ ├── as_cast_selector_expr_err.out │ │ │ ├── as_cast_selector_expr_err.vv │ │ │ ├── asm_immutable_err.out │ │ │ ├── asm_immutable_err.vv │ │ │ ├── assert_extra_message.out │ │ │ ├── assert_extra_message.vv │ │ │ ├── assert_option_err.out │ │ │ ├── assert_option_err.vv │ │ │ ├── assign_anon_struct_to_typed_struct_err.out │ │ │ ├── assign_anon_struct_to_typed_struct_err.vv │ │ │ ├── assign_any_err.out │ │ │ ├── assign_any_err.vv │ │ │ ├── assign_array_init_to_fixed_array_var.out │ │ │ ├── assign_array_init_to_fixed_array_var.vv │ │ │ ├── assign_array_init_with_no_type.out │ │ │ ├── assign_array_init_with_no_type.vv │ │ │ ├── assign_blank_none_err.out │ │ │ ├── assign_blank_none_err.vv │ │ │ ├── assign_const_ptr_int_literal_err.out │ │ │ ├── assign_const_ptr_int_literal_err.vv │ │ │ ├── assign_deref_fn_call_on_left_side_err.out │ │ │ ├── assign_deref_fn_call_on_left_side_err.vv │ │ │ ├── assign_enum_at_comptime.out │ │ │ ├── assign_enum_at_comptime.vv │ │ │ ├── assign_expr_channel_push.out │ │ │ ├── assign_expr_channel_push.vv │ │ │ ├── assign_expr_type_err_a.out │ │ │ ├── assign_expr_type_err_a.vv │ │ │ ├── assign_expr_type_err_b.out │ │ │ ├── assign_expr_type_err_b.vv │ │ │ ├── assign_expr_type_err_c.out │ │ │ ├── assign_expr_type_err_c.vv │ │ │ ├── assign_expr_type_err_d.out │ │ │ ├── assign_expr_type_err_d.vv │ │ │ ├── assign_expr_type_err_e.out │ │ │ ├── assign_expr_type_err_e.vv │ │ │ ├── assign_expr_type_err_f.out │ │ │ ├── assign_expr_type_err_f.vv │ │ │ ├── assign_expr_type_err_g.out │ │ │ ├── assign_expr_type_err_g.vv │ │ │ ├── assign_expr_type_err_h.out │ │ │ ├── assign_expr_type_err_h.vv │ │ │ ├── assign_expr_type_err_i.out │ │ │ ├── assign_expr_type_err_i.vv │ │ │ ├── assign_expr_undefined_err_a.out │ │ │ ├── assign_expr_undefined_err_a.vv │ │ │ ├── assign_expr_undefined_err_b.out │ │ │ ├── assign_expr_undefined_err_b.vv │ │ │ ├── assign_expr_undefined_err_c.out │ │ │ ├── assign_expr_undefined_err_c.vv │ │ │ ├── assign_expr_undefined_err_d.out │ │ │ ├── assign_expr_undefined_err_d.vv │ │ │ ├── assign_expr_undefined_err_e.out │ │ │ ├── assign_expr_undefined_err_e.vv │ │ │ ├── assign_expr_undefined_err_f.out │ │ │ ├── assign_expr_undefined_err_f.vv │ │ │ ├── assign_expr_undefined_err_g.out │ │ │ ├── assign_expr_undefined_err_g.vv │ │ │ ├── assign_expr_undefined_err_h.out │ │ │ ├── assign_expr_undefined_err_h.vv │ │ │ ├── assign_expr_undefined_err_i.out │ │ │ ├── assign_expr_undefined_err_i.vv │ │ │ ├── assign_expr_undefined_err_j.out │ │ │ ├── assign_expr_undefined_err_j.vv │ │ │ ├── assign_expr_undefined_err_k.out │ │ │ ├── assign_expr_undefined_err_k.vv │ │ │ ├── assign_expr_undefined_err_l.out │ │ │ ├── assign_expr_undefined_err_l.vv │ │ │ ├── assign_expr_undefined_err_m.out │ │ │ ├── assign_expr_undefined_err_m.vv │ │ │ ├── assign_expr_undefined_err_n.out │ │ │ ├── assign_expr_undefined_err_n.vv │ │ │ ├── assign_expr_unresolved_variables_err_chain.out │ │ │ ├── assign_expr_unresolved_variables_err_chain.vv │ │ │ ├── assign_fn_call_on_left_side_err.out │ │ │ ├── assign_fn_call_on_left_side_err.vv │ │ │ ├── assign_generic_fn_err.out │ │ │ ├── assign_generic_fn_err.vv │ │ │ ├── assign_immutable_reference_struct_field_err.out │ │ │ ├── assign_immutable_reference_struct_field_err.vv │ │ │ ├── assign_immutable_reference_var_err.out │ │ │ ├── assign_immutable_reference_var_err.vv │ │ │ ├── assign_immutable_reference_var_with_parenthesis_err.out │ │ │ ├── assign_immutable_reference_var_with_parenthesis_err.vv │ │ │ ├── assign_multi_immutable_err.out │ │ │ ├── assign_multi_immutable_err.vv │ │ │ ├── assign_multi_mismatch.out │ │ │ ├── assign_multi_mismatch.vv │ │ │ ├── assign_mut.out │ │ │ ├── assign_mut.vv │ │ │ ├── assign_none.out │ │ │ ├── assign_none.vv │ │ │ ├── assign_ref_call_expr_with_ref_return_err.out │ │ │ ├── assign_ref_call_expr_with_ref_return_err.vv │ │ │ ├── assign_sumtype2_err.out │ │ │ ├── assign_sumtype2_err.vv │ │ │ ├── assign_sumtype_err.out │ │ │ ├── assign_sumtype_err.vv │ │ │ ├── assign_to_typeless_variable_err.out │ │ │ ├── assign_to_typeless_variable_err.vv │ │ │ ├── assign_type_mismatch_with_generics_err.out │ │ │ ├── assign_type_mismatch_with_generics_err.vv │ │ │ ├── assign_var_redefinition_err.out │ │ │ ├── assign_var_redefinition_err.vv │ │ │ ├── assign_with_dump_multireturn_value.out │ │ │ ├── assign_with_dump_multireturn_value.vv │ │ │ ├── auto_deref_assign_err.out │ │ │ ├── auto_deref_assign_err.vv │ │ │ ├── auto_ref_voidptr.out │ │ │ ├── auto_ref_voidptr.vv │ │ │ ├── bad_types_in_string_inter_lit.out │ │ │ ├── bad_types_in_string_inter_lit.vv │ │ │ ├── ban_const_ref_mutation.out │ │ │ ├── ban_const_ref_mutation.vv │ │ │ ├── bin_lit_without_digit_err.out │ │ │ ├── bin_lit_without_digit_err.vv │ │ │ ├── bin_lit_wrong_digit_err.out │ │ │ ├── bin_lit_wrong_digit_err.vv │ │ │ ├── bit_op_wrong_left_type_err.out │ │ │ ├── bit_op_wrong_left_type_err.vv │ │ │ ├── bit_op_wrong_right_type_err.out │ │ │ ├── bit_op_wrong_right_type_err.vv │ │ │ ├── blank_ident_const_ptr_int_literal_err.out │ │ │ ├── blank_ident_const_ptr_int_literal_err.vv │ │ │ ├── blank_ident_invalid_use.out │ │ │ ├── blank_ident_invalid_use.vv │ │ │ ├── blank_ident_select_branch_send_err.out │ │ │ ├── blank_ident_select_branch_send_err.vv │ │ │ ├── blank_modify.out │ │ │ ├── blank_modify.vv │ │ │ ├── bool_string_cast_err.out │ │ │ ├── bool_string_cast_err.vv │ │ │ ├── break_anon_fn_err.out │ │ │ ├── break_anon_fn_err.vv │ │ │ ├── c_fn_surplus_args.out │ │ │ ├── c_fn_surplus_args.vv │ │ │ ├── c_js_struct_and_fn_as_generics_error.out │ │ │ ├── c_js_struct_and_fn_as_generics_error.vv │ │ │ ├── c_struct_cast.out │ │ │ ├── c_struct_cast.vv │ │ │ ├── call_arg_multi_return_err.out │ │ │ ├── call_arg_multi_return_err.vv │ │ │ ├── call_empty_or_block_err.out │ │ │ ├── call_empty_or_block_err.vv │ │ │ ├── cannot_assign_array.out │ │ │ ├── cannot_assign_array.vv │ │ │ ├── cannot_cast_to_alias.out │ │ │ ├── cannot_cast_to_alias.vv │ │ │ ├── cannot_cast_to_struct.out │ │ │ ├── cannot_cast_to_struct.vv │ │ │ ├── cannot_dereference_if_different_muls.out │ │ │ ├── cannot_dereference_if_different_muls.vv │ │ │ ├── cast_array_to_number_err.out │ │ │ ├── cast_array_to_number_err.vv │ │ │ ├── cast_err.out │ │ │ ├── cast_err.vv │ │ │ ├── cast_expr_T_type_err.out │ │ │ ├── cast_expr_T_type_err.vv │ │ │ ├── cast_fn_err.out │ │ │ ├── cast_fn_err.vv │ │ │ ├── cast_function_to_string_err.out │ │ │ ├── cast_function_to_string_err.vv │ │ │ ├── cast_generic_err.out │ │ │ ├── cast_generic_err.vv │ │ │ ├── cast_integer_with_overflow_err.out │ │ │ ├── cast_integer_with_overflow_err.vv │ │ │ ├── cast_string_err.out │ │ │ ├── cast_string_err.vv │ │ │ ├── cast_string_to_char_err.out │ │ │ ├── cast_string_to_char_err.vv │ │ │ ├── cast_string_to_int_err.out │ │ │ ├── cast_string_to_int_err.vv │ │ │ ├── cast_string_to_ptr_err.out │ │ │ ├── cast_string_to_ptr_err.vv │ │ │ ├── cast_string_to_rune_err.out │ │ │ ├── cast_string_to_rune_err.vv │ │ │ ├── cast_string_with_byte_err.out │ │ │ ├── cast_string_with_byte_err.vv │ │ │ ├── cast_sumtype_as_generic_err.out │ │ │ ├── cast_sumtype_as_generic_err.vv │ │ │ ├── cast_sumtype_err.out │ │ │ ├── cast_sumtype_err.vv │ │ │ ├── cast_to_byte_err.out │ │ │ ├── cast_to_byte_err.vv │ │ │ ├── cast_to_concrete_mut_err.out │ │ │ ├── cast_to_concrete_mut_err.vv │ │ │ ├── cast_to_interface_err.out │ │ │ ├── cast_to_interface_err.vv │ │ │ ├── cast_to_ref_struct_err.out │ │ │ ├── cast_to_ref_struct_err.vv │ │ │ ├── cast_void.out │ │ │ ├── cast_void.vv │ │ │ ├── cast_voidptr_to_struct_alias_err.out │ │ │ ├── cast_voidptr_to_struct_alias_err.vv │ │ │ ├── cast_voidptr_to_struct_err.out │ │ │ ├── cast_voidptr_to_struct_err.vv │ │ │ ├── casting_numbers_to_enums_outside_unsafe_err.out │ │ │ ├── casting_numbers_to_enums_outside_unsafe_err.vv │ │ │ ├── chan_args.out │ │ │ ├── chan_args.vv │ │ │ ├── chan_elem_type_unknown.out │ │ │ ├── chan_elem_type_unknown.vv │ │ │ ├── chan_incompatible_type_err.out │ │ │ ├── chan_incompatible_type_err.vv │ │ │ ├── chan_mut.out │ │ │ ├── chan_mut.vv │ │ │ ├── chan_ref.out │ │ │ ├── chan_ref.vv │ │ │ ├── chan_unknown_err.out │ │ │ ├── chan_unknown_err.vv │ │ │ ├── char_str.out │ │ │ ├── char_str.vv │ │ │ ├── check_err_msg_with_generics.out │ │ │ ├── check_err_msg_with_generics.vv │ │ │ ├── check_fn_init_as_mutable.out │ │ │ ├── check_fn_init_as_mutable.vv │ │ │ ├── check_incompatible_struct.out │ │ │ ├── check_incompatible_struct.vv │ │ │ ├── check_wrong_usage_of_break_and_continue.out │ │ │ ├── check_wrong_usage_of_break_and_continue.vv │ │ │ ├── checker_comparison_between_obj_and_int.out │ │ │ ├── checker_comparison_between_obj_and_int.vv │ │ │ ├── clash_ident_module_name_prefix.out │ │ │ ├── clash_ident_module_name_prefix.vv │ │ │ ├── closure_copy_immutable_var_err.out │ │ │ ├── closure_copy_immutable_var_err.vv │ │ │ ├── closure_immutable.out │ │ │ ├── closure_immutable.vv │ │ │ ├── closure_undefined_ident_err.out │ │ │ ├── closure_undefined_ident_err.vv │ │ │ ├── cmp_between_struct.out │ │ │ ├── cmp_between_struct.vv │ │ │ ├── compare_unsigned_signed.out │ │ │ ├── compare_unsigned_signed.vv │ │ │ ├── comparing_typesymbol_to_a_type_should_not_compile.out │ │ │ ├── comparing_typesymbol_to_a_type_should_not_compile.vv │ │ │ ├── compile_error.out │ │ │ ├── compile_error.vv │ │ │ ├── compile_error_call_position.out │ │ │ ├── compile_error_call_position.vv │ │ │ ├── compile_error_explicit_type.out │ │ │ ├── compile_error_explicit_type.vv │ │ │ ├── comptime_assign_missing_mut_err.out │ │ │ ├── comptime_assign_missing_mut_err.vv │ │ │ ├── comptime_branching_working_with_a_custom_compile_error.out │ │ │ ├── comptime_branching_working_with_a_custom_compile_error.vv │ │ │ ├── comptime_call_method.out │ │ │ ├── comptime_call_method.vv │ │ │ ├── comptime_call_method_args_err.out │ │ │ ├── comptime_call_method_args_err.vv │ │ │ ├── comptime_call_method_void_err.out │ │ │ ├── comptime_call_method_void_err.vv │ │ │ ├── comptime_call_no_unused_var.out │ │ │ ├── comptime_call_no_unused_var.vv │ │ │ ├── comptime_compile_warn_with_string_interp_test.out │ │ │ ├── comptime_compile_warn_with_string_interp_test.vv │ │ │ ├── comptime_defer_err.out │ │ │ ├── comptime_defer_err.vv │ │ │ ├── comptime_dump_fields_var_test.out │ │ │ ├── comptime_dump_fields_var_test.vv │ │ │ ├── comptime_else_compile_error_no_return.out │ │ │ ├── comptime_else_compile_error_no_return.vv │ │ │ ├── comptime_env/ │ │ │ │ ├── env_parser_errors_1.run.out │ │ │ │ ├── env_parser_errors_1.vv │ │ │ │ ├── env_parser_errors_2.run.out │ │ │ │ ├── env_parser_errors_2.vv │ │ │ │ ├── env_parser_errors_3.run.out │ │ │ │ ├── env_parser_errors_3.vv │ │ │ │ ├── using_comptime_env.run.out │ │ │ │ ├── using_comptime_env.var.run.out │ │ │ │ ├── using_comptime_env.var_invalid.run.out │ │ │ │ └── using_comptime_env.vv │ │ │ ├── comptime_field_name_assign_incorrect_type_err.out │ │ │ ├── comptime_field_name_assign_incorrect_type_err.vv │ │ │ ├── comptime_field_name_not_exist.out │ │ │ ├── comptime_field_name_not_exist.vv │ │ │ ├── comptime_field_selector_not_in_for_err.out │ │ │ ├── comptime_field_selector_not_in_for_err.vv │ │ │ ├── comptime_field_selector_not_name_err.out │ │ │ ├── comptime_field_selector_not_name_err.vv │ │ │ ├── comptime_for.out │ │ │ ├── comptime_for.vv │ │ │ ├── comptime_if_option_string_test.out │ │ │ ├── comptime_if_option_string_test.vv │ │ │ ├── comptime_insert_err.cc │ │ │ ├── comptime_insert_err.out │ │ │ ├── comptime_insert_err.vv │ │ │ ├── comptime_match_cond_cannot_mut.out │ │ │ ├── comptime_match_cond_cannot_mut.vv │ │ │ ├── comptime_match_value_different_type.out │ │ │ ├── comptime_match_value_different_type.vv │ │ │ ├── comptime_match_value_type_mix_check.out │ │ │ ├── comptime_match_value_type_mix_check.vv │ │ │ ├── comptime_param_not_fn_err.out │ │ │ ├── comptime_param_not_fn_err.vv │ │ │ ├── comptime_selector_assign.out │ │ │ ├── comptime_selector_assign.vv │ │ │ ├── comptime_selector_expr_type_err.out │ │ │ ├── comptime_selector_expr_type_err.vv │ │ │ ├── comptime_value_d_in_include_errors.out │ │ │ ├── comptime_value_d_in_include_errors.vv │ │ │ ├── comptime_value_d_only_d_in_fixed_size_array.out │ │ │ ├── comptime_value_d_only_d_in_fixed_size_array.vv │ │ │ ├── comptime_value_d_values_can_only_be_pure_literals.out │ │ │ ├── comptime_value_d_values_can_only_be_pure_literals.vv │ │ │ ├── comptime_veb_vweb_call_err.out │ │ │ ├── comptime_veb_vweb_call_err.vv │ │ │ ├── const_array_unknown_type_err.out │ │ │ ├── const_array_unknown_type_err.vv │ │ │ ├── const_blank_ident_as_name_err.out │ │ │ ├── const_blank_ident_as_name_err.vv │ │ │ ├── const_cycle_decl_err.out │ │ │ ├── const_cycle_decl_err.vv │ │ │ ├── const_decl_multi_return_err.out │ │ │ ├── const_decl_multi_return_err.vv │ │ │ ├── const_define_in_function_err.out │ │ │ ├── const_define_in_function_err.vv │ │ │ ├── const_expr_match_range_invalid_err.out │ │ │ ├── const_expr_match_range_invalid_err.vv │ │ │ ├── const_field_add_err.out │ │ │ ├── const_field_add_err.vv │ │ │ ├── const_field_dec_err.out │ │ │ ├── const_field_dec_err.vv │ │ │ ├── const_field_inc_err.out │ │ │ ├── const_field_inc_err.vv │ │ │ ├── const_field_name_duplicate_err.out │ │ │ ├── const_field_name_duplicate_err.vv │ │ │ ├── const_field_name_snake_case.out │ │ │ ├── const_field_name_snake_case.vv │ │ │ ├── const_field_sub_err.out │ │ │ ├── const_field_sub_err.vv │ │ │ ├── const_int_overflow_err.out │ │ │ ├── const_int_overflow_err.vv │ │ │ ├── const_match_invalid_type_range_err.out │ │ │ ├── const_match_invalid_type_range_err.vv │ │ │ ├── const_match_mismatch_end_range_err.out │ │ │ ├── const_match_mismatch_end_range_err.vv │ │ │ ├── const_match_range_duplicate_case_err.out │ │ │ ├── const_match_range_duplicate_case_err.vv │ │ │ ├── const_match_range_invalid_err.out │ │ │ ├── const_match_range_invalid_err.vv │ │ │ ├── const_match_type_mismatch_range_err.out │ │ │ ├── const_match_type_mismatch_range_err.vv │ │ │ ├── const_name_for_loop_duplicate_name_err.out │ │ │ ├── const_name_for_loop_duplicate_name_err.vv │ │ │ ├── const_reference_write_err.out │ │ │ ├── const_reference_write_err.vv │ │ │ ├── crystallib_struct_init_result_err.out │ │ │ ├── crystallib_struct_init_result_err.vv │ │ │ ├── ctdefine.out │ │ │ ├── ctdefine.vv │ │ │ ├── custom_comptime_define_error.mysymbol.run.out │ │ │ ├── custom_comptime_define_error.out │ │ │ ├── custom_comptime_define_error.vv │ │ │ ├── custom_comptime_define_if_debug.cg.run.out │ │ │ ├── custom_comptime_define_if_debug.debug.bar.run.out │ │ │ ├── custom_comptime_define_if_debug.debug.run.out │ │ │ ├── custom_comptime_define_if_debug.g.run.out │ │ │ ├── custom_comptime_define_if_debug.out │ │ │ ├── custom_comptime_define_if_debug.run.out │ │ │ ├── custom_comptime_define_if_debug.vv │ │ │ ├── custom_comptime_define_if_flag.mydebug.run.out │ │ │ ├── custom_comptime_define_if_flag.nodebug.run.out │ │ │ ├── custom_comptime_define_if_flag.out │ │ │ ├── custom_comptime_define_if_flag.vv │ │ │ ├── dec_lit_wrong_digit_err.out │ │ │ ├── dec_lit_wrong_digit_err.vv │ │ │ ├── decompose_interface_err.out │ │ │ ├── decompose_interface_err.vv │ │ │ ├── decompose_type_err.out │ │ │ ├── decompose_type_err.vv │ │ │ ├── defer_fn_inside_fn_scope.out │ │ │ ├── defer_fn_inside_fn_scope.vv │ │ │ ├── defer_fn_inside_lock_stmt_err.out │ │ │ ├── defer_fn_inside_lock_stmt_err.vv │ │ │ ├── defer_in_for.out │ │ │ ├── defer_in_for.vv │ │ │ ├── defer_use_multi_return_value_with_index_out_of_bounds.out │ │ │ ├── defer_use_multi_return_value_with_index_out_of_bounds.vv │ │ │ ├── defer_use_multi_return_value_without_index.out │ │ │ ├── defer_use_multi_return_value_without_index.vv │ │ │ ├── defer_use_returned_value_when_nothing_is_returned.out │ │ │ ├── defer_use_returned_value_when_nothing_is_returned.vv │ │ │ ├── defer_use_returned_value_when_result_is_returned.out │ │ │ ├── defer_use_returned_value_when_result_is_returned.vv │ │ │ ├── deference_nil_ptr_err.out │ │ │ ├── deference_nil_ptr_err.vv │ │ │ ├── deprecate_any.out │ │ │ ├── deprecate_any.vv │ │ │ ├── deprecations.out │ │ │ ├── deprecations.vv │ │ │ ├── deprecations_consts.out │ │ │ ├── deprecations_consts.vv │ │ │ ├── diff_type_map_value_err.out │ │ │ ├── diff_type_map_value_err.vv │ │ │ ├── disallow_pointer_arithmetic_err.out │ │ │ ├── disallow_pointer_arithmetic_err.vv │ │ │ ├── discard_import_usage.out │ │ │ ├── discard_import_usage.vv │ │ │ ├── div_mod_by_cast_zero_int_err.out │ │ │ ├── div_mod_by_cast_zero_int_err.vv │ │ │ ├── div_op_wrong_type_err.out │ │ │ ├── div_op_wrong_type_err.vv │ │ │ ├── division_by_cast_zero_float_err.out │ │ │ ├── division_by_cast_zero_float_err.vv │ │ │ ├── division_by_zero_float_err.out │ │ │ ├── division_by_zero_float_err.vv │ │ │ ├── division_by_zero_int_err.out │ │ │ ├── division_by_zero_int_err.vv │ │ │ ├── dump_char.out │ │ │ ├── dump_char.vv │ │ │ ├── dump_of_void_expr.out │ │ │ ├── dump_of_void_expr.vv │ │ │ ├── duplicate_field_method_err.out │ │ │ ├── duplicate_field_method_err.vv │ │ │ ├── embed_unknown_compress_type.out │ │ │ ├── embed_unknown_compress_type.vv │ │ │ ├── empty_arr_to_generic_param_err.out │ │ │ ├── empty_arr_to_generic_param_err.vv │ │ │ ├── empty_arr_to_generic_param_sum_like_err.out │ │ │ ├── empty_arr_to_generic_param_sum_like_err.vv │ │ │ ├── empty_fn_noreturn_err.out │ │ │ ├── empty_fn_noreturn_err.vv │ │ │ ├── enum_as_int_err.out │ │ │ ├── enum_as_int_err.vv │ │ │ ├── enum_cast.out │ │ │ ├── enum_cast.vv │ │ │ ├── enum_empty.out │ │ │ ├── enum_empty.vv │ │ │ ├── enum_err.out │ │ │ ├── enum_err.vv │ │ │ ├── enum_error_module.out │ │ │ ├── enum_error_module.vv │ │ │ ├── enum_field_name_duplicate_err.out │ │ │ ├── enum_field_name_duplicate_err.vv │ │ │ ├── enum_field_overflow.out │ │ │ ├── enum_field_overflow.vv │ │ │ ├── enum_field_value_duplicate_a.out │ │ │ ├── enum_field_value_duplicate_a.vv │ │ │ ├── enum_field_value_duplicate_b.out │ │ │ ├── enum_field_value_duplicate_b.vv │ │ │ ├── enum_field_value_duplicate_c.out │ │ │ ├── enum_field_value_duplicate_c.vv │ │ │ ├── enum_field_value_duplicate_d.out │ │ │ ├── enum_field_value_duplicate_d.vv │ │ │ ├── enum_field_value_duplicate_e.out │ │ │ ├── enum_field_value_duplicate_e.vv │ │ │ ├── enum_field_value_overflow.out │ │ │ ├── enum_field_value_overflow.vv │ │ │ ├── enum_from_string_args_err.out │ │ │ ├── enum_from_string_args_err.vv │ │ │ ├── enum_init_err.out │ │ │ ├── enum_init_err.vv │ │ │ ├── enum_op_err.out │ │ │ ├── enum_op_err.vv │ │ │ ├── enum_op_flag_err.out │ │ │ ├── enum_op_flag_err.vv │ │ │ ├── enum_redeclare_err.out │ │ │ ├── enum_redeclare_err.vv │ │ │ ├── enum_self_reference.out │ │ │ ├── enum_self_reference.vv │ │ │ ├── enum_single_letter.out │ │ │ ├── enum_single_letter.vv │ │ │ ├── enum_value_used_before_decl_err.out │ │ │ ├── enum_value_used_before_decl_err.vv │ │ │ ├── eq_ne_op_wrong_type_err.out │ │ │ ├── eq_ne_op_wrong_type_err.vv │ │ │ ├── error_fn_with_0_args.out │ │ │ ├── error_fn_with_0_args.vv │ │ │ ├── error_with_comment_with_crlf_ending.out │ │ │ ├── error_with_comment_with_crlf_ending.vv │ │ │ ├── error_with_comment_with_lf_ending.out │ │ │ ├── error_with_comment_with_lf_ending.vv │ │ │ ├── error_with_several_comments_with_crlf_ending.out │ │ │ ├── error_with_several_comments_with_crlf_ending.vv │ │ │ ├── error_with_unicode.out │ │ │ ├── error_with_unicode.vv │ │ │ ├── expr_evaluated_but_not_used.out │ │ │ ├── expr_evaluated_but_not_used.vv │ │ │ ├── expression_should_return_an_option.out │ │ │ ├── expression_should_return_an_option.vv │ │ │ ├── field_can_not_be_from_the_same_type_as_containing_struct.out │ │ │ ├── field_can_not_be_from_the_same_type_as_containing_struct.vv │ │ │ ├── field_deprecations.out │ │ │ ├── field_deprecations.vv │ │ │ ├── filter_func_return_nonbool_err.out │ │ │ ├── filter_func_return_nonbool_err.vv │ │ │ ├── filter_on_non_arr_err.out │ │ │ ├── filter_on_non_arr_err.vv │ │ │ ├── fixed_array_builtin_method_args_err.out │ │ │ ├── fixed_array_builtin_method_args_err.vv │ │ │ ├── fixed_array_conv.out │ │ │ ├── fixed_array_conv.vv │ │ │ ├── fixed_array_decompose_err.out │ │ │ ├── fixed_array_decompose_err.vv │ │ │ ├── fixed_array_init_with_default.out │ │ │ ├── fixed_array_init_with_default.vv │ │ │ ├── fixed_array_non_const_size_err.out │ │ │ ├── fixed_array_non_const_size_err.vv │ │ │ ├── fixed_array_size_err.out │ │ │ ├── fixed_array_size_err.vv │ │ │ ├── fixed_array_sort_err.out │ │ │ ├── fixed_array_sort_err.vv │ │ │ ├── flag_enum_exhaustive_else_branch.out │ │ │ ├── flag_enum_exhaustive_else_branch.vv │ │ │ ├── float_lit_exp_not_integer_err.out │ │ │ ├── float_lit_exp_not_integer_err.vv │ │ │ ├── float_lit_exp_without_digit_err.out │ │ │ ├── float_lit_exp_without_digit_err.vv │ │ │ ├── float_lit_too_many_points_err.out │ │ │ ├── float_lit_too_many_points_err.vv │ │ │ ├── float_modulo_err.out │ │ │ ├── float_modulo_err.vv │ │ │ ├── fn_args.out │ │ │ ├── fn_args.vv │ │ │ ├── fn_array_decompose_arg_mismatch_err_a.out │ │ │ ├── fn_array_decompose_arg_mismatch_err_a.vv │ │ │ ├── fn_array_decompose_arg_mismatch_err_b.out │ │ │ ├── fn_array_decompose_arg_mismatch_err_b.vv │ │ │ ├── fn_array_decompose_arg_mismatch_err_c.out │ │ │ ├── fn_array_decompose_arg_mismatch_err_c.vv │ │ │ ├── fn_call_arg_array_mismatch_err.out │ │ │ ├── fn_call_arg_array_mismatch_err.vv │ │ │ ├── fn_call_arg_fn_mismatch_err.out │ │ │ ├── fn_call_arg_fn_mismatch_err.vv │ │ │ ├── fn_call_arg_mismatch_err_a.out │ │ │ ├── fn_call_arg_mismatch_err_a.vv │ │ │ ├── fn_call_arg_mismatch_err_b.out │ │ │ ├── fn_call_arg_mismatch_err_b.vv │ │ │ ├── fn_call_arg_mismatch_err_c.out │ │ │ ├── fn_call_arg_mismatch_err_c.vv │ │ │ ├── fn_call_arg_mismatch_err_d.out │ │ │ ├── fn_call_arg_mismatch_err_d.vv │ │ │ ├── fn_call_arg_mismatch_err_e.out │ │ │ ├── fn_call_arg_mismatch_err_e.vv │ │ │ ├── fn_call_arg_multi_err.out │ │ │ ├── fn_call_arg_multi_err.vv │ │ │ ├── fn_call_arg_ptr_mismatch_err.out │ │ │ ├── fn_call_arg_ptr_mismatch_err.vv │ │ │ ├── fn_call_mismatch_alias_type_err.out │ │ │ ├── fn_call_mismatch_alias_type_err.vv │ │ │ ├── fn_call_mut_arg_mismatch_err.out │ │ │ ├── fn_call_mut_arg_mismatch_err.vv │ │ │ ├── fn_call_no_body.out │ │ │ ├── fn_call_no_body.vv │ │ │ ├── fn_call_or_block_err.out │ │ │ ├── fn_call_or_block_err.vv │ │ │ ├── fn_call_ref_incompatible_u8_test.out │ │ │ ├── fn_call_ref_incompatible_u8_test.vv │ │ │ ├── fn_call_using_none_arg_err.out │ │ │ ├── fn_call_using_none_arg_err.vv │ │ │ ├── fn_call_with_extra_parenthesis.out │ │ │ ├── fn_call_with_extra_parenthesis.vv │ │ │ ├── fn_check_for_matching_option_result_in_fields.out │ │ │ ├── fn_check_for_matching_option_result_in_fields.vv │ │ │ ├── fn_duplicate.out │ │ │ ├── fn_duplicate.vv │ │ │ ├── fn_init_sig.out │ │ │ ├── fn_init_sig.vv │ │ │ ├── fn_mismatch_option_return_err.out │ │ │ ├── fn_mismatch_option_return_err.vv │ │ │ ├── fn_param_import_sym_conflict.out │ │ │ ├── fn_param_import_sym_conflict.vv │ │ │ ├── fn_ptr_undereferenced_err.out │ │ │ ├── fn_ptr_undereferenced_err.vv │ │ │ ├── fn_ref_arg_mismatch_err.out │ │ │ ├── fn_ref_arg_mismatch_err.vv │ │ │ ├── fn_result_option_call_infix_err.out │ │ │ ├── fn_result_option_call_infix_err.vv │ │ │ ├── fn_return_array_sort_err.out │ │ │ ├── fn_return_array_sort_err.vv │ │ │ ├── fn_return_fixed_array_sort_err.out │ │ │ ├── fn_return_fixed_array_sort_err.vv │ │ │ ├── fn_return_fn_type_mismatch_err.out │ │ │ ├── fn_return_fn_type_mismatch_err.vv │ │ │ ├── fn_return_or_err.out │ │ │ ├── fn_return_or_err.vv │ │ │ ├── fn_return_type_mismatch.out │ │ │ ├── fn_return_type_mismatch.vv │ │ │ ├── fn_return_unsign_type_mismatch.out │ │ │ ├── fn_return_unsign_type_mismatch.vv │ │ │ ├── fn_return_void_fn_call_err.out │ │ │ ├── fn_return_void_fn_call_err.vv │ │ │ ├── fn_selector_expr_err.out │ │ │ ├── fn_selector_expr_err.vv │ │ │ ├── fn_type_exists.out │ │ │ ├── fn_type_exists.vv │ │ │ ├── fn_type_mismatch.out │ │ │ ├── fn_type_mismatch.vv │ │ │ ├── fn_var.out │ │ │ ├── fn_var.vv │ │ │ ├── fn_variadic.out │ │ │ ├── fn_variadic.vv │ │ │ ├── fn_variadic_arg_err.out │ │ │ ├── fn_variadic_arg_err.vv │ │ │ ├── for_c_stmt_with_var_declaration_in_post_stmt.out │ │ │ ├── for_c_stmt_with_var_declaration_in_post_stmt.vv │ │ │ ├── for_comptime_enum_fields_err.out │ │ │ ├── for_comptime_enum_fields_err.vv │ │ │ ├── for_comptime_struct_values_err.out │ │ │ ├── for_comptime_struct_values_err.vv │ │ │ ├── for_in_index_option.out │ │ │ ├── for_in_index_option.vv │ │ │ ├── for_in_index_type.out │ │ │ ├── for_in_index_type.vv │ │ │ ├── for_in_invalid_identifier.out │ │ │ ├── for_in_invalid_identifier.vv │ │ │ ├── for_in_iterator_returning_multiple_values_err.out │ │ │ ├── for_in_iterator_returning_multiple_values_err.vv │ │ │ ├── for_in_key_redefinition.out │ │ │ ├── for_in_key_redefinition.vv │ │ │ ├── for_in_map_one_variable_err.out │ │ │ ├── for_in_map_one_variable_err.vv │ │ │ ├── for_in_mut_string.out │ │ │ ├── for_in_mut_string.vv │ │ │ ├── for_in_mut_val_type.out │ │ │ ├── for_in_mut_val_type.vv │ │ │ ├── for_in_range_not_match_type.out │ │ │ ├── for_in_range_not_match_type.vv │ │ │ ├── for_in_range_result_optional_err.out │ │ │ ├── for_in_range_result_optional_err.vv │ │ │ ├── for_in_range_string_type.out │ │ │ ├── for_in_range_string_type.vv │ │ │ ├── for_in_same_var_err.out │ │ │ ├── for_in_same_var_err.vv │ │ │ ├── for_in_value_redefinition.out │ │ │ ├── for_in_value_redefinition.vv │ │ │ ├── for_in_with_reserved_type_names.out │ │ │ ├── for_in_with_reserved_type_names.vv │ │ │ ├── for_loop_range_inclusive_err.out │ │ │ ├── for_loop_range_inclusive_err.vv │ │ │ ├── for_match_err.out │ │ │ ├── for_match_err.vv │ │ │ ├── for_mut_compare_rune_string_err.out │ │ │ ├── for_mut_compare_rune_string_err.vv │ │ │ ├── free_method_errors.out │ │ │ ├── free_method_errors.vv │ │ │ ├── from_string_on_non_enum_err.out │ │ │ ├── from_string_on_non_enum_err.vv │ │ │ ├── func_with_static_keyword_err.out │ │ │ ├── func_with_static_keyword_err.vv │ │ │ ├── function_arg_mutable_err.out │ │ │ ├── function_arg_mutable_err.vv │ │ │ ├── function_arg_redefinition.out │ │ │ ├── function_arg_redefinition.vv │ │ │ ├── function_cast_outside_unsafe_err.out │ │ │ ├── function_cast_outside_unsafe_err.vv │ │ │ ├── function_count_of_args_mismatch_err.out │ │ │ ├── function_count_of_args_mismatch_err.vv │ │ │ ├── function_missing_return_type.out │ │ │ ├── function_missing_return_type.vv │ │ │ ├── function_variadic_arg_array_decompose.out │ │ │ ├── function_variadic_arg_array_decompose.vv │ │ │ ├── function_wrong_arg_type.out │ │ │ ├── function_wrong_arg_type.vv │ │ │ ├── function_wrong_return_type.out │ │ │ ├── function_wrong_return_type.vv │ │ │ ├── generic_array_init_err.out │ │ │ ├── generic_array_init_err.vv │ │ │ ├── generic_closure_fn_decl_err_a.out │ │ │ ├── generic_closure_fn_decl_err_a.vv │ │ │ ├── generic_closure_fn_decl_err_b.out │ │ │ ├── generic_closure_fn_decl_err_b.vv │ │ │ ├── generic_eq_wrong_type.err.out │ │ │ ├── generic_eq_wrong_type.err.vv │ │ │ ├── generic_field_init_with_call_err.out │ │ │ ├── generic_field_init_with_call_err.vv │ │ │ ├── generic_fn_call_arg_mismatch_err.out │ │ │ ├── generic_fn_call_arg_mismatch_err.vv │ │ │ ├── generic_fn_decl_err.out │ │ │ ├── generic_fn_decl_err.vv │ │ │ ├── generic_fn_decl_without_generic_names_err.out │ │ │ ├── generic_fn_decl_without_generic_names_err.vv │ │ │ ├── generic_fn_generic_name_unresolved_err.out │ │ │ ├── generic_fn_generic_name_unresolved_err.vv │ │ │ ├── generic_fn_infinite_loop_limit_err.out │ │ │ ├── generic_fn_infinite_loop_limit_err.vv │ │ │ ├── generic_fn_var_unresolved_err.out │ │ │ ├── generic_fn_var_unresolved_err.vv │ │ │ ├── generic_fntype_err.out │ │ │ ├── generic_fntype_err.vv │ │ │ ├── generic_infix_plus_err.out │ │ │ ├── generic_infix_plus_err.vv │ │ │ ├── generic_interface_err.out │ │ │ ├── generic_interface_err.vv │ │ │ ├── generic_interface_method_decl_err.out │ │ │ ├── generic_interface_method_decl_err.vv │ │ │ ├── generic_interface_missing_type_names_err.out │ │ │ ├── generic_interface_missing_type_names_err.vv │ │ │ ├── generic_mut_struct_index_err.out │ │ │ ├── generic_mut_struct_index_err.vv │ │ │ ├── generic_sumtype_decl_err_a.out │ │ │ ├── generic_sumtype_decl_err_a.vv │ │ │ ├── generic_sumtype_decl_err_b.out │ │ │ ├── generic_sumtype_decl_err_b.vv │ │ │ ├── generic_sumtype_decl_err_c.out │ │ │ ├── generic_sumtype_decl_err_c.vv │ │ │ ├── generic_sumtype_decl_err_d.out │ │ │ ├── generic_sumtype_decl_err_d.vv │ │ │ ├── generic_sumtype_decl_err_e.out │ │ │ ├── generic_sumtype_decl_err_e.vv │ │ │ ├── generic_sumtype_invalid_variant.out │ │ │ ├── generic_sumtype_invalid_variant.vv │ │ │ ├── generic_type_inference.out │ │ │ ├── generic_type_inference.vv │ │ │ ├── generic_type_name_in_non_generic_function.out │ │ │ ├── generic_type_name_in_non_generic_function.vv │ │ │ ├── generics_field_struct_arr_err.out │ │ │ ├── generics_field_struct_arr_err.vv │ │ │ ├── generics_fn_arg_type_err.out │ │ │ ├── generics_fn_arg_type_err.vv │ │ │ ├── generics_fn_arguments_count_err.out │ │ │ ├── generics_fn_arguments_count_err.vv │ │ │ ├── generics_fn_called_arg_mismatch.out │ │ │ ├── generics_fn_called_arg_mismatch.vv │ │ │ ├── generics_fn_called_fntype_arg_mismatch.out │ │ │ ├── generics_fn_called_fntype_arg_mismatch.vv │ │ │ ├── generics_fn_called_multi_args_mismatch.out │ │ │ ├── generics_fn_called_multi_args_mismatch.vv │ │ │ ├── generics_fn_called_no_arg_err.out │ │ │ ├── generics_fn_called_no_arg_err.vv │ │ │ ├── generics_fn_called_outside_of_generic_fn.out │ │ │ ├── generics_fn_called_outside_of_generic_fn.vv │ │ │ ├── generics_fn_called_variadic_arg_mismatch.out │ │ │ ├── generics_fn_called_variadic_arg_mismatch.vv │ │ │ ├── generics_fn_param_wrong_arg_type_err.out │ │ │ ├── generics_fn_param_wrong_arg_type_err.vv │ │ │ ├── generics_fn_return_generic_closure_err.out │ │ │ ├── generics_fn_return_generic_closure_err.vv │ │ │ ├── generics_fn_return_generic_struct_err.out │ │ │ ├── generics_fn_return_generic_struct_err.vv │ │ │ ├── generics_inst_non_generic_struct_err.out │ │ │ ├── generics_inst_non_generic_struct_err.vv │ │ │ ├── generics_interface_decl_no_mention_err.out │ │ │ ├── generics_interface_decl_no_mention_err.vv │ │ │ ├── generics_interface_declaration_err.out │ │ │ ├── generics_interface_declaration_err.vv │ │ │ ├── generics_interface_field_type_err.out │ │ │ ├── generics_interface_field_type_err.vv │ │ │ ├── generics_method_arg_type_err.out │ │ │ ├── generics_method_arg_type_err.vv │ │ │ ├── generics_method_called_arg_mismatch.out │ │ │ ├── generics_method_called_arg_mismatch.vv │ │ │ ├── generics_method_called_variadic_arg_mismatch.out │ │ │ ├── generics_method_called_variadic_arg_mismatch.vv │ │ │ ├── generics_method_receiver_type_err_a.out │ │ │ ├── generics_method_receiver_type_err_a.vv │ │ │ ├── generics_method_receiver_type_err_b.out │ │ │ ├── generics_method_receiver_type_err_b.vv │ │ │ ├── generics_method_sumtype_arg_mismatch.out │ │ │ ├── generics_method_sumtype_arg_mismatch.vv │ │ │ ├── generics_non_generic_fn_called_like_a_generic_one.out │ │ │ ├── generics_non_generic_fn_called_like_a_generic_one.vv │ │ │ ├── generics_non_generic_struct_used_like_a_generic_one.out │ │ │ ├── generics_non_generic_struct_used_like_a_generic_one.vv │ │ │ ├── generics_struct_decl_no_mention_err.out │ │ │ ├── generics_struct_decl_no_mention_err.vv │ │ │ ├── generics_struct_declaration_err.out │ │ │ ├── generics_struct_declaration_err.vv │ │ │ ├── generics_struct_field_fn_args_err.out │ │ │ ├── generics_struct_field_fn_args_err.vv │ │ │ ├── generics_struct_field_type_err.out │ │ │ ├── generics_struct_field_type_err.vv │ │ │ ├── generics_struct_in_non_generic_fn_err.out │ │ │ ├── generics_struct_in_non_generic_fn_err.vv │ │ │ ├── generics_struct_infer_err.out │ │ │ ├── generics_struct_infer_err.vv │ │ │ ├── generics_struct_init_err.out │ │ │ ├── generics_struct_init_err.vv │ │ │ ├── generics_struct_init_type_parameter_err.out │ │ │ ├── generics_struct_init_type_parameter_err.vv │ │ │ ├── generics_struct_init_with_inconsistent_generic_types_3_err.out │ │ │ ├── generics_struct_init_with_inconsistent_generic_types_3_err.vv │ │ │ ├── generics_struct_nokeys_init_err.out │ │ │ ├── generics_struct_nokeys_init_err.vv │ │ │ ├── generics_struct_type_mismatch_err.out │ │ │ ├── generics_struct_type_mismatch_err.vv │ │ │ ├── generics_too_many_parameters.out │ │ │ ├── generics_too_many_parameters.vv │ │ │ ├── generics_type_ambiguous.out │ │ │ ├── generics_type_ambiguous.vv │ │ │ ├── generics_undefined_operation.out │ │ │ ├── generics_undefined_operation.vv │ │ │ ├── generics_undefined_operation_2.out │ │ │ ├── generics_undefined_operation_2.vv │ │ │ ├── globals/ │ │ │ │ ├── assign_global_to_shared_err.out │ │ │ │ ├── assign_global_to_shared_err.vv │ │ │ │ ├── assign_no_value.out │ │ │ │ ├── assign_no_value.vv │ │ │ │ ├── cast_expr_T_type_err.out │ │ │ │ ├── cast_expr_T_type_err.vv │ │ │ │ ├── closure_capture_global_var.out │ │ │ │ ├── closure_capture_global_var.vv │ │ │ │ ├── global_anon_fn_without_body.out │ │ │ │ ├── global_anon_fn_without_body.vv │ │ │ │ ├── global_blank_ident_as_name_err.out │ │ │ │ ├── global_blank_ident_as_name_err.vv │ │ │ │ ├── global_receiver_var_name_err.out │ │ │ │ ├── global_receiver_var_name_err.vv │ │ │ │ ├── global_var_redeclare.out │ │ │ │ ├── global_var_redeclare.vv │ │ │ │ ├── incorrect_name_global.out │ │ │ │ ├── incorrect_name_global.vv │ │ │ │ ├── name_conflict_with_const.out │ │ │ │ ├── name_conflict_with_const.vv │ │ │ │ ├── nested_unknown_typ.out │ │ │ │ ├── nested_unknown_typ.vv │ │ │ │ ├── no_type.out │ │ │ │ ├── no_type.vv │ │ │ │ ├── redefine_main.out │ │ │ │ ├── redefine_main.vv │ │ │ │ ├── unexpected_eof.out │ │ │ │ ├── unexpected_eof.vv │ │ │ │ ├── unknown_typ.out │ │ │ │ └── unknown_typ.vv │ │ │ ├── globals_error.out │ │ │ ├── globals_error.run.out │ │ │ ├── globals_error.vv │ │ │ ├── globals_run/ │ │ │ │ ├── function_stored_in_global.run.out │ │ │ │ ├── function_stored_in_global.vv │ │ │ │ ├── global_array_indexed_by_global_fn.run.out │ │ │ │ ├── global_array_indexed_by_global_fn.vv │ │ │ │ ├── global_fixed_array_initialisation.run.out │ │ │ │ ├── global_fixed_array_initialisation.vv │ │ │ │ ├── global_nested_struct_test.run.out │ │ │ │ ├── global_nested_struct_test.vv │ │ │ │ ├── global_var_in_anon_fn.run.out │ │ │ │ └── global_var_in_anon_fn.vv │ │ │ ├── go_append_option_to_threads_err.out │ │ │ ├── go_append_option_to_threads_err.vv │ │ │ ├── go_expr.out │ │ │ ├── go_expr.vv │ │ │ ├── go_mut_arg.out │ │ │ ├── go_mut_arg.vv │ │ │ ├── go_mut_receiver.out │ │ │ ├── go_mut_receiver.vv │ │ │ ├── go_wait_or.out │ │ │ ├── go_wait_or.vv │ │ │ ├── goto_label.out │ │ │ ├── goto_label.vv │ │ │ ├── hex_lit_without_digit_err.out │ │ │ ├── hex_lit_without_digit_err.vv │ │ │ ├── hex_lit_wrong_digit_err.out │ │ │ ├── hex_lit_wrong_digit_err.vv │ │ │ ├── hex_literal_overflow.out │ │ │ ├── hex_literal_overflow.vv │ │ │ ├── i64_to_f64_implicit_cast_err.out │ │ │ ├── i64_to_f64_implicit_cast_err.vv │ │ │ ├── ierror_in_return_tuple.out │ │ │ ├── ierror_in_return_tuple.vv │ │ │ ├── if_diff_expected_type_err.out │ │ │ ├── if_diff_expected_type_err.vv │ │ │ ├── if_expr_last_branch_stmt_err.out │ │ │ ├── if_expr_last_branch_stmt_err.vv │ │ │ ├── if_expr_last_stmt.out │ │ │ ├── if_expr_last_stmt.vv │ │ │ ├── if_expr_mismatch.out │ │ │ ├── if_expr_mismatch.vv │ │ │ ├── if_expr_no_else.out │ │ │ ├── if_expr_no_else.vv │ │ │ ├── if_expr_option_err.out │ │ │ ├── if_expr_option_err.vv │ │ │ ├── if_expr_result_err.out │ │ │ ├── if_expr_result_err.vv │ │ │ ├── if_expr_with_none_only.out │ │ │ ├── if_expr_with_none_only.vv │ │ │ ├── if_guard_expr_err.out │ │ │ ├── if_guard_expr_err.vv │ │ │ ├── if_guard_variables_err.out │ │ │ ├── if_guard_variables_err.vv │ │ │ ├── if_match_expr_err.out │ │ │ ├── if_match_expr_err.vv │ │ │ ├── if_match_result.out │ │ │ ├── if_match_result.vv │ │ │ ├── if_mismatch_muls_err.out │ │ │ ├── if_mismatch_muls_err.vv │ │ │ ├── if_mismatch_option_err.out │ │ │ ├── if_mismatch_option_err.vv │ │ │ ├── if_mut_with_immutable_var_err.out │ │ │ ├── if_mut_with_immutable_var_err.vv │ │ │ ├── if_non_bool_cond.out │ │ │ ├── if_non_bool_cond.vv │ │ │ ├── if_smartcast_mut_var_interface_err.out │ │ │ ├── if_smartcast_mut_var_interface_err.vv │ │ │ ├── immutable_arg.out │ │ │ ├── immutable_arg.vv │ │ │ ├── immutable_array_field_assign.out │ │ │ ├── immutable_array_field_assign.vv │ │ │ ├── immutable_array_field_shift.out │ │ │ ├── immutable_array_field_shift.vv │ │ │ ├── immutable_array_in_if_expr_index.out │ │ │ ├── immutable_array_in_if_expr_index.vv │ │ │ ├── immutable_array_struct_assign.out │ │ │ ├── immutable_array_struct_assign.vv │ │ │ ├── immutable_array_struct_shift.out │ │ │ ├── immutable_array_struct_shift.vv │ │ │ ├── immutable_array_var.out │ │ │ ├── immutable_array_var.vv │ │ │ ├── immutable_builtin_modify.out │ │ │ ├── immutable_builtin_modify.vv │ │ │ ├── immutable_deref.out │ │ │ ├── immutable_deref.vv │ │ │ ├── immutable_field.out │ │ │ ├── immutable_field.vv │ │ │ ├── immutable_field_postfix.out │ │ │ ├── immutable_field_postfix.vv │ │ │ ├── immutable_interface_field.out │ │ │ ├── immutable_interface_field.vv │ │ │ ├── immutable_map.out │ │ │ ├── immutable_map.vv │ │ │ ├── immutable_rec.out │ │ │ ├── immutable_rec.vv │ │ │ ├── immutable_struct_postfix.out │ │ │ ├── immutable_struct_postfix.vv │ │ │ ├── immutable_to_mutable_err.out │ │ │ ├── immutable_to_mutable_err.vv │ │ │ ├── immutable_var.out │ │ │ ├── immutable_var.vv │ │ │ ├── immutable_var_postfix.out │ │ │ ├── immutable_var_postfix.vv │ │ │ ├── implements_generic_err.out │ │ │ ├── implements_generic_err.vv │ │ │ ├── implements_keyword.out │ │ │ ├── implements_keyword.vv │ │ │ ├── import_duplicate_err.out │ │ │ ├── import_duplicate_err.vv │ │ │ ├── import_middle_err.out │ │ │ ├── import_middle_err.vv │ │ │ ├── import_mod_as_duplicate_err.out │ │ │ ├── import_mod_as_duplicate_err.vv │ │ │ ├── import_mod_as_import_alias_duplicate_err.out │ │ │ ├── import_mod_as_import_alias_duplicate_err.vv │ │ │ ├── import_mod_as_import_duplicate_err.out │ │ │ ├── import_mod_as_import_duplicate_err.vv │ │ │ ├── import_mod_as_mod_err.out │ │ │ ├── import_mod_as_mod_err.vv │ │ │ ├── import_mod_duplicate_as_alias_err.out │ │ │ ├── import_mod_duplicate_as_alias_err.vv │ │ │ ├── import_mod_duplicate_err.out │ │ │ ├── import_mod_duplicate_err.vv │ │ │ ├── import_mod_sub_as_duplicate_err.out │ │ │ ├── import_mod_sub_as_duplicate_err.vv │ │ │ ├── import_mod_sub_as_sub_err.out │ │ │ ├── import_mod_sub_as_sub_err.vv │ │ │ ├── import_mod_sub_duplicate_as_mod.out │ │ │ ├── import_mod_sub_duplicate_as_mod.vv │ │ │ ├── import_mod_sub_duplicate_err.out │ │ │ ├── import_mod_sub_duplicate_err.vv │ │ │ ├── import_multiple_modules_err.out │ │ │ ├── import_multiple_modules_err.vv │ │ │ ├── import_not_found_err.out │ │ │ ├── import_not_found_err.vv │ │ │ ├── import_not_same_line_err.out │ │ │ ├── import_not_same_line_err.vv │ │ │ ├── import_sym_builtin_override_err.out │ │ │ ├── import_sym_builtin_override_err.vv │ │ │ ├── import_symbol_empty.out │ │ │ ├── import_symbol_empty.vv │ │ │ ├── import_symbol_fn_err.out │ │ │ ├── import_symbol_fn_err.vv │ │ │ ├── import_symbol_invalid.out │ │ │ ├── import_symbol_invalid.vv │ │ │ ├── import_symbol_private_err.out │ │ │ ├── import_symbol_private_err.vv │ │ │ ├── import_symbol_type_err.out │ │ │ ├── import_symbol_type_err.vv │ │ │ ├── import_symbol_unclosed.out │ │ │ ├── import_symbol_unclosed.vv │ │ │ ├── import_syntax_err.out │ │ │ ├── import_syntax_err.vv │ │ │ ├── import_unused_warning.out │ │ │ ├── import_unused_warning.vv │ │ │ ├── in_mismatch_type.out │ │ │ ├── in_mismatch_type.vv │ │ │ ├── in_range_expr_err.out │ │ │ ├── in_range_expr_err.vv │ │ │ ├── inc_dec_fun_call.out │ │ │ ├── inc_dec_fun_call.vv │ │ │ ├── inc_num_literal.out │ │ │ ├── inc_num_literal.vv │ │ │ ├── inc_ok.out │ │ │ ├── inc_ok.vv │ │ │ ├── inc_paren_expr.out │ │ │ ├── inc_paren_expr.vv │ │ │ ├── incorrect_for_in_name_variable.out │ │ │ ├── incorrect_for_in_name_variable.vv │ │ │ ├── incorrect_name_alias_type.out │ │ │ ├── incorrect_name_alias_type.vv │ │ │ ├── incorrect_name_const.out │ │ │ ├── incorrect_name_const.vv │ │ │ ├── incorrect_name_enum.out │ │ │ ├── incorrect_name_enum.vv │ │ │ ├── incorrect_name_enum_field.out │ │ │ ├── incorrect_name_enum_field.vv │ │ │ ├── incorrect_name_fn_type.out │ │ │ ├── incorrect_name_fn_type.vv │ │ │ ├── incorrect_name_function.out │ │ │ ├── incorrect_name_function.vv │ │ │ ├── incorrect_name_interface.out │ │ │ ├── incorrect_name_interface.vv │ │ │ ├── incorrect_name_interface_method.out │ │ │ ├── incorrect_name_interface_method.vv │ │ │ ├── incorrect_name_module.out │ │ │ ├── incorrect_name_module.vv │ │ │ ├── incorrect_name_struct.out │ │ │ ├── incorrect_name_struct.vv │ │ │ ├── incorrect_name_struct_field.out │ │ │ ├── incorrect_name_struct_field.vv │ │ │ ├── incorrect_name_sum_type.out │ │ │ ├── incorrect_name_sum_type.vv │ │ │ ├── incorrect_name_variable.out │ │ │ ├── incorrect_name_variable.vv │ │ │ ├── incorrect_smartcast2_err.out │ │ │ ├── incorrect_smartcast2_err.vv │ │ │ ├── incorrect_smartcast3_err.out │ │ │ ├── incorrect_smartcast3_err.vv │ │ │ ├── incorrect_smartcast_err.out │ │ │ ├── incorrect_smartcast_err.vv │ │ │ ├── index_expr.out │ │ │ ├── index_expr.vv │ │ │ ├── index_invalid_call.out │ │ │ ├── index_invalid_call.vv │ │ │ ├── index_of_option_err.out │ │ │ ├── index_of_option_err.vv │ │ │ ├── index_sumtype_interface_struct_params_err.out │ │ │ ├── index_sumtype_interface_struct_params_err.vv │ │ │ ├── infix_and_op_expr_err.out │ │ │ ├── infix_and_op_expr_err.vv │ │ │ ├── infix_compare_option_err.out │ │ │ ├── infix_compare_option_err.vv │ │ │ ├── infix_dup_in_err.out │ │ │ ├── infix_dup_in_err.vv │ │ │ ├── infix_err.out │ │ │ ├── infix_err.vv │ │ │ ├── infix_expr_left_side_assogn_err.out │ │ │ ├── infix_expr_left_side_assogn_err.vv │ │ │ ├── infix_is_notis_interface_unimplemented_err.out │ │ │ ├── infix_is_notis_interface_unimplemented_err.vv │ │ │ ├── infix_is_unknown_module_no_panic.out │ │ │ ├── infix_is_unknown_module_no_panic.vv │ │ │ ├── infix_sumtype_in_array_err.out │ │ │ ├── infix_sumtype_in_array_err.vv │ │ │ ├── inner_functions_call_before_define.out │ │ │ ├── inner_functions_call_before_define.vv │ │ │ ├── int_modulo_by_zero_err.out │ │ │ ├── int_modulo_by_zero_err.vv │ │ │ ├── int_ptr_array_index_err.out │ │ │ ├── int_ptr_array_index_err.vv │ │ │ ├── int_signess_call_arg_test.out │ │ │ ├── int_signess_call_arg_test.vv │ │ │ ├── interface_field_name_err.out │ │ │ ├── interface_field_name_err.vv │ │ │ ├── interface_generic_err.out │ │ │ ├── interface_generic_err.vv │ │ │ ├── interface_implemented_by_function.out │ │ │ ├── interface_implemented_by_function.vv │ │ │ ├── interface_implementing_interface.out │ │ │ ├── interface_implementing_interface.vv │ │ │ ├── interface_implementing_own_interface_method.out │ │ │ ├── interface_implementing_own_interface_method.vv │ │ │ ├── interface_init_err.out │ │ │ ├── interface_init_err.vv │ │ │ ├── interface_method_name_err.out │ │ │ ├── interface_method_name_err.vv │ │ │ ├── interface_option_cast_err.out │ │ │ ├── interface_option_cast_err.vv │ │ │ ├── interface_return_parameter_err.out │ │ │ ├── interface_return_parameter_err.vv │ │ │ ├── interface_sameness_check_for_mutable_methods.out │ │ │ ├── interface_sameness_check_for_mutable_methods.vv │ │ │ ├── interface_too_many_embedding_levels.out │ │ │ ├── interface_too_many_embedding_levels.vv │ │ │ ├── interpolation_recursive_str_err.out │ │ │ ├── interpolation_recursive_str_err.vv │ │ │ ├── invalid_alias_ptr_cast_on_map_err.out │ │ │ ├── invalid_alias_ptr_cast_on_map_err.vv │ │ │ ├── invalid_char_err.out │ │ │ ├── invalid_char_err.vv │ │ │ ├── invalid_comptime_test.out │ │ │ ├── invalid_comptime_test.vv │ │ │ ├── invalid_const_expr_match_range_err.out │ │ │ ├── invalid_const_expr_match_range_err.vv │ │ │ ├── invalid_defer_mode_err.out │ │ │ ├── invalid_defer_mode_err.vv │ │ │ ├── invalid_generic_field_err.out │ │ │ ├── invalid_generic_field_err.vv │ │ │ ├── invalid_insert_references_test.out │ │ │ ├── invalid_insert_references_test.vv │ │ │ ├── invalid_literal_assign_err.out │ │ │ ├── invalid_literal_assign_err.vv │ │ │ ├── invalid_mismatch_for_range_type_err.out │ │ │ ├── invalid_mismatch_for_range_type_err.vv │ │ │ ├── invalid_multi_return_operations_err.out │ │ │ ├── invalid_multi_return_operations_err.vv │ │ │ ├── invalid_mut.out │ │ │ ├── invalid_mut.vv │ │ │ ├── invalid_nilref_err.out │ │ │ ├── invalid_nilref_err.vv │ │ │ ├── invalid_none_operations_err.out │ │ │ ├── invalid_none_operations_err.vv │ │ │ ├── invalid_op_ptr_err.out │ │ │ ├── invalid_op_ptr_err.vv │ │ │ ├── invalid_parameter_name_err.out │ │ │ ├── invalid_parameter_name_err.vv │ │ │ ├── invalid_prefix_left_side_assign_stmt_err.out │ │ │ ├── invalid_prefix_left_side_assign_stmt_err.vv │ │ │ ├── invalid_property.out │ │ │ ├── invalid_property.vv │ │ │ ├── invalid_recursive_struct_err.out │ │ │ ├── invalid_recursive_struct_err.vv │ │ │ ├── invalid_string_cast_to_pointers_err.out │ │ │ ├── invalid_string_cast_to_pointers_err.vv │ │ │ ├── invalid_utf8_string.out │ │ │ ├── invalid_utf8_string.vv │ │ │ ├── invalid_variable_err.out │ │ │ ├── invalid_variable_err.vv │ │ │ ├── invalid_variable_name_err.out │ │ │ ├── invalid_variable_name_err.vv │ │ │ ├── invalid_vweb_param_type.out │ │ │ ├── invalid_vweb_param_type.vv │ │ │ ├── invert_other_types_bits_error.out │ │ │ ├── invert_other_types_bits_error.vv │ │ │ ├── is_type_invalid.out │ │ │ ├── is_type_invalid.vv │ │ │ ├── is_type_not_exist.out │ │ │ ├── is_type_not_exist.vv │ │ │ ├── js_with_non_js_backend_too_many_arguments.out │ │ │ ├── js_with_non_js_backend_too_many_arguments.vv │ │ │ ├── json_decode.out │ │ │ ├── json_decode.vv │ │ │ ├── json_decode_shared_err.out │ │ │ ├── json_decode_shared_err.vv │ │ │ ├── labelled_break_continue.out │ │ │ ├── labelled_break_continue.vv │ │ │ ├── lambda_expression_in_map.out │ │ │ ├── lambda_expression_in_map.vv │ │ │ ├── lambda_expression_invalid.out │ │ │ ├── lambda_expression_invalid.vv │ │ │ ├── lambda_or_block_err.out │ │ │ ├── lambda_or_block_err.vv │ │ │ ├── lambda_undefined_variables_err.out │ │ │ ├── lambda_undefined_variables_err.vv │ │ │ ├── like_operator_outside_orm_1_error.out │ │ │ ├── like_operator_outside_orm_1_error.vv │ │ │ ├── like_operator_outside_orm_2_error.out │ │ │ ├── like_operator_outside_orm_2_error.vv │ │ │ ├── like_operator_with_non_string_type_error.out │ │ │ ├── like_operator_with_non_string_type_error.vv │ │ │ ├── lock_already_locked.out │ │ │ ├── lock_already_locked.vv │ │ │ ├── lock_already_rlocked.out │ │ │ ├── lock_already_rlocked.vv │ │ │ ├── lock_const.out │ │ │ ├── lock_const.vv │ │ │ ├── lock_needed.out │ │ │ ├── lock_needed.vv │ │ │ ├── lock_nonshared.out │ │ │ ├── lock_nonshared.vv │ │ │ ├── lockexpr_missing_return_err.out │ │ │ ├── lockexpr_missing_return_err.vv │ │ │ ├── main_args_err.out │ │ │ ├── main_args_err.vv │ │ │ ├── main_called_err.out │ │ │ ├── main_called_err.vv │ │ │ ├── main_no_body_err.out │ │ │ ├── main_no_body_err.vv │ │ │ ├── main_return_err.out │ │ │ ├── main_return_err.vv │ │ │ ├── map_builtin_method_args_err.out │ │ │ ├── map_builtin_method_args_err.vv │ │ │ ├── map_def_err.out │ │ │ ├── map_def_err.vv │ │ │ ├── map_delete.out │ │ │ ├── map_delete.vv │ │ │ ├── map_func_return_multiple_values_err.out │ │ │ ├── map_func_return_multiple_values_err.vv │ │ │ ├── map_func_void_return_err.out │ │ │ ├── map_func_void_return_err.vv │ │ │ ├── map_index_or_block_type_mismatch_err.out │ │ │ ├── map_index_or_block_type_mismatch_err.vv │ │ │ ├── map_index_reference_value.out │ │ │ ├── map_index_reference_value.vv │ │ │ ├── map_init_invalid_syntax.out │ │ │ ├── map_init_invalid_syntax.vv │ │ │ ├── map_init_invalid_update.out │ │ │ ├── map_init_invalid_update.vv │ │ │ ├── map_init_key_duplicate_err.out │ │ │ ├── map_init_key_duplicate_err.vv │ │ │ ├── map_init_wrong_expected_type.out │ │ │ ├── map_init_wrong_expected_type.vv │ │ │ ├── map_init_wrong_type.out │ │ │ ├── map_init_wrong_type.vv │ │ │ ├── map_init_wrong_update_type.out │ │ │ ├── map_init_wrong_update_type.vv │ │ │ ├── map_key_val_or_not_progagate_err.out │ │ │ ├── map_key_val_or_not_progagate_err.vv │ │ │ ├── map_lambda_void_return_err.out │ │ │ ├── map_lambda_void_return_err.vv │ │ │ ├── map_of_generic_struct_init_err.out │ │ │ ├── map_of_generic_struct_init_err.vv │ │ │ ├── map_ops.out │ │ │ ├── map_ops.vv │ │ │ ├── map_repeated_float_key_err.out │ │ │ ├── map_repeated_float_key_err.vv │ │ │ ├── map_result_callback_fn_err.out │ │ │ ├── map_result_callback_fn_err.vv │ │ │ ├── map_unknown_value.out │ │ │ ├── map_unknown_value.vv │ │ │ ├── map_with_none_err.out │ │ │ ├── map_with_none_err.vv │ │ │ ├── map_with_result_value_err.out │ │ │ ├── map_with_result_value_err.vv │ │ │ ├── match_alias_type_err.out │ │ │ ├── match_alias_type_err.vv │ │ │ ├── match_branch_call_expr_arg_mismatch.out │ │ │ ├── match_branch_call_expr_arg_mismatch.vv │ │ │ ├── match_cast_cond_not_same_range_cast_type_err.out │ │ │ ├── match_cast_cond_not_same_range_cast_type_err.vv │ │ │ ├── match_cond_with_parenthesis_err.out │ │ │ ├── match_cond_with_parenthesis_err.vv │ │ │ ├── match_duplicate_branch.out │ │ │ ├── match_duplicate_branch.vv │ │ │ ├── match_else_last_expr.out │ │ │ ├── match_else_last_expr.vv │ │ │ ├── match_enum_ref.out │ │ │ ├── match_enum_ref.vv │ │ │ ├── match_expr_and_expected_type_error.out │ │ │ ├── match_expr_and_expected_type_error.vv │ │ │ ├── match_expr_else.out │ │ │ ├── match_expr_else.vv │ │ │ ├── match_expr_empty_branch.out │ │ │ ├── match_expr_empty_branch.vv │ │ │ ├── match_expr_range_low_higher_than_high.out │ │ │ ├── match_expr_range_low_higher_than_high.vv │ │ │ ├── match_expr_with_none_only.out │ │ │ ├── match_expr_with_none_only.vv │ │ │ ├── match_generic_case_err.out │ │ │ ├── match_generic_case_err.vv │ │ │ ├── match_incorrect_cast_branch_err.out │ │ │ ├── match_incorrect_cast_branch_err.vv │ │ │ ├── match_invalid_type.out │ │ │ ├── match_invalid_type.vv │ │ │ ├── match_last_branch_only_casted.out │ │ │ ├── match_last_branch_only_casted.vv │ │ │ ├── match_missing.out │ │ │ ├── match_missing.vv │ │ │ ├── match_mut_with_immutable_var_err.out │ │ │ ├── match_mut_with_immutable_var_err.vv │ │ │ ├── match_no_branch_cast_rest_casted_err.out │ │ │ ├── match_no_branch_cast_rest_casted_err.vv │ │ │ ├── match_option_without_none_err.out │ │ │ ├── match_option_without_none_err.vv │ │ │ ├── match_range_mismatch_type_err.out │ │ │ ├── match_range_mismatch_type_err.vv │ │ │ ├── match_ranges_not_same_cast_err.out │ │ │ ├── match_ranges_not_same_cast_err.vv │ │ │ ├── match_return_mismatch_type_err.out │ │ │ ├── match_return_mismatch_type_err.vv │ │ │ ├── match_return_sumtype_mismatch_err.out │ │ │ ├── match_return_sumtype_mismatch_err.vv │ │ │ ├── match_sumtype_multiple_types.out │ │ │ ├── match_sumtype_multiple_types.vv │ │ │ ├── match_type_node_with_non_sum_type_err.out │ │ │ ├── match_type_node_with_non_sum_type_err.vv │ │ │ ├── match_undefined_cond.out │ │ │ ├── match_undefined_cond.vv │ │ │ ├── method_array_slice.out │ │ │ ├── method_array_slice.vv │ │ │ ├── method_call_arg_mismatch.out │ │ │ ├── method_call_arg_mismatch.vv │ │ │ ├── method_call_arg_no_mut_err.out │ │ │ ├── method_call_arg_no_mut_err.vv │ │ │ ├── method_call_on_undefined_err.out │ │ │ ├── method_call_on_undefined_err.vv │ │ │ ├── method_call_with_empty_struct_init.out │ │ │ ├── method_call_with_empty_struct_init.vv │ │ │ ├── method_generic_infer_err.out │ │ │ ├── method_generic_infer_err.vv │ │ │ ├── method_op_alias_err.out │ │ │ ├── method_op_alias_err.vv │ │ │ ├── method_op_err.out │ │ │ ├── method_op_err.vv │ │ │ ├── method_ptr_used_as_argument_err.out │ │ │ ├── method_ptr_used_as_argument_err.vv │ │ │ ├── method_wrong_arg_type.out │ │ │ ├── method_wrong_arg_type.vv │ │ │ ├── minus_op_wrong_type_err.out │ │ │ ├── minus_op_wrong_type_err.vv │ │ │ ├── mismatch_bool_assign_err.out │ │ │ ├── mismatch_bool_assign_err.vv │ │ │ ├── mismatched_ptr_op_ptr.out │ │ │ ├── mismatched_ptr_op_ptr.vv │ │ │ ├── missing_c_lib_header_1.out │ │ │ ├── missing_c_lib_header_1.vv │ │ │ ├── missing_c_lib_header_with_explanation_2.out │ │ │ ├── missing_c_lib_header_with_explanation_2.vv │ │ │ ├── missing_concrete_type_err.out │ │ │ ├── missing_concrete_type_err.vv │ │ │ ├── missing_export_attr_arg_err.out │ │ │ ├── missing_export_attr_arg_err.vv │ │ │ ├── misspelled_mod_const_should_have_suggestion.out │ │ │ ├── misspelled_mod_const_should_have_suggestion.vv │ │ │ ├── misspelled_mod_fn_name_should_have_suggestion.out │ │ │ ├── misspelled_mod_fn_name_should_have_suggestion.vv │ │ │ ├── mod_name_duplicate_const_err.out │ │ │ ├── mod_name_duplicate_const_err.vv │ │ │ ├── mod_name_duplicate_param_err.out │ │ │ ├── mod_name_duplicate_param_err.vv │ │ │ ├── mod_name_duplicate_var_err.out │ │ │ ├── mod_name_duplicate_var_err.vv │ │ │ ├── mod_op_wrong_type_err.out │ │ │ ├── mod_op_wrong_type_err.vv │ │ │ ├── module_not_at_same_line_err.out │ │ │ ├── module_not_at_same_line_err.vv │ │ │ ├── module_selector_decl_assign_err.out │ │ │ ├── module_selector_decl_assign_err.vv │ │ │ ├── module_with_deprecated_structs/ │ │ │ │ └── module.v │ │ │ ├── modules/ │ │ │ │ ├── anon_fn_name_across_files/ │ │ │ │ │ ├── a.v │ │ │ │ │ ├── b.v │ │ │ │ │ └── main.v │ │ │ │ ├── anon_fn_name_across_files.out │ │ │ │ ├── deprecated_consts/ │ │ │ │ │ └── consts.v │ │ │ │ ├── deprecated_consts.out │ │ │ │ ├── deprecated_module/ │ │ │ │ │ ├── bbb/ │ │ │ │ │ │ └── ccc/ │ │ │ │ │ │ └── ccc.v │ │ │ │ │ ├── main.v │ │ │ │ │ ├── v.mod │ │ │ │ │ ├── www/ │ │ │ │ │ │ └── ttt/ │ │ │ │ │ │ └── ttt.v │ │ │ │ │ └── xxx/ │ │ │ │ │ └── yyy/ │ │ │ │ │ └── yyy.v │ │ │ │ ├── deprecated_module.out │ │ │ │ ├── embedded_private_method_visibility/ │ │ │ │ │ ├── drawlib.v │ │ │ │ │ └── main.v │ │ │ │ ├── embedded_private_method_visibility.out │ │ │ │ ├── enum_from_string_in_different_mods/ │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── main.v │ │ │ │ │ │ └── mod.v │ │ │ │ │ └── v.mod │ │ │ │ ├── enum_from_string_in_different_mods.out │ │ │ │ ├── implement_private_interface/ │ │ │ │ │ ├── baz.v │ │ │ │ │ └── main.v │ │ │ │ ├── implement_private_interface.out │ │ │ │ ├── module_alias_started_with_underscore/ │ │ │ │ │ ├── main.v │ │ │ │ │ └── underscore.v │ │ │ │ ├── module_alias_started_with_underscore.out │ │ │ │ ├── module_struct_noinit/ │ │ │ │ │ └── src/ │ │ │ │ │ ├── main.v │ │ │ │ │ └── mod.v │ │ │ │ ├── module_struct_noinit.out │ │ │ │ ├── module_with_redeclaration/ │ │ │ │ │ ├── redeclare_time_structs.c.v │ │ │ │ │ └── v.mod │ │ │ │ ├── module_with_redeclaration.out │ │ │ │ ├── overload_return_type/ │ │ │ │ │ ├── main.v │ │ │ │ │ └── point.v │ │ │ │ ├── overload_return_type.out │ │ │ │ ├── private_symbol/ │ │ │ │ │ ├── main.v │ │ │ │ │ └── priv_sym.v │ │ │ │ └── private_symbol.out │ │ │ ├── mul_op_wrong_type_err.out │ │ │ ├── mul_op_wrong_type_err.vv │ │ │ ├── multi_const_field_name_duplicate_err.out │ │ │ ├── multi_const_field_name_duplicate_err.vv │ │ │ ├── multi_names_err.out │ │ │ ├── multi_names_err.vv │ │ │ ├── multi_return_arg_missing_err.out │ │ │ ├── multi_return_arg_missing_err.vv │ │ │ ├── multi_return_err.out │ │ │ ├── multi_return_err.vv │ │ │ ├── multi_return_use_void_type_err.out │ │ │ ├── multi_return_use_void_type_err.vv │ │ │ ├── multi_value_method_err.out │ │ │ ├── multi_value_method_err.vv │ │ │ ├── multiple_pointer_yield_err.out │ │ │ ├── multiple_pointer_yield_err.vv │ │ │ ├── multireturn_mix_err.out │ │ │ ├── multireturn_mix_err.vv │ │ │ ├── must_use.out │ │ │ ├── must_use.vv │ │ │ ├── mut_arg.out │ │ │ ├── mut_arg.vv │ │ │ ├── mut_arg_different_muls_err.out │ │ │ ├── mut_arg_different_muls_err.vv │ │ │ ├── mut_array_get_element_address_err.out │ │ │ ├── mut_array_get_element_address_err.vv │ │ │ ├── mut_assign_ref.out │ │ │ ├── mut_assign_ref.vv │ │ │ ├── mut_int.out │ │ │ ├── mut_int.vv │ │ │ ├── mut_interface_param_err.out │ │ │ ├── mut_interface_param_err.vv │ │ │ ├── mut_map_get_value_address_err.out │ │ │ ├── mut_map_get_value_address_err.vv │ │ │ ├── mut_parms_struct_param_err.out │ │ │ ├── mut_parms_struct_param_err.vv │ │ │ ├── mut_receiver.out │ │ │ ├── mut_receiver.vv │ │ │ ├── mut_receiver_lit.out │ │ │ ├── mut_receiver_lit.vv │ │ │ ├── mut_receiver_wrong_return_type.out │ │ │ ├── mut_receiver_wrong_return_type.vv │ │ │ ├── negative_assign_to_unsigned.out │ │ │ ├── negative_assign_to_unsigned.vv │ │ │ ├── nested_aliases.out │ │ │ ├── nested_aliases.vv │ │ │ ├── nested_fn_alias_err.out │ │ │ ├── nested_fn_alias_err.vv │ │ │ ├── nested_struct_with_required_attr_err.out │ │ │ ├── nested_struct_with_required_attr_err.vv │ │ │ ├── nil.out │ │ │ ├── nil.vv │ │ │ ├── nil_compare_err.out │ │ │ ├── nil_compare_err.vv │ │ │ ├── nil_to_option_err.out │ │ │ ├── nil_to_option_err.vv │ │ │ ├── no_arrays_of_references_in_translated.out │ │ │ ├── no_arrays_of_references_in_translated.vv │ │ │ ├── no_assign_0_to_a_reference_field_notice_in_translated.out │ │ │ ├── no_assign_0_to_a_reference_field_notice_in_translated.vv │ │ │ ├── no_cannot_cast_a_fixed_array_in_translated.out │ │ │ ├── no_cannot_cast_a_fixed_array_in_translated.vv │ │ │ ├── no_function_must_be_called_from_unsafe_in_translated.out │ │ │ ├── no_function_must_be_called_from_unsafe_in_translated.vv │ │ │ ├── no_goto_requires_unsafe_in_translated.out │ │ │ ├── no_goto_requires_unsafe_in_translated.vv │ │ │ ├── no_heap_struct.out │ │ │ ├── no_heap_struct.vv │ │ │ ├── no_interface_instantiation_a.out │ │ │ ├── no_interface_instantiation_a.vv │ │ │ ├── no_interface_instantiation_b.out │ │ │ ├── no_interface_instantiation_b.vv │ │ │ ├── no_interface_instantiation_c.out │ │ │ ├── no_interface_instantiation_c.vv │ │ │ ├── no_interface_str.out │ │ │ ├── no_interface_str.vv │ │ │ ├── no_main_mod.out │ │ │ ├── no_main_mod.vv │ │ │ ├── no_main_println_err.out │ │ │ ├── no_main_println_err.vv │ │ │ ├── no_method_must_be_called_from_unsafe_in_translated.out │ │ │ ├── no_method_must_be_called_from_unsafe_in_translated.vv │ │ │ ├── no_method_on_interface_propagation.out │ │ │ ├── no_method_on_interface_propagation.vv │ │ │ ├── no_operator_can_only_be_used_as_a_statement_in_translated.out │ │ │ ├── no_operator_can_only_be_used_as_a_statement_in_translated.vv │ │ │ ├── no_pointer_arithmetic_is_only_allowed_in_translated.out │ │ │ ├── no_pointer_arithmetic_is_only_allowed_in_translated.vv │ │ │ ├── no_pub_in_main.out │ │ │ ├── no_reading_a_union_field_in_translated.out │ │ │ ├── no_reading_a_union_field_in_translated.vv │ │ │ ├── no_sign_notice_in_translated.out │ │ │ ├── no_sign_notice_in_translated.vv │ │ │ ├── no_uninitialized_fn_struct_field_notice_in_translated.out │ │ │ ├── no_uninitialized_fn_struct_field_notice_in_translated.vv │ │ │ ├── no_unused_variable_in_translated.out │ │ │ ├── no_unused_variable_in_translated.vv │ │ │ ├── no_warning_for_in_mut_var_unused.out │ │ │ ├── no_warning_for_in_mut_var_unused.vv │ │ │ ├── non_const_match_range_err.out │ │ │ ├── non_const_match_range_err.vv │ │ │ ├── non_lvalue_as_voidptr.out │ │ │ ├── non_lvalue_as_voidptr.vv │ │ │ ├── non_matching_functional_args.out │ │ │ ├── non_matching_functional_args.vv │ │ │ ├── non_nil_array_with_nil_element_err.out │ │ │ ├── non_nil_array_with_nil_element_err.vv │ │ │ ├── non_optional_array_append_optional_type_err.out │ │ │ ├── non_optional_array_append_optional_type_err.vv │ │ │ ├── none_match_cond_err.out │ │ │ ├── none_match_cond_err.vv │ │ │ ├── none_type_cast_err.out │ │ │ ├── none_type_cast_err.vv │ │ │ ├── noreturn_with_non_empty_loop_at_end.out │ │ │ ├── noreturn_with_non_empty_loop_at_end.vv │ │ │ ├── noreturn_with_return.out │ │ │ ├── noreturn_with_return.vv │ │ │ ├── noreturn_without_loop_or_another_noreturn_at_end.out │ │ │ ├── noreturn_without_loop_or_another_noreturn_at_end.vv │ │ │ ├── number_literal_overflows_known_type_range_warn.out │ │ │ ├── number_literal_overflows_known_type_range_warn.vv │ │ │ ├── oct_lit_without_digit_err.out │ │ │ ├── oct_lit_without_digit_err.vv │ │ │ ├── oct_lit_wrong_digit_err.out │ │ │ ├── oct_lit_wrong_digit_err.vv │ │ │ ├── operator_overloading_return_type_option_or_result.out │ │ │ ├── operator_overloading_return_type_option_or_result.vv │ │ │ ├── opt_is_op_check_err.out │ │ │ ├── opt_is_op_check_err.vv │ │ │ ├── option_alias_result_type_err.out │ │ │ ├── option_alias_result_type_err.vv │ │ │ ├── option_and_result_err.out │ │ │ ├── option_and_result_err.vv │ │ │ ├── option_array_push.out │ │ │ ├── option_array_push.vv │ │ │ ├── option_as_cast_err.out │ │ │ ├── option_as_cast_err.vv │ │ │ ├── option_concrete_type_err.out │ │ │ ├── option_concrete_type_err.vv │ │ │ ├── option_fields_addr_err.out │ │ │ ├── option_fields_addr_err.vv │ │ │ ├── option_fn_err.out │ │ │ ├── option_fn_err.vv │ │ │ ├── option_fn_field_err.out │ │ │ ├── option_fn_field_err.vv │ │ │ ├── option_fn_return_error.out │ │ │ ├── option_fn_return_error.vv │ │ │ ├── option_fn_var_err.out │ │ │ ├── option_fn_var_err.vv │ │ │ ├── option_in_operator_err.out │ │ │ ├── option_in_operator_err.vv │ │ │ ├── option_in_println_mismatch.out │ │ │ ├── option_in_println_mismatch.vv │ │ │ ├── option_in_receiver_err.out │ │ │ ├── option_in_receiver_err.vv │ │ │ ├── option_interface_mismatch.out │ │ │ ├── option_interface_mismatch.vv │ │ │ ├── option_map_err.out │ │ │ ├── option_map_err.vv │ │ │ ├── option_multi_return_err.out │ │ │ ├── option_multi_return_err.vv │ │ │ ├── option_mut_non_mut_err.out │ │ │ ├── option_mut_non_mut_err.vv │ │ │ ├── option_or_block_mismatch.out │ │ │ ├── option_or_block_mismatch.vv │ │ │ ├── option_or_block_returns_value_of_incompatible_type.out │ │ │ ├── option_or_block_returns_value_of_incompatible_type.vv │ │ │ ├── option_propagate_nested.out │ │ │ ├── option_propagate_nested.vv │ │ │ ├── option_ptr_err.out │ │ │ ├── option_ptr_err.vv │ │ │ ├── option_ptr_without_unwrapp_err.out │ │ │ ├── option_ptr_without_unwrapp_err.vv │ │ │ ├── option_receive_ptr_err.out │ │ │ ├── option_receive_ptr_err.vv │ │ │ ├── option_ref_init_err.out │ │ │ ├── option_ref_init_err.vv │ │ │ ├── option_return_call_non_opt_err.out │ │ │ ├── option_return_call_non_opt_err.vv │ │ │ ├── option_return_selector_non_opt_err.out │ │ │ ├── option_return_selector_non_opt_err.vv │ │ │ ├── option_selector_fn_unwrap_err.out │ │ │ ├── option_selector_fn_unwrap_err.vv │ │ │ ├── option_selector_or_block_err.out │ │ │ ├── option_selector_or_block_err.vv │ │ │ ├── option_str_call.out │ │ │ ├── option_str_call.vv │ │ │ ├── option_type_call_err.out │ │ │ ├── option_type_call_err.vv │ │ │ ├── option_var_assign_err.out │ │ │ ├── option_var_assign_err.vv │ │ │ ├── option_var_unwrap_err.out │ │ │ ├── option_var_unwrap_err.vv │ │ │ ├── option_with_match_err.out │ │ │ ├── option_with_match_err.vv │ │ │ ├── option_wrapped_cmp_op_err.out │ │ │ ├── option_wrapped_cmp_op_err.vv │ │ │ ├── or_block_assert_err.out │ │ │ ├── or_block_assert_err.vv │ │ │ ├── or_block_check_err.out │ │ │ ├── or_block_check_err.vv │ │ │ ├── or_block_non_option_err.out │ │ │ ├── or_block_non_option_err.vv │ │ │ ├── or_err.out │ │ │ ├── or_err.vv │ │ │ ├── orm_aggregate_avg_time_error.out │ │ │ ├── orm_aggregate_avg_time_error.vv │ │ │ ├── orm_aggregate_expr_error.out │ │ │ ├── orm_aggregate_expr_error.vv │ │ │ ├── orm_aggregate_sum_string_error.out │ │ │ ├── orm_aggregate_sum_string_error.vv │ │ │ ├── orm_db_expr_option_error.out │ │ │ ├── orm_db_expr_option_error.vv │ │ │ ├── orm_empty_struct.out │ │ │ ├── orm_empty_struct.vv │ │ │ ├── orm_fkey_attribute.out │ │ │ ├── orm_fkey_attribute.vv │ │ │ ├── orm_fkey_has_pkey.out │ │ │ ├── orm_fkey_has_pkey.vv │ │ │ ├── orm_fkey_update.out │ │ │ ├── orm_fkey_update.vv │ │ │ ├── orm_fn_call_with_wrong_return_type.out │ │ │ ├── orm_fn_call_with_wrong_return_type.vv │ │ │ ├── orm_insert_object_with_mismatched_type_error.out │ │ │ ├── orm_insert_object_with_mismatched_type_error.vv │ │ │ ├── orm_invalid_recursive_structs_err_1.out │ │ │ ├── orm_invalid_recursive_structs_err_1.vv │ │ │ ├── orm_invalid_recursive_structs_err_2.out │ │ │ ├── orm_invalid_recursive_structs_err_2.vv │ │ │ ├── orm_left_side_expr_in_infix_expr_has_no_struct_field_error.out │ │ │ ├── orm_left_side_expr_in_infix_expr_has_no_struct_field_error.vv │ │ │ ├── orm_limit_less_than_zero_error.out │ │ │ ├── orm_limit_less_than_zero_error.vv │ │ │ ├── orm_multidim_array.out │ │ │ ├── orm_multidim_array.vv │ │ │ ├── orm_multiple_pkeys.out │ │ │ ├── orm_multiple_pkeys.vv │ │ │ ├── orm_no_default_value.out │ │ │ ├── orm_no_default_value.vv │ │ │ ├── orm_not_a_struct.out │ │ │ ├── orm_not_a_struct.vv │ │ │ ├── orm_op_with_option_and_none.out │ │ │ ├── orm_op_with_option_and_none.vv │ │ │ ├── orm_sub_struct_primary_key.out │ │ │ ├── orm_sub_struct_primary_key.vv │ │ │ ├── orm_table_attributes.out │ │ │ ├── orm_table_attributes.vv │ │ │ ├── orm_unused_var.out │ │ │ ├── orm_unused_var.vv │ │ │ ├── orm_update_anon_fn_option_infix_err.out │ │ │ ├── orm_update_anon_fn_option_infix_err.vv │ │ │ ├── orm_using_non_struct_field_in_order_by_error.out │ │ │ ├── orm_using_non_struct_field_in_order_by_error.vv │ │ │ ├── orm_using_undefined_object_in_insert_error.out │ │ │ ├── orm_using_undefined_object_in_insert_error.vv │ │ │ ├── orm_using_undefined_var_in_where_err.out │ │ │ ├── orm_using_undefined_var_in_where_err.vv │ │ │ ├── orm_where_clause_unsupported_field_types_err.out │ │ │ ├── orm_where_clause_unsupported_field_types_err.vv │ │ │ ├── orm_wrong_where_expr_error.out │ │ │ ├── orm_wrong_where_expr_error.vv │ │ │ ├── os_prefix.out │ │ │ ├── os_prefix.vv │ │ │ ├── overflow_int_err.out │ │ │ ├── overflow_int_err.vv │ │ │ ├── overflow_int_signed_err.out │ │ │ ├── overflow_int_signed_err.vv │ │ │ ├── overload_operator_difference_in_operand_types.out │ │ │ ├── overload_operator_difference_in_operand_types.vv │ │ │ ├── overload_return_type.out │ │ │ ├── overload_return_type.vv │ │ │ ├── oversized_int_lit.out │ │ │ ├── oversized_int_lit.vv │ │ │ ├── par_expr_assign_void_right_type_err.out │ │ │ ├── par_expr_assign_void_right_type_err.vv │ │ │ ├── par_expr_decl_assign_err.out │ │ │ ├── par_expr_decl_assign_err.vv │ │ │ ├── pass_mut_lit.out │ │ │ ├── pass_mut_lit.vv │ │ │ ├── passing_expr_to_fn_expecting_voidptr.out │ │ │ ├── passing_expr_to_fn_expecting_voidptr.vv │ │ │ ├── pointer_ops.out │ │ │ ├── pointer_ops.vv │ │ │ ├── prefix_addr_err.out │ │ │ ├── prefix_addr_err.vv │ │ │ ├── prefix_err.out │ │ │ ├── prefix_err.vv │ │ │ ├── prefix_expr_decl_assign_err.out │ │ │ ├── prefix_expr_decl_assign_err.vv │ │ │ ├── print_char.out │ │ │ ├── print_char.vv │ │ │ ├── println_can_not_print_void_expressions.out │ │ │ ├── println_can_not_print_void_expressions.vv │ │ │ ├── propagate_option_with_result_err.out │ │ │ ├── propagate_option_with_result_err.vv │ │ │ ├── propagate_result_with_option.out │ │ │ ├── propagate_result_with_option.vv │ │ │ ├── ptr_assign.out │ │ │ ├── ptr_assign.vv │ │ │ ├── ptr_slice.out │ │ │ ├── ptr_slice.vv │ │ │ ├── qsort_external_variable_err.out │ │ │ ├── qsort_external_variable_err.vv │ │ │ ├── receiver_unknown_type_single_letter.out │ │ │ ├── receiver_unknown_type_single_letter.vv │ │ │ ├── recursive_alias_type_err.out │ │ │ ├── recursive_alias_type_err.vv │ │ │ ├── recursive_interface_err.out │ │ │ ├── recursive_interface_err.vv │ │ │ ├── recursive_struct_inited_array_err.out │ │ │ ├── recursive_struct_inited_array_err.vv │ │ │ ├── redefining_builtin_pub_functions.out │ │ │ ├── redefining_builtin_pub_functions.vv │ │ │ ├── redfine_global_const_fn_names.out │ │ │ ├── redfine_global_const_fn_names.vv │ │ │ ├── redundant_parentheses_warning.out │ │ │ ├── redundant_parentheses_warning.vv │ │ │ ├── ref_to_non_ref_err.out │ │ │ ├── ref_to_non_ref_err.vv │ │ │ ├── reference_field_must_be_initialized.out │ │ │ ├── reference_field_must_be_initialized.vv │ │ │ ├── reference_return.out │ │ │ ├── reference_return.vv │ │ │ ├── require_or_block_sumtype_map.err.out │ │ │ ├── require_or_block_sumtype_map.err.vv │ │ │ ├── res_use_outside_defer.out │ │ │ ├── res_use_outside_defer.vv │ │ │ ├── reserved_type_name_const_err.out │ │ │ ├── reserved_type_name_const_err.vv │ │ │ ├── result_alias_type_err.out │ │ │ ├── result_alias_type_err.vv │ │ │ ├── result_call_inside_infix_expr_err.out │ │ │ ├── result_call_inside_infix_expr_err.vv │ │ │ ├── result_chan_test_err.out │ │ │ ├── result_chan_test_err.vv │ │ │ ├── result_missing_propagate_err.out │ │ │ ├── result_missing_propagate_err.vv │ │ │ ├── result_param_type_err.out │ │ │ ├── result_param_type_err.vv │ │ │ ├── result_type_call_err.out │ │ │ ├── result_type_call_err.vv │ │ │ ├── return_aliases_of_fixed_array.out │ │ │ ├── return_count_mismatch.out │ │ │ ├── return_count_mismatch.vv │ │ │ ├── return_duplicate_with_none_err_a.out │ │ │ ├── return_duplicate_with_none_err_a.vv │ │ │ ├── return_duplicate_with_none_err_b.out │ │ │ ├── return_duplicate_with_none_err_b.vv │ │ │ ├── return_match_expr_type_mismatch.out │ │ │ ├── return_match_expr_type_mismatch.vv │ │ │ ├── return_missing_comp_if.out │ │ │ ├── return_missing_comp_if.vv │ │ │ ├── return_missing_comp_if_nested.out │ │ │ ├── return_missing_comp_if_nested.vv │ │ │ ├── return_missing_if_else_simple.out │ │ │ ├── return_missing_if_else_simple.vv │ │ │ ├── return_missing_if_match.out │ │ │ ├── return_missing_if_match.vv │ │ │ ├── return_missing_match_if.out │ │ │ ├── return_missing_match_if.vv │ │ │ ├── return_missing_nested.out │ │ │ ├── return_missing_nested.vv │ │ │ ├── return_missing_simple.out │ │ │ ├── return_missing_simple.vv │ │ │ ├── return_option_of_multiple_results.out │ │ │ ├── return_option_of_multiple_results.vv │ │ │ ├── return_ref_as_no_ref_bug.out │ │ │ ├── return_ref_as_no_ref_bug.vv │ │ │ ├── return_result_fn_mismatch.out │ │ │ ├── return_result_fn_mismatch.vv │ │ │ ├── return_result_type_mismatch.out │ │ │ ├── return_result_type_mismatch.vv │ │ │ ├── return_stack_var_err.out │ │ │ ├── return_stack_var_err.vv │ │ │ ├── return_static_name.out │ │ │ ├── return_static_name.vv │ │ │ ├── return_type.out │ │ │ ├── return_type.vv │ │ │ ├── return_void_type_err.out │ │ │ ├── return_void_type_err.vv │ │ │ ├── return_working_comp_if.out │ │ │ ├── return_working_comp_if.vv │ │ │ ├── return_working_comp_if_nested.out │ │ │ ├── return_working_comp_if_nested.vv │ │ │ ├── return_working_if_match.out │ │ │ ├── return_working_if_match.vv │ │ │ ├── return_working_match_if.out │ │ │ ├── return_working_match_if.vv │ │ │ ├── return_working_nested.out │ │ │ ├── return_working_nested.vv │ │ │ ├── return_working_simple.out │ │ │ ├── return_working_simple.vv │ │ │ ├── return_working_two_if.out │ │ │ ├── return_working_two_if.vv │ │ │ ├── return_working_unsafe.out │ │ │ ├── return_working_unsafe.vv │ │ │ ├── returns/ │ │ │ │ └── return_missing_simple.vv │ │ │ ├── right_hand_side_mut.out │ │ │ ├── right_hand_side_mut.vv │ │ │ ├── rshift_op_wrong_left_type_err.out │ │ │ ├── rshift_op_wrong_left_type_err.vv │ │ │ ├── rshift_op_wrong_right_type_err.out │ │ │ ├── rshift_op_wrong_right_type_err.vv │ │ │ ├── run/ │ │ │ │ ├── comptime_ident_in_typearray.run.out │ │ │ │ ├── comptime_ident_in_typearray.vv │ │ │ │ ├── comptime_ident_is_type.run.out │ │ │ │ ├── comptime_ident_is_type.vv │ │ │ │ ├── comptime_main_fn.run.out │ │ │ │ ├── comptime_main_fn.vv │ │ │ │ ├── noreturn_fn_can_be_used_instead_of_panic.run.out │ │ │ │ ├── noreturn_fn_can_be_used_instead_of_panic.vv │ │ │ │ ├── noreturn_method_can_be_used_instead_of_panic.run.out │ │ │ │ ├── noreturn_method_can_be_used_instead_of_panic.vv │ │ │ │ ├── unused_variable_warning.run.out │ │ │ │ ├── unused_variable_warning.vv │ │ │ │ ├── using_comptime_d_value.run.out │ │ │ │ └── using_comptime_d_value.vv │ │ │ ├── selective_const_import.out │ │ │ ├── selective_const_import.vv │ │ │ ├── selector_expr_assign.out │ │ │ ├── selector_expr_assign.vv │ │ │ ├── selector_expr_opt_map_get_err.out │ │ │ ├── selector_expr_opt_map_get_err.vv │ │ │ ├── selector_expr_option_err.out │ │ │ ├── selector_expr_option_err.vv │ │ │ ├── selector_generic_or_block_err.out │ │ │ ├── selector_generic_or_block_err.vv │ │ │ ├── selector_struct_init_amp_err.out │ │ │ ├── selector_struct_init_amp_err.vv │ │ │ ├── shared_bad_args.out │ │ │ ├── shared_bad_args.vv │ │ │ ├── shared_bad_receiver.out │ │ │ ├── shared_bad_receiver.vv │ │ │ ├── shared_element_lock.out │ │ │ ├── shared_element_lock.vv │ │ │ ├── shared_lock.out │ │ │ ├── shared_lock.vv │ │ │ ├── shared_param_assign_err.out │ │ │ ├── shared_param_assign_err.vv │ │ │ ├── shared_param_err.out │ │ │ ├── shared_param_err.vv │ │ │ ├── shared_type_mismatch.out │ │ │ ├── shared_type_mismatch.vv │ │ │ ├── shared_variables_type_err.out │ │ │ ├── shared_variables_type_err.vv │ │ │ ├── shift_op_wrong_left_type_err.out │ │ │ ├── shift_op_wrong_left_type_err.vv │ │ │ ├── shift_op_wrong_right_type_err.out │ │ │ ├── shift_op_wrong_right_type_err.vv │ │ │ ├── shift_ops_expressions.out │ │ │ ├── shift_ops_expressions.vv │ │ │ ├── short_struct_wrong_number.out │ │ │ ├── short_struct_wrong_number.vv │ │ │ ├── sizeof.out │ │ │ ├── sizeof.vv │ │ │ ├── slice_clone_in_struct_init_notice.out │ │ │ ├── slice_clone_in_struct_init_notice.vv │ │ │ ├── slice_clone_notice.out │ │ │ ├── slice_clone_notice.vv │ │ │ ├── slice_reassignment.out │ │ │ ├── slice_reassignment.vv │ │ │ ├── sort_method_called_on_immutable_receiver.out │ │ │ ├── sort_method_called_on_immutable_receiver.vv │ │ │ ├── spawn_wrong_fn_err.out │ │ │ ├── spawn_wrong_fn_err.vv │ │ │ ├── stack_var_check_err.out │ │ │ ├── stack_var_check_err.vv │ │ │ ├── static_fn_call_no_struct_decl_err.out │ │ │ ├── static_fn_call_no_struct_decl_err.vv │ │ │ ├── static_init_err.out │ │ │ ├── static_init_err.vv │ │ │ ├── static_maps_err.out │ │ │ ├── static_maps_err.vv │ │ │ ├── static_method_multi_return_err.out │ │ │ ├── static_method_multi_return_err.vv │ │ │ ├── static_method_not_found_err.out │ │ │ ├── static_method_not_found_err.vv │ │ │ ├── static_vars_in_translated_mode.out │ │ │ ├── static_vars_in_translated_mode.vv │ │ │ ├── store_string_err.out │ │ │ ├── store_string_err.vv │ │ │ ├── str_interpol_invalid_err.out │ │ │ ├── str_interpol_invalid_err.vv │ │ │ ├── str_method_0_arguments.out │ │ │ ├── str_method_0_arguments.vv │ │ │ ├── str_method_return_string.out │ │ │ ├── str_method_return_string.vv │ │ │ ├── string_escape_u16_err_a.out │ │ │ ├── string_escape_u16_err_a.vv │ │ │ ├── string_escape_u16_err_b.out │ │ │ ├── string_escape_u16_err_b.vv │ │ │ ├── string_escape_u32_err_a.out │ │ │ ├── string_escape_u32_err_a.vv │ │ │ ├── string_escape_u32_err_b.out │ │ │ ├── string_escape_u32_err_b.vv │ │ │ ├── string_escape_x_err_a.out │ │ │ ├── string_escape_x_err_a.vv │ │ │ ├── string_escape_x_err_b.out │ │ │ ├── string_escape_x_err_b.vv │ │ │ ├── string_index_assign_error.out │ │ │ ├── string_index_assign_error.vv │ │ │ ├── string_index_non_int_err.out │ │ │ ├── string_index_non_int_err.vv │ │ │ ├── string_interpolation_invalid_fmt.out │ │ │ ├── string_interpolation_invalid_fmt.vv │ │ │ ├── string_interpolation_wrong_fmt.out │ │ │ ├── string_interpolation_wrong_fmt.vv │ │ │ ├── string_to_enum_cast_err.out │ │ │ ├── string_to_enum_cast_err.vv │ │ │ ├── struct_aliased_field_unsign_type_check_err.out │ │ │ ├── struct_aliased_field_unsign_type_check_err.vv │ │ │ ├── struct_arr_mut_field_arr_assign_err.out │ │ │ ├── struct_arr_mut_field_arr_assign_err.vv │ │ │ ├── struct_assigned_to_pointer_to_struct.out │ │ │ ├── struct_assigned_to_pointer_to_struct.vv │ │ │ ├── struct_cast_to_struct_generic_err.out │ │ │ ├── struct_cast_to_struct_generic_err.vv │ │ │ ├── struct_cast_to_struct_mut_err_a.out │ │ │ ├── struct_cast_to_struct_mut_err_a.vv │ │ │ ├── struct_cast_to_struct_mut_err_b.out │ │ │ ├── struct_cast_to_struct_mut_err_b.vv │ │ │ ├── struct_cast_to_struct_pub_err_a.out │ │ │ ├── struct_cast_to_struct_pub_err_a.vv │ │ │ ├── struct_cast_to_struct_pub_err_b.out │ │ │ ├── struct_cast_to_struct_pub_err_b.vv │ │ │ ├── struct_embed_invalid_type.out │ │ │ ├── struct_embed_invalid_type.vv │ │ │ ├── struct_embed_required_field_err.out │ │ │ ├── struct_embed_required_field_err.vv │ │ │ ├── struct_field_assign_internal_types_nil_err.out │ │ │ ├── struct_field_assign_internal_types_nil_err.vv │ │ │ ├── struct_field_fixed_size_init_with_d_as_size_err.out │ │ │ ├── struct_field_fixed_size_init_with_d_as_size_err.vv │ │ │ ├── struct_field_generic_struct_unknown_type_err.out │ │ │ ├── struct_field_generic_struct_unknown_type_err.vv │ │ │ ├── struct_field_init_and_default_is_map_err.out │ │ │ ├── struct_field_init_and_default_is_map_err.vv │ │ │ ├── struct_field_init_fntype_mismatch.out │ │ │ ├── struct_field_init_fntype_mismatch.vv │ │ │ ├── struct_field_init_option_ref_err.out │ │ │ ├── struct_field_init_option_ref_err.vv │ │ │ ├── struct_field_init_with_nobody_anon_fn_err.out │ │ │ ├── struct_field_init_with_nobody_anon_fn_err.vv │ │ │ ├── struct_field_init_with_result_err.out │ │ │ ├── struct_field_init_with_result_err.vv │ │ │ ├── struct_field_init_with_void_expr_err.out │ │ │ ├── struct_field_init_with_void_expr_err.vv │ │ │ ├── struct_field_map_address_err.out │ │ │ ├── struct_field_map_address_err.vv │ │ │ ├── struct_field_mismatch_ref_err.out │ │ │ ├── struct_field_mismatch_ref_err.vv │ │ │ ├── struct_field_name_duplicate_err.out │ │ │ ├── struct_field_name_duplicate_err.vv │ │ │ ├── struct_field_name_err.out │ │ │ ├── struct_field_name_err.vv │ │ │ ├── struct_field_option_err.out │ │ │ ├── struct_field_option_err.vv │ │ │ ├── struct_field_private_err.out │ │ │ ├── struct_field_private_err.vv │ │ │ ├── struct_field_reference_type_err.out │ │ │ ├── struct_field_reference_type_err.vv │ │ │ ├── struct_field_type_err.out │ │ │ ├── struct_field_type_err.vv │ │ │ ├── struct_field_unsign_type_check_err.out │ │ │ ├── struct_field_unsign_type_check_err.vv │ │ │ ├── struct_field_with_any_type_err.out │ │ │ ├── struct_field_with_any_type_err.vv │ │ │ ├── struct_field_with_default_err.out │ │ │ ├── struct_field_with_default_err.vv │ │ │ ├── struct_fixed_array_init_test.out │ │ │ ├── struct_fixed_array_init_test.vv │ │ │ ├── struct_implements_interface_more_than_once_err.out │ │ │ ├── struct_implements_interface_more_than_once_err.vv │ │ │ ├── struct_implements_non_interface_err.out │ │ │ ├── struct_implements_non_interface_err.vv │ │ │ ├── struct_init_deprecations.out │ │ │ ├── struct_init_deprecations.vv │ │ │ ├── struct_init_field_result_err.out │ │ │ ├── struct_init_field_result_err.vv │ │ │ ├── struct_init_update_type_err.out │ │ │ ├── struct_init_update_type_err.vv │ │ │ ├── struct_init_with_iface_embed_iface_with_incorrect_method_impl_ref_field_err.out │ │ │ ├── struct_init_with_iface_embed_iface_with_incorrect_method_impl_ref_field_err.vv │ │ │ ├── struct_init_wrong_warn.out │ │ │ ├── struct_init_wrong_warn.vv │ │ │ ├── struct_iter_generic_invalid_infer_err.out │ │ │ ├── struct_iter_generic_invalid_infer_err.vv │ │ │ ├── struct_match_same_type_node.out │ │ │ ├── struct_match_same_type_node.vv │ │ │ ├── struct_multi_return_field_err.out │ │ │ ├── struct_multi_return_field_err.vv │ │ │ ├── struct_multiple_attrs_test.out │ │ │ ├── struct_multiple_attrs_test.vv │ │ │ ├── struct_non_ptr_field_nil_default_value_err.out │ │ │ ├── struct_non_ptr_field_nil_default_value_err.vv │ │ │ ├── struct_non_ptr_struct_field_nil_default_value_err.out │ │ │ ├── struct_non_ptr_struct_field_nil_default_value_err.vv │ │ │ ├── struct_none_field_type_err.out │ │ │ ├── struct_none_field_type_err.vv │ │ │ ├── struct_not_init_err.out │ │ │ ├── struct_not_init_err.vv │ │ │ ├── struct_option_field_assign_ptr_err.out │ │ │ ├── struct_option_field_assign_ptr_err.vv │ │ │ ├── struct_ptr_cast_int_outside_unsafe_err.out │ │ │ ├── struct_ptr_cast_int_outside_unsafe_err.vv │ │ │ ├── struct_ptr_cast_zero_err.out │ │ │ ├── struct_ptr_cast_zero_err.vv │ │ │ ├── struct_pub_field.out │ │ │ ├── struct_pub_field.vv │ │ │ ├── struct_ref_field_no_ptr_err.out │ │ │ ├── struct_ref_field_no_ptr_err.vv │ │ │ ├── struct_ref_fields_init_0_err.out │ │ │ ├── struct_ref_fields_init_0_err.vv │ │ │ ├── struct_ref_fields_uninitialized_err.out │ │ │ ├── struct_ref_fields_uninitialized_err.vv │ │ │ ├── struct_required_field.out │ │ │ ├── struct_required_field.vv │ │ │ ├── struct_required_fn_field.out │ │ │ ├── struct_required_fn_field.vv │ │ │ ├── struct_scope_err.out │ │ │ ├── struct_scope_err.vv │ │ │ ├── struct_type_cast_err.out │ │ │ ├── struct_type_cast_err.vv │ │ │ ├── struct_unknown_field.out │ │ │ ├── struct_unknown_field.vv │ │ │ ├── struct_unneeded_default.out │ │ │ ├── struct_unneeded_default.vv │ │ │ ├── struct_update_comptime_err.out │ │ │ ├── struct_update_comptime_err.vv │ │ │ ├── struct_void_field_err.out │ │ │ ├── struct_void_field_err.vv │ │ │ ├── struct_voidptr_field_init_err.out │ │ │ ├── struct_voidptr_field_init_err.vv │ │ │ ├── struct_voidptr_field_no_ptr_struct_value_err.out │ │ │ ├── struct_voidptr_field_no_ptr_struct_value_err.vv │ │ │ ├── sum.out │ │ │ ├── sum.vv │ │ │ ├── sum_type_assign_non_variant_err.out │ │ │ ├── sum_type_assign_non_variant_err.vv │ │ │ ├── sum_type_common_fields_alias_error.out │ │ │ ├── sum_type_common_fields_alias_error.vv │ │ │ ├── sum_type_common_fields_error.out │ │ │ ├── sum_type_common_fields_error.vv │ │ │ ├── sum_type_exists.out │ │ │ ├── sum_type_exists.vv │ │ │ ├── sum_type_holding_alias_ptr_err.out │ │ │ ├── sum_type_holding_alias_ptr_err.vv │ │ │ ├── sum_type_infix_err.out │ │ │ ├── sum_type_infix_err.vv │ │ │ ├── sum_type_multiple_type_define.out │ │ │ ├── sum_type_multiple_type_define.vv │ │ │ ├── sum_type_mutable_cast_err.out │ │ │ ├── sum_type_mutable_cast_err.vv │ │ │ ├── sum_type_ref_variant_err.out │ │ │ ├── sum_type_ref_variant_err.vv │ │ │ ├── sum_type_result_variant_err.out │ │ │ ├── sum_type_result_variant_err.vv │ │ │ ├── sumtype_array_to_variadic.out │ │ │ ├── sumtype_array_to_variadic.vv │ │ │ ├── sumtype_as_mismatched_type.out │ │ │ ├── sumtype_as_mismatched_type.vv │ │ │ ├── sumtype_circular_reference_err.out │ │ │ ├── sumtype_circular_reference_err.vv │ │ │ ├── sumtype_define_recursively.out │ │ │ ├── sumtype_define_recursively.vv │ │ │ ├── sumtype_from_voidptr_err.out │ │ │ ├── sumtype_from_voidptr_err.vv │ │ │ ├── sumtype_has_no_variant_suggestion.out │ │ │ ├── sumtype_has_no_variant_suggestion.vv │ │ │ ├── sumtype_in_sumtype_err.out │ │ │ ├── sumtype_in_sumtype_err.vv │ │ │ ├── sumtype_in_unknown_types_err.out │ │ │ ├── sumtype_in_unknown_types_err.vv │ │ │ ├── sumtype_init_with_ref_fields_err.out │ │ │ ├── sumtype_init_with_ref_fields_err.vv │ │ │ ├── sumtype_mismatch_of_aggregate_err.out │ │ │ ├── sumtype_mismatch_of_aggregate_err.vv │ │ │ ├── sumtype_mismatched_type.out │ │ │ ├── sumtype_mismatched_type.vv │ │ │ ├── sumtype_of_fntype_assign_err.out │ │ │ ├── sumtype_of_fntype_assign_err.vv │ │ │ ├── sumtype_variant_mismatch.out │ │ │ ├── sumtype_variant_mismatch.vv │ │ │ ├── sync_receiver_decl.out │ │ │ ├── sync_receiver_decl.vv │ │ │ ├── sync_stdatomic_compile_err.out │ │ │ ├── sync_stdatomic_compile_err.vv │ │ │ ├── template_call_position.out │ │ │ ├── template_call_position.vv │ │ │ ├── template_call_position_test.txt │ │ │ ├── template_keyword_ident_err.out │ │ │ ├── template_keyword_ident_err.vv │ │ │ ├── template_type_mismatch_err.out │ │ │ ├── template_type_mismatch_err.vv │ │ │ ├── templates/ │ │ │ │ ├── empty.html │ │ │ │ ├── index.html │ │ │ │ ├── template.md │ │ │ │ └── template_keyword_ident_err.html │ │ │ ├── test_functions_wrong_signature_test.out │ │ │ ├── test_functions_wrong_signature_test.vv │ │ │ ├── test_invalid_name.out │ │ │ ├── test_invalid_name.vv │ │ │ ├── thread_as_var_name_err.out │ │ │ ├── thread_as_var_name_err.vv │ │ │ ├── top_level_fn_builtin_decl_err.out │ │ │ ├── top_level_fn_builtin_decl_err.vv │ │ │ ├── trailing_comma_struct_attr.out │ │ │ ├── trailing_comma_struct_attr.vv │ │ │ ├── type_alias_decl_anon_struct_invalid_embed.out │ │ │ ├── type_alias_decl_anon_struct_invalid_embed.vv │ │ │ ├── type_alias_decl_parent_type_generic_struct_no_concrete_type_err.out │ │ │ ├── type_alias_decl_parent_type_generic_struct_no_concrete_type_err.vv │ │ │ ├── type_alias_none_parent_type_err.out │ │ │ ├── type_alias_none_parent_type_err.vv │ │ │ ├── type_alias_struct_generic_unknown_name_err.out │ │ │ ├── type_alias_struct_generic_unknown_name_err.vv │ │ │ ├── type_alias_struct_invalid_field_naming.out │ │ │ ├── type_alias_struct_invalid_field_naming.vv │ │ │ ├── type_cast_option_err.out │ │ │ ├── type_cast_option_err.vv │ │ │ ├── type_exists_err.out │ │ │ ├── type_exists_err.vv │ │ │ ├── typedef_attr_v_struct_err.out │ │ │ ├── typedef_attr_v_struct_err.vv │ │ │ ├── typeof_comptime_test.out │ │ │ ├── typeof_comptime_test.vv │ │ │ ├── uncasted_enum_val_as_size_for_fixed_array_err.out │ │ │ ├── uncasted_enum_val_as_size_for_fixed_array_err.vv │ │ │ ├── undefined_ident_in_if_guard_err_a.out │ │ │ ├── undefined_ident_in_if_guard_err_a.vv │ │ │ ├── undefined_ident_in_if_guard_err_b.out │ │ │ ├── undefined_ident_in_if_guard_err_b.vv │ │ │ ├── undefined_ident_in_ref_selector.out │ │ │ ├── undefined_ident_in_ref_selector.vv │ │ │ ├── undefined_ident_of_struct.out │ │ │ ├── undefined_ident_of_struct.vv │ │ │ ├── undefined_type_on_sumtype.out │ │ │ ├── undefined_type_on_sumtype.vv │ │ │ ├── undefined_var_in_comptime_for_test.out │ │ │ ├── undefined_var_in_comptime_for_test.vv │ │ │ ├── unexpected_or.out │ │ │ ├── unexpected_or.vv │ │ │ ├── unexpected_or_propagate.out │ │ │ ├── unexpected_or_propagate.vv │ │ │ ├── unfinished_string.out │ │ │ ├── unfinished_string.vv │ │ │ ├── unimplemented_interface_a.out │ │ │ ├── unimplemented_interface_a.vv │ │ │ ├── unimplemented_interface_b.out │ │ │ ├── unimplemented_interface_b.vv │ │ │ ├── unimplemented_interface_c.out │ │ │ ├── unimplemented_interface_c.vv │ │ │ ├── unimplemented_interface_d.out │ │ │ ├── unimplemented_interface_d.vv │ │ │ ├── unimplemented_interface_e.out │ │ │ ├── unimplemented_interface_e.vv │ │ │ ├── unimplemented_interface_f.out │ │ │ ├── unimplemented_interface_f.vv │ │ │ ├── unimplemented_interface_g.out │ │ │ ├── unimplemented_interface_g.vv.disabled │ │ │ ├── unimplemented_interface_h.out │ │ │ ├── unimplemented_interface_h.vv │ │ │ ├── unimplemented_interface_i.out │ │ │ ├── unimplemented_interface_i.vv │ │ │ ├── unimplemented_interface_j.out │ │ │ ├── unimplemented_interface_j.vv │ │ │ ├── union_init_having_more_fields_err.out │ │ │ ├── union_init_having_more_fields_err.vv │ │ │ ├── union_unsafe_fields.out │ │ │ ├── union_unsafe_fields.vv │ │ │ ├── unknown_array_element_type_b.out │ │ │ ├── unknown_array_element_type_b.vv │ │ │ ├── unknown_array_fn_type_in_struct_field.out │ │ │ ├── unknown_array_fn_type_in_struct_field.vv │ │ │ ├── unknown_as_type.out │ │ │ ├── unknown_as_type.vv │ │ │ ├── unknown_comptime_expr.out │ │ │ ├── unknown_comptime_expr.vv │ │ │ ├── unknown_field.out │ │ │ ├── unknown_field.vv │ │ │ ├── unknown_field_in_struct_literal.out │ │ │ ├── unknown_field_in_struct_literal.vv │ │ │ ├── unknown_fn_call_err.out │ │ │ ├── unknown_fn_call_err.vv │ │ │ ├── unknown_function.out │ │ │ ├── unknown_function.vv │ │ │ ├── unknown_generic_type.out │ │ │ ├── unknown_generic_type.vv │ │ │ ├── unknown_method.out │ │ │ ├── unknown_method.vv │ │ │ ├── unknown_method_suggest_name.out │ │ │ ├── unknown_method_suggest_name.vv │ │ │ ├── unknown_sizeof_type_err_a.out │ │ │ ├── unknown_sizeof_type_err_a.vv │ │ │ ├── unknown_sizeof_type_err_b.out │ │ │ ├── unknown_sizeof_type_err_b.vv │ │ │ ├── unknown_struct_field_suggest_name.out │ │ │ ├── unknown_struct_field_suggest_name.vv │ │ │ ├── unknown_struct_name.out │ │ │ ├── unknown_struct_name.vv │ │ │ ├── unknown_type_in_anon_fn.out │ │ │ ├── unknown_type_in_anon_fn.vv │ │ │ ├── unknown_var_assign.out │ │ │ ├── unknown_var_assign.vv │ │ │ ├── unkown_enum_call_err.out │ │ │ ├── unkown_enum_call_err.vv │ │ │ ├── unnecessary_parenthesis.out │ │ │ ├── unnecessary_parenthesis.vv │ │ │ ├── unnecessary_parenthesis_of_reference.out │ │ │ ├── unnecessary_parenthesis_of_reference.vv │ │ │ ├── unreachable_code.out │ │ │ ├── unreachable_code.vv │ │ │ ├── unsafe_assign_none_err.out │ │ │ ├── unsafe_assign_none_err.vv │ │ │ ├── unsafe_c_calls_should_be_checked.out │ │ │ ├── unsafe_c_calls_should_be_checked.vv │ │ │ ├── unsafe_deference_nil_err.out │ │ │ ├── unsafe_deference_nil_err.vv │ │ │ ├── unsafe_deref_assign_err.out │ │ │ ├── unsafe_deref_assign_err.vv │ │ │ ├── unsafe_fixed_array_assign.out │ │ │ ├── unsafe_fixed_array_assign.vv │ │ │ ├── unsafe_generic_call_test.out │ │ │ ├── unsafe_generic_call_test.vv │ │ │ ├── unsafe_method_as_field.out │ │ │ ├── unsafe_method_as_field.vv │ │ │ ├── unsafe_none_return_err.out │ │ │ ├── unsafe_none_return_err.vv │ │ │ ├── unsafe_pointer_arithmetic_should_be_checked.out │ │ │ ├── unsafe_pointer_arithmetic_should_be_checked.vv │ │ │ ├── unsafe_required.out │ │ │ ├── unsafe_required.vv │ │ │ ├── unused_import_err.out │ │ │ ├── unused_import_err.vv │ │ │ ├── unused_label.out │ │ │ ├── unused_label.vv │ │ │ ├── unused_last_expr_stmt_in_if.out │ │ │ ├── unused_last_expr_stmt_in_if.vv │ │ │ ├── unused_param.out │ │ │ ├── unused_param.vv │ │ │ ├── unwrapped_option_infix.out │ │ │ ├── unwrapped_option_infix.vv │ │ │ ├── unwrapped_option_result_in_operation_err.out │ │ │ ├── unwrapped_option_result_in_operation_err.vv │ │ │ ├── unwrapped_result_infix_err.out │ │ │ ├── unwrapped_result_infix_err.vv │ │ │ ├── use_byte_instead_of_u8_array_param_err.out │ │ │ ├── use_byte_instead_of_u8_array_param_err.vv │ │ │ ├── use_byte_instead_of_u8_array_type_err.out │ │ │ ├── use_byte_instead_of_u8_array_type_err.vv │ │ │ ├── use_byte_instead_of_u8_err.out │ │ │ ├── use_byte_instead_of_u8_err.vv │ │ │ ├── use_deprecated_function_warning.out │ │ │ ├── use_deprecated_function_warning.vv │ │ │ ├── use_empty_map_literal_to_initialize_anon_struct_error.out │ │ │ ├── use_empty_map_literal_to_initialize_anon_struct_error.vv │ │ │ ├── var_decl_import_sym_conflict.out │ │ │ ├── var_decl_import_sym_conflict.vv │ │ │ ├── var_duplicate_const.out │ │ │ ├── var_duplicate_const.vv │ │ │ ├── var_eval_not_used.out │ │ │ ├── var_eval_not_used.vv │ │ │ ├── var_eval_not_used_scope.out │ │ │ ├── var_eval_not_used_scope.vv │ │ │ ├── var_option_index_error.out │ │ │ ├── var_option_index_error.vv │ │ │ ├── var_option_wrong_default.out │ │ │ ├── var_option_wrong_default.vv │ │ │ ├── var_option_wrong_type.out │ │ │ ├── var_option_wrong_type.vv │ │ │ ├── var_option_wrong_unwrap.out │ │ │ ├── var_option_wrong_unwrap.vv │ │ │ ├── var_used_before_declaration.out │ │ │ ├── var_used_before_declaration.vv │ │ │ ├── variadic_value_print_err.out │ │ │ ├── variadic_value_print_err.vv │ │ │ ├── veb_ctx_on_fn_err.out │ │ │ ├── veb_ctx_on_fn_err.vv │ │ │ ├── void_fn_as_value.out │ │ │ ├── void_fn_as_value.vv │ │ │ ├── void_fn_multiple_ret_err.out │ │ │ ├── void_fn_multiple_ret_err.vv │ │ │ ├── void_function_assign_to_string.out │ │ │ ├── void_function_assign_to_string.vv │ │ │ ├── void_method_call.out │ │ │ ├── void_method_call.vv │ │ │ ├── void_option_err.out │ │ │ ├── void_option_err.vv │ │ │ ├── voidptr_arg_err.out │ │ │ ├── voidptr_arg_err.vv │ │ │ ├── voidptr_cast_to_struct_err.out │ │ │ ├── voidptr_cast_to_struct_err.vv │ │ │ ├── voidptr_dereference_err.out │ │ │ ├── voidptr_dereference_err.vv │ │ │ ├── vweb_missing_result.out │ │ │ ├── vweb_missing_result.vv │ │ │ ├── vweb_routing_checks.out │ │ │ ├── vweb_routing_checks.vv │ │ │ ├── vweb_tmpl_used_var.out │ │ │ ├── vweb_tmpl_used_var.vv │ │ │ ├── warnings_for_string_c2v_calls.out │ │ │ ├── warnings_for_string_c2v_calls.vv │ │ │ ├── with_check_option/ │ │ │ │ ├── empty_global_const.out │ │ │ │ ├── empty_global_const.vv │ │ │ │ ├── v_import_const.out │ │ │ │ ├── v_import_const.vv │ │ │ │ ├── v_tictactoe.out │ │ │ │ ├── v_tictactoe.vv │ │ │ │ ├── v_tictactoe_fixed_syntax_error.out │ │ │ │ └── v_tictactoe_fixed_syntax_error.vv │ │ │ ├── wrong_arg_count_with_or_block_no_panic.out │ │ │ ├── wrong_arg_count_with_or_block_no_panic.vv │ │ │ ├── wrong_arr_field_err.out │ │ │ ├── wrong_arr_field_err.vv │ │ │ ├── wrong_comptime_for_err.out │ │ │ ├── wrong_comptime_for_err.vv │ │ │ ├── wrong_fn_init_err.out │ │ │ ├── wrong_fn_init_err.vv │ │ │ ├── wrong_muti_dim_arr_declare_err.out │ │ │ ├── wrong_muti_dim_arr_declare_err.vv │ │ │ ├── wrong_none_on_or_block_err.out │ │ │ ├── wrong_none_on_or_block_err.vv │ │ │ ├── wrong_option_type.out │ │ │ ├── wrong_option_type.vv │ │ │ ├── wrong_option_unwrap_err.out │ │ │ ├── wrong_option_unwrap_err.vv │ │ │ ├── wrong_or_expr_err.out │ │ │ ├── wrong_or_expr_err.vv │ │ │ ├── wrong_predicate_type_err.out │ │ │ ├── wrong_predicate_type_err.vv │ │ │ ├── wrong_propagate_ret_type.out │ │ │ ├── wrong_propagate_ret_type.vv │ │ │ ├── wrong_result_type.out │ │ │ ├── wrong_result_type.vv │ │ │ ├── wrong_return_type_err.out │ │ │ ├── wrong_return_type_err.vv │ │ │ ├── wrong_shift_left_option_err.out │ │ │ ├── wrong_shift_left_option_err.vv │ │ │ ├── wrong_struct_init_err.out │ │ │ ├── wrong_struct_init_err.vv │ │ │ ├── wrong_type_casted_fixed_array_size_err.out │ │ │ └── wrong_type_casted_fixed_array_size_err.vv │ │ └── used_features.v │ ├── compiler_errors_test.v │ ├── comptime/ │ │ └── comptime.v │ ├── debug/ │ │ ├── callstack.c.v │ │ ├── debug.v │ │ ├── interactive_test.v │ │ ├── tests/ │ │ │ ├── aggregate.expect │ │ │ ├── aggregate.vv │ │ │ ├── common.tcl │ │ │ ├── comptime_smartcast.expect │ │ │ ├── comptime_smartcast.vv │ │ │ ├── comptime_variant.expect │ │ │ ├── comptime_variant.vv │ │ │ ├── interface_var.expect │ │ │ ├── interface_var.vv │ │ │ ├── iteration.expect │ │ │ ├── iteration.vv │ │ │ ├── mut_arg.expect │ │ │ ├── mut_arg.vv │ │ │ ├── mut_sumtype.expect │ │ │ ├── mut_sumtype.vv │ │ │ ├── option.expect │ │ │ ├── option.vv │ │ │ ├── option_unwrap.expect │ │ │ ├── option_unwrap.vv │ │ │ ├── or_expr_scope.expect │ │ │ ├── or_expr_scope.vv │ │ │ ├── smartcast.expect │ │ │ ├── smartcast.vv │ │ │ ├── struct_heap.expect │ │ │ ├── struct_heap.vv │ │ │ ├── sumtype.expect │ │ │ ├── sumtype.vv │ │ │ ├── trace/ │ │ │ │ └── trace_test.v │ │ │ ├── var_scope.expect │ │ │ └── var_scope.vv │ │ ├── trace.v │ │ └── tracing_test.v │ ├── depgraph/ │ │ ├── depgraph.v │ │ └── depgraph_test.v │ ├── dotgraph/ │ │ ├── dotgraph.c.v │ │ ├── dotgraph.js.v │ │ └── dotgraph.v │ ├── embed_file/ │ │ ├── decoder.v │ │ ├── embed_file.v │ │ ├── embed_file_d_freestanding.v │ │ ├── embed_file_notd_freestanding.v │ │ └── tests/ │ │ ├── a.txt │ │ ├── embed_file_self_test.v │ │ ├── embed_file_test.v │ │ ├── embed_file_to_string_test.v │ │ ├── embed_file_with_import_test.v │ │ ├── embed_file_with_variable_arg_test.v │ │ └── embed_v_logo_using_vexeroot_test.v │ ├── errors/ │ │ └── errors.v │ ├── eval/ │ │ ├── eval.v │ │ ├── expr.c.v │ │ ├── gen/ │ │ │ └── infix_gen.v │ │ ├── infix.v │ │ ├── interpret_test.v │ │ ├── object.v │ │ ├── stmt.v │ │ ├── testdata/ │ │ │ ├── constants_and_casts.out │ │ │ ├── constants_and_casts.vv │ │ │ ├── hello.out │ │ │ ├── hello.vv │ │ │ ├── range_and_assign_ops.out │ │ │ ├── range_and_assign_ops.vv │ │ │ ├── string_interpolation.out │ │ │ ├── string_interpolation.vv │ │ │ ├── unsafe_expr.out │ │ │ └── unsafe_expr.vv │ │ ├── tests/ │ │ │ ├── comptime_if_test.v │ │ │ ├── const_test.v │ │ │ ├── func_call_test.v │ │ │ ├── if_test.v │ │ │ └── push_val_test.v │ │ └── var.v │ ├── fmt/ │ │ ├── align.v │ │ ├── asm.v │ │ ├── attrs.v │ │ ├── comments.v │ │ ├── fmt.v │ │ ├── fmt_bin2v_test.v │ │ ├── fmt_keep_test.v │ │ ├── fmt_new_int_test.v │ │ ├── fmt_test.v │ │ ├── fmt_vlib_test.v │ │ ├── struct.v │ │ ├── testdata/ │ │ │ └── vmodules/ │ │ │ ├── submod_import_alias/ │ │ │ │ └── vlas/ │ │ │ │ ├── internal/ │ │ │ │ │ └── blas/ │ │ │ │ │ └── .gitkeep │ │ │ │ ├── module_alias_import_submod_in_submod_keep.vv │ │ │ │ ├── module_alias_submod_import_parent_mod_expected.vv │ │ │ │ └── module_alias_submod_import_parent_mod_input.vv │ │ │ └── submod_type_alias/ │ │ │ ├── bar/ │ │ │ │ └── baz/ │ │ │ │ └── baz.v │ │ │ ├── submod_type_alias_expected.vv │ │ │ └── submod_type_alias_input.vv │ │ ├── tests/ │ │ │ ├── .gitattributes │ │ │ ├── allow_const_with_decl_assign_expected.vv │ │ │ ├── allow_const_with_decl_assign_input.vv │ │ │ ├── anon_fn_as_param_keep.vv │ │ │ ├── anon_fn_call_keep.vv │ │ │ ├── anon_fn_expected.vv │ │ │ ├── anon_fn_input.vv │ │ │ ├── anon_fn_result_return_with_comment_keep.vv │ │ │ ├── anon_fn_with_if_expr_expected.vv │ │ │ ├── anon_fn_with_if_expr_input.vv │ │ │ ├── anon_struct_as_param_expected.vv │ │ │ ├── anon_struct_as_param_input.vv │ │ │ ├── anon_struct_as_param_with_fn_attrs_keep.vv │ │ │ ├── array_decomposition_keep.vv │ │ │ ├── array_init_comment_ending_keep.vv │ │ │ ├── array_init_comments_expected.vv │ │ │ ├── array_init_comments_input.vv │ │ │ ├── array_init_eol_comments_keep.vv │ │ │ ├── array_init_expected.vv │ │ │ ├── array_init_input.vv │ │ │ ├── array_init_it_expected.vv │ │ │ ├── array_init_it_input.vv │ │ │ ├── array_init_keep.vv │ │ │ ├── array_newlines_keep.vv │ │ │ ├── array_option_anon_struct_keep.vv │ │ │ ├── array_slices_expected.vv │ │ │ ├── array_slices_input.vv │ │ │ ├── array_static_keep.vv │ │ │ ├── assembly/ │ │ │ │ └── asm_keep.vv │ │ │ ├── assert_extra_message_keep.vv │ │ │ ├── asserts_expected.vv │ │ │ ├── asserts_input.vv │ │ │ ├── asserts_keep.vv │ │ │ ├── attrs_expected.vv │ │ │ ├── attrs_input.vv │ │ │ ├── attrs_keep.vv │ │ │ ├── block_with_blank_line_keep.vv │ │ │ ├── blocks_expected.vv │ │ │ ├── blocks_input.vv │ │ │ ├── blocks_keep.vv │ │ │ ├── c_struct_init_keep.vv │ │ │ ├── c_varargs_keep.vv │ │ │ ├── cast_expected.vv │ │ │ ├── cast_input.vv │ │ │ ├── cast_or_dump_arg_ending_with_comma_expected.vv │ │ │ ├── cast_or_dump_arg_ending_with_comma_input.vv │ │ │ ├── chain_calls_with_comments_expected.vv │ │ │ ├── chain_calls_with_comments_input.vv │ │ │ ├── chan_init_keep.vv │ │ │ ├── chan_ops_keep.vv │ │ │ ├── chan_or_keep.vv │ │ │ ├── char_literal_keep.vv │ │ │ ├── closure_keep.vv │ │ │ ├── comments_array_keep.vv │ │ │ ├── comments_expected.vv │ │ │ ├── comments_input.vv │ │ │ ├── comments_keep.vv │ │ │ ├── comptime_call_keep.vv │ │ │ ├── comptime_field_selector_keep.vv │ │ │ ├── comptime_field_selector_parentheses_keep.vv │ │ │ ├── comptime_if_after_inc_expr_keep.vv │ │ │ ├── comptime_if_duplicate_method_keep.vv │ │ │ ├── comptime_if_expr_script_keep.vv │ │ │ ├── comptime_if_top_enum_empty_line_keep.vv │ │ │ ├── comptime_keep.vv │ │ │ ├── comptime_method_args_expected.vv │ │ │ ├── comptime_method_args_input.vv │ │ │ ├── comptime_method_call_keep.vv │ │ │ ├── comptime_value_keep.vv │ │ │ ├── comptime_warn_keep.vv │ │ │ ├── concat_expr_expected.vv │ │ │ ├── concat_expr_input.vv │ │ │ ├── conditional_compilation_keep.vv │ │ │ ├── conditional_compilation_keep_in_module.vv │ │ │ ├── conditions_expected.vv │ │ │ ├── conditions_input.vv │ │ │ ├── consts_after_linebreak_expected.vv │ │ │ ├── consts_after_linebreak_input.vv │ │ │ ├── consts_expected.vv │ │ │ ├── consts_input.vv │ │ │ ├── consts_keep.vv │ │ │ ├── consts_with_comments_end_keep.vv │ │ │ ├── consts_with_comments_expected.vv │ │ │ ├── consts_with_comments_input.vv │ │ │ ├── consts_with_comments_keep.vv │ │ │ ├── consts_with_embedded_comments_expected.vv │ │ │ ├── consts_with_embedded_comments_input.vv │ │ │ ├── consts_with_or_block_keep.vv │ │ │ ├── defer_keep.vv │ │ │ ├── defer_mode_expected.vv │ │ │ ├── defer_mode_input.vv │ │ │ ├── do_not_change_type_names_that_just_happen_to_have_the_module_as_a_substring_keep.vv │ │ │ ├── donut_card_expected.vv │ │ │ ├── donut_card_input.vv │ │ │ ├── embed_file_keep.vv │ │ │ ├── empty_curlies_and_parens_keep.vv │ │ │ ├── empty_lines_expected.vv │ │ │ ├── empty_lines_input.vv │ │ │ ├── empty_lines_keep.vv │ │ │ ├── empty_map_fmt_keep.vv │ │ │ ├── enum_attributes_keep.vv │ │ │ ├── enum_attrs_comments_keep.vv │ │ │ ├── enum_comments_keep.vv │ │ │ ├── enum_decl_with_comment_expected.vv │ │ │ ├── enum_decl_with_comment_input.vv │ │ │ ├── enum_fields_with_empty_line_1_keep.vv │ │ │ ├── enum_fields_with_empty_line_2_keep.vv │ │ │ ├── enum_values_comments_keep.vv │ │ │ ├── enums_expected.vv │ │ │ ├── enums_input.vv │ │ │ ├── expressions_expected.vv │ │ │ ├── expressions_input.vv │ │ │ ├── extra_par_expr_expected.vv │ │ │ ├── extra_par_expr_input.vv │ │ │ ├── file_with_just_imports_keep.vv │ │ │ ├── fixed_size_array_type_keep.vv │ │ │ ├── float_literals_expected.vv │ │ │ ├── float_literals_input.vv │ │ │ ├── fn_call_concrete_type_keep.vv │ │ │ ├── fn_call_with_call_expr_and_params_struct_args_keep.vv │ │ │ ├── fn_headers_with_comments_expected.vv │ │ │ ├── fn_headers_with_comments_input.vv │ │ │ ├── fn_headers_with_comments_keep.vv │ │ │ ├── fn_headers_with_no_bodies_keep.vv │ │ │ ├── fn_multi_return_keep.vv │ │ │ ├── fn_parameter_the_same_as_a_module_const_keep.vv │ │ │ ├── fn_return_generic_struct_keep.vv │ │ │ ├── fn_return_parentheses_expected.vv │ │ │ ├── fn_return_parentheses_input.vv │ │ │ ├── fn_trailing_arg_syntax_expected.vv │ │ │ ├── fn_trailing_arg_syntax_input.vv │ │ │ ├── fn_trailing_arg_syntax_keep.vv │ │ │ ├── fn_type_attributes_and_calling_convention_keep.vv │ │ │ ├── fn_types_list_ending_with_comma_expected.vv │ │ │ ├── fn_types_list_ending_with_comma_input.vv │ │ │ ├── fn_with_anon_params_keep.vv │ │ │ ├── fn_with_args_comments_keep.vv │ │ │ ├── fn_with_c_binding_type_args_keep.vv │ │ │ ├── fn_with_end_comments_keep.vv │ │ │ ├── fn_with_long_args_keep.vv │ │ │ ├── fn_with_mut_ref_params_keep.vv │ │ │ ├── fn_with_short_args_keep.vv │ │ │ ├── fn_with_variadic_arg_expected.vv │ │ │ ├── fn_with_variadic_arg_input.vv │ │ │ ├── fntype_alias_array_keep.vv │ │ │ ├── fntype_alias_keep.vv │ │ │ ├── fntype_mut_args_with_option_keep.vv │ │ │ ├── fntype_return_option_keep.vv │ │ │ ├── functions_expected.vv │ │ │ ├── functions_expected_new_int.vv │ │ │ ├── functions_input.vv │ │ │ ├── gated_array_keep.vv │ │ │ ├── generic_recursive_structs_keep.vv │ │ │ ├── generic_struct_init_keep.vv │ │ │ ├── generic_structs_keep.vv │ │ │ ├── generic_structs_using_mod_keep.vv │ │ │ ├── generics_cascade_types_keep.vv │ │ │ ├── generics_fntype_keep.vv │ │ │ ├── generics_keep.vv │ │ │ ├── global_keep.vv │ │ │ ├── go_stmt_expected.vv │ │ │ ├── go_stmt_input.vv │ │ │ ├── go_stmt_keep.vv │ │ │ ├── goto_expected.vv │ │ │ ├── goto_input.vv │ │ │ ├── hashstmt_expected.vv │ │ │ ├── hashstmt_input.vv │ │ │ ├── hashstmt_keep.vv │ │ │ ├── if_array_contains_expected.vv │ │ │ ├── if_array_contains_input.vv │ │ │ ├── if_brace_on_newline_expected.vv │ │ │ ├── if_brace_on_newline_input.vv │ │ │ ├── if_expected.vv │ │ │ ├── if_input.vv │ │ │ ├── if_keep.vv │ │ │ ├── if_not_in_is_expected.vv │ │ │ ├── if_not_in_is_input.vv │ │ │ ├── if_ternary_expected.vv │ │ │ ├── if_ternary_input.vv │ │ │ ├── if_ternary_keep.vv │ │ │ ├── if_ternary_return_keep.vv │ │ │ ├── import_auto_added_expected.vv │ │ │ ├── import_auto_added_input.vv │ │ │ ├── import_auto_with_shebang_and_comment_above_imports_expected.vv │ │ │ ├── import_auto_with_shebang_and_comment_above_imports_input.vv │ │ │ ├── import_auto_with_shebang_expected.vv │ │ │ ├── import_auto_with_shebang_input.vv │ │ │ ├── import_comments_keep.vv │ │ │ ├── import_duplicate_expected.vv │ │ │ ├── import_multiple_imports_at_one_line_expected.vv │ │ │ ├── import_multiple_imports_at_one_line_input.vv │ │ │ ├── import_multiple_with_alias_expected.vv │ │ │ ├── import_multiple_with_alias_input.vv │ │ │ ├── import_rand_and_rand_seed_keep.vv │ │ │ ├── import_selective_expected.vv │ │ │ ├── import_selective_input.vv │ │ │ ├── import_selective_keep.vv │ │ │ ├── import_selective_map_keep.vv │ │ │ ├── import_selective_with_func_call_args_keep.vv │ │ │ ├── import_selective_with_implements_keep.vv │ │ │ ├── import_single_keep.vv │ │ │ ├── import_submod_from_vmodule_src_dir_keep.vv │ │ │ ├── import_with_alias_keep.vv │ │ │ ├── import_with_symbol_of_struct_keep.vv │ │ │ ├── import_with_symbols_keep.vv │ │ │ ├── infix_expr_and_op_expected.vv │ │ │ ├── infix_expr_and_op_input.vv │ │ │ ├── infix_expr_expected.vv │ │ │ ├── infix_expr_input.vv │ │ │ ├── infix_expr_keep.vv │ │ │ ├── infix_expr_with_comments_keep.vv │ │ │ ├── inline_comment_expected.vv │ │ │ ├── inline_comment_input.vv │ │ │ ├── integer_literal_keep.vv │ │ │ ├── interface_anon_struct_decl_keep.vv │ │ │ ├── interface_decl_with_comment_expected.vv │ │ │ ├── interface_decl_with_comment_input.vv │ │ │ ├── interface_declaration_comments_keep.vv │ │ │ ├── interface_field_expected.vv │ │ │ ├── interface_field_input.vv │ │ │ ├── interface_fields_with_pre_comments_keep.vv │ │ │ ├── interface_js_interop_method_keep.vv │ │ │ ├── interface_method_with_fntype_arg_keep.vv │ │ │ ├── interface_method_with_pre_comments_keep.vv │ │ │ ├── interface_variadic_keep.vv │ │ │ ├── interface_with_empty_newline_1_keep.vv │ │ │ ├── interface_with_empty_newline_2_keep.vv │ │ │ ├── interface_with_mut_fields_keep.vv │ │ │ ├── json_decode_fmt_keep.vv │ │ │ ├── keyword_attr_keep.vv │ │ │ ├── labelled_break_continue_keep.vv │ │ │ ├── language_prefixes_keep.vv │ │ │ ├── lock_expected.vv │ │ │ ├── lock_input.vv │ │ │ ├── long_sumtype_expected.vv │ │ │ ├── long_sumtype_input.vv │ │ │ ├── loops_expected.vv │ │ │ ├── loops_input.vv │ │ │ ├── manualfree_keep.vv │ │ │ ├── map_init_comments_keep.vv │ │ │ ├── map_of_strings_to_enums_init_with_utf8_keys_keep.vv │ │ │ ├── map_value_with_option_result_expected.vv │ │ │ ├── map_value_with_option_result_input.vv │ │ │ ├── maps_expected.vv │ │ │ ├── maps_in_fn_args__keep.vv │ │ │ ├── maps_input.vv │ │ │ ├── maps_keep.vv │ │ │ ├── maps_of_fns_with_string_keys_keep.vv │ │ │ ├── match_expected.vv │ │ │ ├── match_input.vv │ │ │ ├── match_keep.vv │ │ │ ├── match_range_expression_branches_keep.vv │ │ │ ├── match_with_commented_branches_keep.vv │ │ │ ├── match_with_multi_commented_branches_keep.vv │ │ │ ├── missing_import_expected.vv │ │ │ ├── missing_import_input.vv │ │ │ ├── module_alias_keep.vv │ │ │ ├── module_interface_keep.vv │ │ │ ├── module_struct_keep.vv │ │ │ ├── multi_generic_test_keep.vv │ │ │ ├── multiline_comment_1_keep.vv │ │ │ ├── multiline_comment_2_keep.vv │ │ │ ├── nested_map_type_keep.vv │ │ │ ├── new_int_expected.vv │ │ │ ├── new_int_expected_new_int.vv │ │ │ ├── new_int_input.vv │ │ │ ├── newlines_keep.vv │ │ │ ├── no_main_expected.vv │ │ │ ├── no_main_input.vv │ │ │ ├── obj/ │ │ │ │ └── obj.v │ │ │ ├── offset_keep.vv │ │ │ ├── old_attrs_to_new_expected.vv │ │ │ ├── old_attrs_to_new_input.vv │ │ │ ├── operator_overload_keep.vv │ │ │ ├── option_keep.vv │ │ │ ├── option_propagate_keep.vv │ │ │ ├── option_with_multi_stmts_keep.vv │ │ │ ├── or_keep.vv │ │ │ ├── orm_keep.vv │ │ │ ├── orm_or_keep.vv │ │ │ ├── orm_prefix_keep.vv │ │ │ ├── par_expr_expected.vv │ │ │ ├── par_expr_input.vv │ │ │ ├── pointer_casts_keep.vv │ │ │ ├── proto_module_importing_vproto_keep.vv │ │ │ ├── receiver_state_keep.vv │ │ │ ├── ref_type_cast_keep.vv │ │ │ ├── result_return_type_keep.vv │ │ │ ├── select_keep.vv │ │ │ ├── semicolons_expected.vv │ │ │ ├── semicolons_input.vv │ │ │ ├── shared_expected.vv │ │ │ ├── shared_input.vv │ │ │ ├── shorten_longer_module_paths_first_keep.vv │ │ │ ├── sqlstmt_comments_keep.vv │ │ │ ├── star__amp_int__cast_keep.vv │ │ │ ├── static_methods_keep.vv │ │ │ ├── static_mut_keep.vv │ │ │ ├── stmt_attr_keep.vv │ │ │ ├── stmt_keep.vv │ │ │ ├── string_interpolation_complex_keep.vv │ │ │ ├── string_interpolation_expected.vv │ │ │ ├── string_interpolation_input.vv │ │ │ ├── string_interpolation_keep.vv │ │ │ ├── string_intp_with_result_keep.vv │ │ │ ├── string_quotes_expected.vv │ │ │ ├── string_quotes_input.vv │ │ │ ├── string_raw_and_cstr_keep.vv │ │ │ ├── strings_name_variable_call_keep.vv │ │ │ ├── struct_decl_keep.vv │ │ │ ├── struct_decl_with_comments_expected.vv │ │ │ ├── struct_decl_with_comments_input.vv │ │ │ ├── struct_decl_with_comments_keep.vv │ │ │ ├── struct_decl_with_const_default_value_and_comments_keep.vv │ │ │ ├── struct_decl_with_nested_struct_keep.vv │ │ │ ├── struct_decl_with_newline_and_comments_keep.vv │ │ │ ├── struct_default_field_expressions_keep.vv │ │ │ ├── struct_embed_keep.vv │ │ │ ├── struct_end_comments_keep.vv │ │ │ ├── struct_fixed_array_ident_keep.vv │ │ │ ├── struct_init_keep.vv │ │ │ ├── struct_init_with_comments_keep.vv │ │ │ ├── struct_init_with_custom_len_keep.vv │ │ │ ├── struct_init_with_newline_and_comments_1_keep.vv │ │ │ ├── struct_init_with_newline_and_comments_2_keep.vv │ │ │ ├── struct_init_with_ref_cast_keep.vv │ │ │ ├── struct_init_with_update_expr_comment_keep.vv │ │ │ ├── struct_keep.vv │ │ │ ├── struct_no_extra_attr_keep.vv │ │ │ ├── struct_update_comment_keep.vv │ │ │ ├── struct_update_keep.vv │ │ │ ├── struct_with_array_of_anon_struct_field_decl_keep.vv │ │ │ ├── struct_with_fn_fields_keep.vv │ │ │ ├── structs_comments_keep.vv │ │ │ ├── sum_attributes_keep.vv │ │ │ ├── sum_smartcast_keep.vv │ │ │ ├── symbol_registration_keep.vv │ │ │ ├── thread_in_a_module_keep.vv │ │ │ ├── to_string_2_forms_keep.vv │ │ │ ├── too_long_infix_expressions_keep.vv │ │ │ ├── trailing_space_expected.vv │ │ │ ├── trailing_space_input.vv │ │ │ ├── translated_module_expected.vv │ │ │ ├── translated_module_expected_new_int.vv │ │ │ ├── translated_module_input.vv │ │ │ ├── type_decl_comments_keep.vv │ │ │ ├── type_decl_with_anon_struct_keep.vv │ │ │ ├── type_ptr_keep.vv │ │ │ ├── typeof_keep.vv │ │ │ ├── types_expected.vv │ │ │ ├── types_input.vv │ │ │ ├── union_keep.vv │ │ │ ├── union_with_nested_union_keep.vv │ │ │ ├── unsafe_keep.vv │ │ │ ├── vargs_reference_param_keep.vv │ │ │ ├── vfmt_off_vfmt_on_keep.vv │ │ │ ├── vfmt_off_vfmt_on_with_crlf_expected.vv │ │ │ ├── vfmt_off_vfmt_on_with_crlf_input.vv │ │ │ ├── void_option_keep.vv │ │ │ └── vscript_keep.vv │ │ └── vfmt_on_off.v │ ├── gen/ │ │ ├── c/ │ │ │ ├── array.v │ │ │ ├── assert.v │ │ │ ├── assign.v │ │ │ ├── auto_eq_methods.v │ │ │ ├── auto_free_methods.v │ │ │ ├── auto_str_methods.v │ │ │ ├── autofree.v │ │ │ ├── cgen.v │ │ │ ├── cheaders.v │ │ │ ├── cmain.v │ │ │ ├── comptime.v │ │ │ ├── consts_and_globals.v │ │ │ ├── coutput_test.v │ │ │ ├── coverage.v │ │ │ ├── ctempvars.v │ │ │ ├── defer.v │ │ │ ├── dumpexpr.v │ │ │ ├── embed.v │ │ │ ├── fn.v │ │ │ ├── for.v │ │ │ ├── if.v │ │ │ ├── index.v │ │ │ ├── infix.v │ │ │ ├── json.v │ │ │ ├── live.v │ │ │ ├── match.v │ │ │ ├── orm.v │ │ │ ├── past_tmp_var.v │ │ │ ├── profile.v │ │ │ ├── reflection.v │ │ │ ├── spawn_and_go.v │ │ │ ├── str.v │ │ │ ├── str_intp.v │ │ │ ├── struct.v │ │ │ ├── testdata/ │ │ │ │ ├── README.md │ │ │ │ ├── addition.c.must_have │ │ │ │ ├── addition.out │ │ │ │ ├── addition.vv │ │ │ │ ├── addr.c.must_have │ │ │ │ ├── addr.vv │ │ │ │ ├── addr_from_range.c.must_have │ │ │ │ ├── addr_from_range.out │ │ │ │ ├── addr_from_range.vv │ │ │ │ ├── alias_c_parent_type_decl.c.must_have │ │ │ │ ├── alias_c_parent_type_decl.out │ │ │ │ ├── alias_c_parent_type_decl.vv │ │ │ │ ├── alias_char_ptr_to_ptr.c.must_have │ │ │ │ ├── alias_char_ptr_to_ptr.vv │ │ │ │ ├── alias_interface_method_call.out │ │ │ │ ├── alias_interface_method_call.vv │ │ │ │ ├── alias_of_array_method_call.out │ │ │ │ ├── alias_of_array_method_call.vv │ │ │ │ ├── aligned_attr_gcc_windows.c.must_have │ │ │ │ ├── aligned_attr_gcc_windows.out │ │ │ │ ├── aligned_attr_gcc_windows.vv │ │ │ │ ├── aligned_attr_msvc_windows.c.must_have │ │ │ │ ├── aligned_attr_msvc_windows.out │ │ │ │ ├── aligned_attr_msvc_windows.vv │ │ │ │ ├── aligned_attr_nix.c.must_have │ │ │ │ ├── aligned_attr_nix.out │ │ │ │ ├── aligned_attr_nix.vv │ │ │ │ ├── array_as_interface.out │ │ │ │ ├── array_as_interface.vv │ │ │ │ ├── array_init_no_error.out │ │ │ │ ├── array_init_no_error.vv │ │ │ │ ├── assert_fncalls.c.must_have │ │ │ │ ├── assert_fncalls.out │ │ │ │ ├── assert_fncalls.vv │ │ │ │ ├── assign_fn_addr.c.must_have │ │ │ │ ├── assign_fn_addr.out │ │ │ │ ├── assign_fn_addr.vv │ │ │ │ ├── assigning_and_printing_struct_with_optional_field.out │ │ │ │ ├── assigning_and_printing_struct_with_optional_field.vv │ │ │ │ ├── attr_string_quotes_escape.out │ │ │ │ ├── attr_string_quotes_escape.vv │ │ │ │ ├── autofree_compare_strings_if_expr.c.must_have │ │ │ │ ├── autofree_compare_strings_if_expr.vv │ │ │ │ ├── autofree_ifexpr_arg.out │ │ │ │ ├── autofree_ifexpr_arg.vv │ │ │ │ ├── autofree_json_decode.c.must_have │ │ │ │ ├── autofree_json_decode.vv │ │ │ │ ├── autofree_json_encode.c.must_have │ │ │ │ ├── autofree_json_encode.vv │ │ │ │ ├── autofree_method_chain.c.must_have │ │ │ │ ├── autofree_method_chain.out │ │ │ │ ├── autofree_method_chain.vv │ │ │ │ ├── autofree_mut_array_reassign.out │ │ │ │ ├── autofree_mut_array_reassign.vv │ │ │ │ ├── autofree_nested_interpolation_nix.c.must_have │ │ │ │ ├── autofree_nested_interpolation_nix.out │ │ │ │ ├── autofree_nested_interpolation_nix.vv │ │ │ │ ├── autofree_reused.c.must_have │ │ │ │ ├── autofree_reused.out │ │ │ │ ├── autofree_reused.vv │ │ │ │ ├── autofree_sql_or_block.out │ │ │ │ ├── autofree_sql_or_block.vv │ │ │ │ ├── autofree_toml.c.must_have │ │ │ │ ├── autofree_toml.out │ │ │ │ ├── autofree_toml.vv │ │ │ │ ├── building_multiple_c_sources.out │ │ │ │ ├── building_multiple_c_sources.vv │ │ │ │ ├── builtin_gc_enable_name_clash.c.must_have │ │ │ │ ├── builtin_gc_enable_name_clash.vv │ │ │ │ ├── c_extern_on_C_fn_declarations.c.must_have │ │ │ │ ├── c_extern_on_C_fn_declarations.vv │ │ │ │ ├── c_extern_on_C_global_declarations.c.must_have │ │ │ │ ├── c_extern_on_C_global_declarations.out │ │ │ │ ├── c_extern_on_C_global_declarations.vv │ │ │ │ ├── c_file_for_c_extern.c │ │ │ │ ├── c_ident_for_ptr_arg.c.must_have │ │ │ │ ├── c_ident_for_ptr_arg.vv │ │ │ │ ├── c_varargs.c.must_have │ │ │ │ ├── c_varargs.out │ │ │ │ ├── c_varargs.vv │ │ │ │ ├── callstack.out │ │ │ │ ├── callstack.vv │ │ │ │ ├── check_combination_of_alias_and_sumtype.c.must_have │ │ │ │ ├── check_combination_of_alias_and_sumtype.vv │ │ │ │ ├── closure_shared_lib.c.must_have │ │ │ │ ├── closure_shared_lib.vv │ │ │ │ ├── compare_structs.c.must_have │ │ │ │ ├── compare_structs.vv │ │ │ │ ├── comptime_if.c.must_have │ │ │ │ ├── comptime_if.vv │ │ │ │ ├── comptime_if_attribute_in_test.vv │ │ │ │ ├── comptime_if_attribute_in_test2.c.must_have │ │ │ │ ├── comptime_if_attribute_in_test2.vv │ │ │ │ ├── comptime_if_cond.out │ │ │ │ ├── comptime_if_cond.vv │ │ │ │ ├── comptime_if_top_hash_stmts.c.must_have │ │ │ │ ├── comptime_if_top_hash_stmts.vv │ │ │ │ ├── comptime_interface_field.out │ │ │ │ ├── comptime_interface_field.vv │ │ │ │ ├── comptime_option_call.out │ │ │ │ ├── comptime_option_call.vv │ │ │ │ ├── console_windows_program.c.must_have │ │ │ │ ├── console_windows_program.vv │ │ │ │ ├── const_init_cinit.c.must_have │ │ │ │ ├── const_init_cinit.vv │ │ │ │ ├── const_init_or_block.c.must_have │ │ │ │ ├── const_init_or_block.vv │ │ │ │ ├── const_init_or_block_no_parallel.c.must_have │ │ │ │ ├── const_init_or_block_no_parallel.vv │ │ │ │ ├── const_none_memdup.c.must_have │ │ │ │ ├── const_none_memdup.out │ │ │ │ ├── const_none_memdup.vv │ │ │ │ ├── const_references.c.must_have │ │ │ │ ├── const_references.out │ │ │ │ ├── const_references.vv │ │ │ │ ├── cross_printfn_v_malloc.c.must_have │ │ │ │ ├── cross_printfn_v_malloc.out │ │ │ │ ├── cross_printfn_v_malloc.vv │ │ │ │ ├── div_by_zero_is_zero.c.must_have │ │ │ │ ├── div_by_zero_is_zero.out │ │ │ │ ├── div_by_zero_is_zero.vv │ │ │ │ ├── dump_fixed_array.c.must_have │ │ │ │ ├── dump_fixed_array.vv │ │ │ │ ├── embed.c.must_have │ │ │ │ ├── embed.vv │ │ │ │ ├── embed_with_prod.c.must_have │ │ │ │ ├── embed_with_prod.out │ │ │ │ ├── embed_with_prod.vv │ │ │ │ ├── embed_with_prod_and_several_decoders.c.must_have │ │ │ │ ├── embed_with_prod_and_several_decoders.out │ │ │ │ ├── embed_with_prod_and_several_decoders.vv │ │ │ │ ├── embed_with_prod_zlib.c.must_have │ │ │ │ ├── embed_with_prod_zlib.out │ │ │ │ ├── embed_with_prod_zlib.vv │ │ │ │ ├── enum_switch_case.c.must_have │ │ │ │ ├── enum_switch_case.out │ │ │ │ ├── enum_switch_case.vv │ │ │ │ ├── export_and_weak.c.must_have │ │ │ │ ├── export_and_weak.out │ │ │ │ ├── export_and_weak.vv │ │ │ │ ├── fixed_arr_compare.c.must_have │ │ │ │ ├── fixed_arr_compare.vv │ │ │ │ ├── fixed_arr_const_unsafe.c.must_have │ │ │ │ ├── fixed_arr_const_unsafe.vv │ │ │ │ ├── fixed_arr_multi_dim_opt_elem.out │ │ │ │ ├── fixed_arr_multi_dim_opt_elem.vv │ │ │ │ ├── fixed_arr_multi_dim_opt_elem_markused.out │ │ │ │ ├── fixed_arr_multi_dim_opt_elem_markused.vv │ │ │ │ ├── for_in.c.must_have │ │ │ │ ├── for_in.out │ │ │ │ ├── for_in.vv │ │ │ │ ├── for_in_side_effect.out │ │ │ │ ├── for_in_side_effect.vv │ │ │ │ ├── free_array_of_strings.c.must_have │ │ │ │ ├── free_array_of_strings.out │ │ │ │ ├── free_array_of_strings.vv │ │ │ │ ├── free_for_struct_with_c_fields.c.must_have │ │ │ │ ├── free_for_struct_with_c_fields.out │ │ │ │ ├── free_for_struct_with_c_fields.vv │ │ │ │ ├── freestanding_define/ │ │ │ │ │ ├── a_d_freestanding.c.v │ │ │ │ │ └── a_notd_freestanding.c.v │ │ │ │ ├── freestanding_module_import_1.out │ │ │ │ ├── freestanding_module_import_1.vv │ │ │ │ ├── freestanding_module_import_2.out │ │ │ │ ├── freestanding_module_import_2.vv │ │ │ │ ├── func_type_dependency.c.must_have │ │ │ │ ├── func_type_dependency.vv │ │ │ │ ├── gen_expr_to_string_with_call_and_return_ref.out │ │ │ │ ├── gen_expr_to_string_with_call_and_return_ref.vv │ │ │ │ ├── global_export_nix.c.must_have │ │ │ │ ├── global_export_nix.vv │ │ │ │ ├── global_initializer_nix.c.must_have │ │ │ │ ├── global_initializer_nix.vv │ │ │ │ ├── global_initializer_windows.must_have │ │ │ │ ├── global_initializer_windows.vv │ │ │ │ ├── globals_with_weak_tag.c.must_have │ │ │ │ ├── globals_with_weak_tag.vv │ │ │ │ ├── gui_windows_program.c.must_have │ │ │ │ ├── gui_windows_program.vv │ │ │ │ ├── gui_windows_program_with_console_tag.c.must_have │ │ │ │ ├── gui_windows_program_with_console_tag.vv │ │ │ │ ├── hw.c.must_have │ │ │ │ ├── hw.out │ │ │ │ ├── hw.vv │ │ │ │ ├── if_define_check_not_set.out │ │ │ │ ├── if_define_check_not_set.vv │ │ │ │ ├── if_define_check_set.out │ │ │ │ ├── if_define_check_set.vv │ │ │ │ ├── if_else_return.c.must_have │ │ │ │ ├── if_else_return.out │ │ │ │ ├── if_else_return.vv │ │ │ │ ├── iface_method_order.c.must_have │ │ │ │ ├── iface_method_order.vv │ │ │ │ ├── ignore_overflow_tag_check.out │ │ │ │ ├── ignore_overflow_tag_check.vv │ │ │ │ ├── init_fn_with_if_attr_defined.c.must_have │ │ │ │ ├── init_fn_with_if_attr_defined.out │ │ │ │ ├── init_fn_with_if_attr_defined.vv │ │ │ │ ├── init_fn_with_if_attr_not_defined.c.must_have │ │ │ │ ├── init_fn_with_if_attr_not_defined.out │ │ │ │ ├── init_fn_with_if_attr_not_defined.vv │ │ │ │ ├── interface_auto_free.c.must_have │ │ │ │ ├── interface_auto_free.vv │ │ │ │ ├── json_option_time.out │ │ │ │ ├── json_option_time.vv │ │ │ │ ├── linker_section_nix.c.must_have │ │ │ │ ├── linker_section_nix.vv │ │ │ │ ├── literal_c_variadic_arg.out │ │ │ │ ├── literal_c_variadic_arg.vv │ │ │ │ ├── logical_and_short_circuit.must_have │ │ │ │ ├── logical_and_short_circuit.out │ │ │ │ ├── logical_and_short_circuit.vv │ │ │ │ ├── memdup_used_by_program_with_struct_option_fields.c.must_have │ │ │ │ ├── memdup_used_by_program_with_struct_option_fields.vv │ │ │ │ ├── minify_enum_unsigned_not_msvc_windows.c.must_have │ │ │ │ ├── minify_enum_unsigned_not_msvc_windows.out │ │ │ │ ├── minify_enum_unsigned_not_msvc_windows.vv │ │ │ │ ├── minify_option_field_not_msvc_windows.c.must_have │ │ │ │ ├── minify_option_field_not_msvc_windows.out │ │ │ │ ├── minify_option_field_not_msvc_windows.vv │ │ │ │ ├── multi_return_ignored_if_guard.out │ │ │ │ ├── multi_return_ignored_if_guard.vv │ │ │ │ ├── multiple_c_cources/ │ │ │ │ │ ├── common.h │ │ │ │ │ ├── file1.c │ │ │ │ │ ├── file2.c │ │ │ │ │ ├── file3.c │ │ │ │ │ ├── sources.v │ │ │ │ │ └── v.mod │ │ │ │ ├── mutable_receiver_type_mapping.out │ │ │ │ ├── mutable_receiver_type_mapping.vv │ │ │ │ ├── none_literal_str.out │ │ │ │ ├── none_literal_str.vv │ │ │ │ ├── os_specific_hash_stmts.c.must_have │ │ │ │ ├── os_specific_hash_stmts.vv │ │ │ │ ├── platform_wrapper/ │ │ │ │ │ ├── file_default.c.v │ │ │ │ │ ├── file_linux.c.v │ │ │ │ │ ├── file_macos.c.v │ │ │ │ │ ├── file_wasm32_emscripten.c.v │ │ │ │ │ └── file_windows.c.v │ │ │ │ ├── platform_wrapper_emscripten.c.must_have │ │ │ │ ├── platform_wrapper_emscripten.vv │ │ │ │ ├── platform_wrapper_non_emscripten.out │ │ │ │ ├── platform_wrapper_non_emscripten.vv │ │ │ │ ├── postinclude_example.out │ │ │ │ ├── postinclude_example.vv │ │ │ │ ├── postinclude_header.h │ │ │ │ ├── preinclude_example.out │ │ │ │ ├── preinclude_example.vv │ │ │ │ ├── preinclude_example_changed_order.out │ │ │ │ ├── preinclude_example_changed_order.vv │ │ │ │ ├── preinclude_header.h │ │ │ │ ├── preinclude_header2.h │ │ │ │ ├── ref_sumtype_map_as_struct_field.out │ │ │ │ ├── ref_sumtype_map_as_struct_field.vv │ │ │ │ ├── self_printer_with_prod.out │ │ │ │ ├── self_printer_with_prod.vv │ │ │ │ ├── spawn_call_fn_struct_field.out │ │ │ │ ├── spawn_call_fn_struct_field.vv │ │ │ │ ├── spawn_stack_nix.c.must_have │ │ │ │ ├── spawn_stack_nix.out │ │ │ │ ├── spawn_stack_nix.vv │ │ │ │ ├── spawn_stack_windows.c.must_have │ │ │ │ ├── spawn_stack_windows.out │ │ │ │ ├── spawn_stack_windows.vv │ │ │ │ ├── string_escapes_and_quoting_issue_25304_1.out │ │ │ │ ├── string_escapes_and_quoting_issue_25304_1.vv │ │ │ │ ├── string_escapes_and_quoting_issue_25304_2.out │ │ │ │ ├── string_escapes_and_quoting_issue_25304_2.vv │ │ │ │ ├── string_index_method_ptr_receiver.c.must_have │ │ │ │ ├── string_index_method_ptr_receiver.vv │ │ │ │ ├── strlit_len_optimization.c.must_have │ │ │ │ ├── strlit_len_optimization.out │ │ │ │ ├── strlit_len_optimization.vv │ │ │ │ ├── struct_field_free.out │ │ │ │ ├── struct_field_free.vv │ │ │ │ ├── struct_field_result_init.c.must_have │ │ │ │ ├── struct_field_result_init.out │ │ │ │ ├── struct_field_result_init.vv │ │ │ │ ├── struct_fn_member_print.c.must_have │ │ │ │ ├── struct_fn_member_print.out │ │ │ │ ├── struct_fn_member_print.vv │ │ │ │ ├── sumtype_pass_by_reference.out │ │ │ │ ├── sumtype_pass_by_reference.vv │ │ │ │ ├── sumtype_struct_depend_order.out │ │ │ │ ├── sumtype_struct_depend_order.vv │ │ │ │ ├── translated/ │ │ │ │ │ ├── sym.c │ │ │ │ │ ├── translated_module_actual.v │ │ │ │ │ └── v.mod │ │ │ │ ├── translated_const_fixed_array.out │ │ │ │ ├── translated_const_fixed_array.vv │ │ │ │ ├── translated_module.c.must_have │ │ │ │ ├── translated_module.out │ │ │ │ ├── translated_module.vv │ │ │ │ ├── unused_import_aliased_as_underscore.c.must_have │ │ │ │ ├── unused_import_aliased_as_underscore.vv │ │ │ │ ├── unused_result_err.c.must_have │ │ │ │ ├── unused_result_err.vv │ │ │ │ ├── use_flag_comptime_values.out │ │ │ │ ├── use_flag_comptime_values.vv │ │ │ │ ├── use_flag_comptime_with_if.out │ │ │ │ ├── use_flag_comptime_with_if.vv │ │ │ │ ├── volatile.c.must_have │ │ │ │ ├── volatile.out │ │ │ │ ├── volatile.vv │ │ │ │ ├── waiter_fns_gen_nix.c.must_have │ │ │ │ ├── waiter_fns_gen_nix.vv │ │ │ │ ├── waiter_fns_gen_windows.c.must_have │ │ │ │ └── waiter_fns_gen_windows.vv │ │ │ ├── text_manipulation.v │ │ │ └── utils.v │ │ ├── golang/ │ │ │ ├── attrs.v │ │ │ ├── golang.v │ │ │ ├── struct.v │ │ │ └── tests/ │ │ │ ├── array.go.vv │ │ │ ├── array.go.vv.out │ │ │ ├── golang_test.v │ │ │ ├── simple.go.vv │ │ │ ├── simple.go.vv.out │ │ │ ├── string.go.vv │ │ │ └── string.go.vv.out │ │ ├── js/ │ │ │ ├── README.md │ │ │ ├── array.v │ │ │ ├── auto_eq_methods.v │ │ │ ├── auto_str_methods.v │ │ │ ├── builtin_types.v │ │ │ ├── comptime.v │ │ │ ├── deep_copy.v │ │ │ ├── fast_deep_equal.js │ │ │ ├── fn.v │ │ │ ├── infix.v │ │ │ ├── js.v │ │ │ ├── jsdoc.v │ │ │ ├── jsgen_test.v │ │ │ ├── map.v │ │ │ ├── program_test.v │ │ │ ├── sourcemap/ │ │ │ │ ├── basic_test.v │ │ │ │ ├── compare_test.v │ │ │ │ ├── mappings.v │ │ │ │ ├── sets.v │ │ │ │ ├── source_map.v │ │ │ │ ├── source_map_generator.v │ │ │ │ └── vlq/ │ │ │ │ ├── vlq.v │ │ │ │ ├── vlq_decode_test.v │ │ │ │ └── vlq_encode_test.v │ │ │ ├── str.v │ │ │ ├── temp_fast_deep_equal.v │ │ │ ├── tests/ │ │ │ │ ├── .gitignore │ │ │ │ ├── alias.v │ │ │ │ ├── array.v │ │ │ │ ├── auto_deref_args.v │ │ │ │ ├── callback.v │ │ │ │ ├── casting.v │ │ │ │ ├── enum.v │ │ │ │ ├── hello/ │ │ │ │ │ ├── hello.js.v │ │ │ │ │ ├── hello.v │ │ │ │ │ └── hello1/ │ │ │ │ │ └── hello1.v │ │ │ │ ├── interface.v │ │ │ │ ├── interp.v │ │ │ │ ├── js.v │ │ │ │ ├── life.v │ │ │ │ ├── map.v │ │ │ │ ├── option.v │ │ │ │ ├── simple.v │ │ │ │ ├── simple_sourcemap.v │ │ │ │ ├── string.v │ │ │ │ ├── struct.v │ │ │ │ ├── testdata/ │ │ │ │ │ ├── byte_is_space.out │ │ │ │ │ ├── byte_is_space.v │ │ │ │ │ ├── compare_ints.out │ │ │ │ │ ├── compare_ints.v │ │ │ │ │ ├── hw.out │ │ │ │ │ ├── hw.v │ │ │ │ │ ├── match.out │ │ │ │ │ ├── match.v │ │ │ │ │ ├── overloading.out │ │ │ │ │ ├── overloading.v │ │ │ │ │ ├── string.out │ │ │ │ │ ├── string.v │ │ │ │ │ ├── string_methods.out │ │ │ │ │ ├── string_methods.v │ │ │ │ │ ├── u16.out │ │ │ │ │ ├── u16.v │ │ │ │ │ ├── u32.out │ │ │ │ │ ├── u32.v │ │ │ │ │ ├── u64.out │ │ │ │ │ └── u64.v │ │ │ │ └── unsafe.v │ │ │ └── util.v │ │ ├── native/ │ │ │ ├── amd64.v │ │ │ ├── arm64.v │ │ │ ├── array.v │ │ │ ├── blacklist.v │ │ │ ├── builtins.v │ │ │ ├── comptime.v │ │ │ ├── dos.v │ │ │ ├── elf.v │ │ │ ├── expr.v │ │ │ ├── gen.v │ │ │ ├── macho.v │ │ │ ├── macho_test.v │ │ │ ├── pe.v │ │ │ ├── readdll.c.v │ │ │ ├── stmt.c.v │ │ │ ├── syscall.v │ │ │ └── tests/ │ │ │ ├── arrays.vv │ │ │ ├── arrays.vv.out │ │ │ ├── asm.vv │ │ │ ├── asm.vv.out │ │ │ ├── assert.vv │ │ │ ├── assert.vv.out │ │ │ ├── assign.vv │ │ │ ├── assign.vv.out │ │ │ ├── atexpr.vv │ │ │ ├── atexpr.vv.out │ │ │ ├── builtin.vv │ │ │ ├── builtin.vv.out │ │ │ ├── compare.vv │ │ │ ├── compare.vv.out │ │ │ ├── comptime.vv │ │ │ ├── comptime.vv.out │ │ │ ├── defer.vv │ │ │ ├── defer.vv.out │ │ │ ├── enum.vv │ │ │ ├── enum.vv.out │ │ │ ├── expressions.vv │ │ │ ├── expressions.vv.out │ │ │ ├── fibonacci_native.vv │ │ │ ├── fibonacci_native.vv.out │ │ │ ├── float.vv │ │ │ ├── float.vv.out │ │ │ ├── for.vv │ │ │ ├── for.vv.out │ │ │ ├── general.vv │ │ │ ├── general.vv.out │ │ │ ├── hello.vv │ │ │ ├── hello.vv.out │ │ │ ├── ifs.vv │ │ │ ├── ifs.vv.out │ │ │ ├── inc.vv │ │ │ ├── inc.vv.out │ │ │ ├── libc.vv │ │ │ ├── libc.vv.out │ │ │ ├── linux.vv │ │ │ ├── linux.vv.out │ │ │ ├── match.vv │ │ │ ├── match.vv.out │ │ │ ├── method.vv │ │ │ ├── method.vv.out │ │ │ ├── multi_assign.vv │ │ │ ├── multi_assign.vv.out │ │ │ ├── native_test.v │ │ │ ├── new_transformer.vv │ │ │ ├── new_transformer.vv.out │ │ │ ├── pointers.vv │ │ │ ├── pointers.vv.out │ │ │ ├── print.vv │ │ │ ├── print.vv.err │ │ │ ├── print.vv.out │ │ │ ├── simple_fn_calls.vv │ │ │ ├── simple_fn_calls.vv.out │ │ │ ├── string.vv │ │ │ ├── string.vv.out │ │ │ ├── struct.vv │ │ │ ├── struct.vv.out │ │ │ ├── struct_with_fn.vv │ │ │ ├── struct_with_fn.vv.out │ │ │ ├── sumcall.vv │ │ │ ├── sumcall.vv.out │ │ │ ├── typeof.vv │ │ │ ├── typeof.vv.out │ │ │ ├── vtest_int_cmp.vv │ │ │ └── vtest_int_cmp.vv.out │ │ └── wasm/ │ │ ├── asm.v │ │ ├── comptime.v │ │ ├── gen.v │ │ ├── mem.v │ │ ├── ops.v │ │ ├── serialise/ │ │ │ ├── alignment_test.v │ │ │ └── serialise.v │ │ ├── tests/ │ │ │ ├── arith.vv │ │ │ ├── arith.vv.out │ │ │ ├── arrays.vv │ │ │ ├── arrays.vv.out │ │ │ ├── asm.vv │ │ │ ├── asm.vv.out │ │ │ ├── builtin.vv │ │ │ ├── builtin.vv.out │ │ │ ├── cast.vv │ │ │ ├── cast.vv.out │ │ │ ├── comptime.vv │ │ │ ├── comptime.vv.out │ │ │ ├── control_flow.vv │ │ │ ├── control_flow.vv.out │ │ │ ├── for_in_range.vv │ │ │ ├── for_in_range.vv.out │ │ │ ├── labeled_for_inc.vv │ │ │ ├── labeled_for_inc.vv.out │ │ │ ├── match.vv │ │ │ ├── match.vv.out │ │ │ ├── match_ranges.vv │ │ │ ├── match_ranges.vv.out │ │ │ ├── misc.vv │ │ │ ├── misc.vv.out │ │ │ ├── multi_expr.vv │ │ │ ├── multi_expr.vv.out │ │ │ ├── structs.vv │ │ │ ├── structs.vv.out │ │ │ ├── wasi_api.vv │ │ │ ├── wasi_api.vv.out │ │ │ └── wasm_test.v │ │ └── tests_decompile/ │ │ ├── must_have_test.v │ │ ├── pub_exports_work_for_wasi_os_target.vv │ │ └── pub_exports_work_for_wasi_os_target.wasm.must_have │ ├── generics/ │ │ ├── generics.v │ │ └── new_generics_regression_test.v │ ├── help/ │ │ ├── FORMATTING.md │ │ ├── build/ │ │ │ ├── build-c.txt │ │ │ ├── build-js.txt │ │ │ ├── build-native.txt │ │ │ ├── build-wasm.txt │ │ │ └── build.txt │ │ ├── common/ │ │ │ ├── common.txt │ │ │ ├── crun.txt │ │ │ ├── doc.txt │ │ │ ├── fmt.txt │ │ │ ├── missdoc.txt │ │ │ ├── repl.txt │ │ │ ├── run.txt │ │ │ ├── test.txt │ │ │ ├── vet.txt │ │ │ ├── watch.txt │ │ │ └── where.txt │ │ ├── default.txt │ │ ├── help.v │ │ ├── help_test.v │ │ ├── installation/ │ │ │ ├── installation.txt │ │ │ ├── self.txt │ │ │ ├── symlink.txt │ │ │ ├── up.txt │ │ │ └── version.txt │ │ ├── other/ │ │ │ ├── ast.txt │ │ │ ├── bin2v.txt │ │ │ ├── bump.txt │ │ │ ├── check-md.txt │ │ │ ├── complete.txt │ │ │ ├── doctor.txt │ │ │ ├── download.txt │ │ │ ├── git-fmt-hook.txt │ │ │ ├── gret.txt │ │ │ ├── ls.txt │ │ │ ├── other.txt │ │ │ ├── reduce.txt │ │ │ ├── repeat.txt │ │ │ ├── retry.txt │ │ │ ├── shader.txt │ │ │ ├── share.txt │ │ │ ├── time.txt │ │ │ └── tracev.txt │ │ ├── scaffolding/ │ │ │ └── scaffolding.txt │ │ └── vpm/ │ │ ├── install.txt │ │ ├── link.txt │ │ ├── list.txt │ │ ├── outdated.txt │ │ ├── remove.txt │ │ ├── search.txt │ │ ├── show.txt │ │ ├── unlink.txt │ │ ├── update.txt │ │ ├── upgrade.txt │ │ └── vpm.txt │ ├── live/ │ │ ├── common.c.v │ │ ├── executable/ │ │ │ └── reloader.c.v │ │ ├── live_test.v │ │ ├── live_test_template.vv │ │ ├── live_test_template_main.vv │ │ └── sharedlib/ │ │ └── live_sharedlib.v │ ├── markused/ │ │ ├── markused.v │ │ └── walker.v │ ├── mathutil/ │ │ ├── mathutil.v │ │ └── mathutil_test.v │ ├── parser/ │ │ ├── asm.v │ │ ├── assign.v │ │ ├── attribute.v │ │ ├── checks.v │ │ ├── codegen.v │ │ ├── comptime.v │ │ ├── containers.v │ │ ├── enum.v │ │ ├── expr.v │ │ ├── fn.v │ │ ├── for.v │ │ ├── if_match.v │ │ ├── lock.v │ │ ├── messages.v │ │ ├── module.v │ │ ├── orm.v │ │ ├── parse_file_spawn_execute_regression_test.v │ │ ├── parse_type.v │ │ ├── parser.v │ │ ├── struct.v │ │ ├── testdata/ │ │ │ ├── silent/ │ │ │ │ ├── orm_infinite_loop_in_parser_sql_stmt.vv │ │ │ │ ├── radamsa_invalid_108093448084708208784587_vfmt_off.vv │ │ │ │ ├── radamsa_invalid_prinln_invalid_utf8_vfmt_off.vv │ │ │ │ ├── radamsa_invalid_prinln_nonsense_vfmt_off.vv │ │ │ │ ├── radamsa_too_many_nested_exprs_vfmt_off.vv.txt │ │ │ │ └── radamsa_too_many_nested_generic_types_vfmt_off.vv.txt │ │ │ └── stdout/ │ │ │ └── .gitkeep │ │ ├── tests/ │ │ │ ├── README.md │ │ │ ├── already_existing_sym_err.out │ │ │ ├── already_existing_sym_err.vv │ │ │ ├── anon_fn_return_type.out │ │ │ ├── anon_fn_return_type.vv │ │ │ ├── anon_sum_type_interface.out │ │ │ ├── anon_sum_type_interface.vv │ │ │ ├── anon_sum_type_multi_return_err.out │ │ │ ├── anon_sum_type_multi_return_err.vv │ │ │ ├── anon_sum_type_receiver_err.out │ │ │ ├── anon_sum_type_receiver_err.vv │ │ │ ├── anon_sum_type_struct.out │ │ │ ├── anon_sum_type_struct.vv │ │ │ ├── anon_unused_param.out │ │ │ ├── anon_unused_param.vv │ │ │ ├── argumented_op_overloading_fn_decl_err.out │ │ │ ├── argumented_op_overloading_fn_decl_err.vv │ │ │ ├── argumented_op_overloading_fn_op_overloaded_decl_err.out │ │ │ ├── argumented_op_overloading_fn_op_overloaded_decl_err.vv │ │ │ ├── array_decl_type_alias_err.out │ │ │ ├── array_decl_type_alias_err.vv │ │ │ ├── array_decl_type_err.out │ │ │ ├── array_decl_type_err.vv │ │ │ ├── array_decl_type_struct_field_err.out │ │ │ ├── array_decl_type_struct_field_err.vv │ │ │ ├── array_init.out │ │ │ ├── array_init.vv │ │ │ ├── array_init_given_len_not_given_err.out │ │ │ ├── array_init_given_len_not_given_err.vv │ │ │ ├── array_init_parenthesized_optional_elem_type.out │ │ │ ├── array_init_parenthesized_optional_elem_type.vv │ │ │ ├── array_pos_err.out │ │ │ ├── array_pos_err.vv │ │ │ ├── atomic_blank_ident_err.out │ │ │ ├── atomic_blank_ident_err.vv │ │ │ ├── attribute_call_syntax.out │ │ │ ├── attribute_call_syntax.vv │ │ │ ├── builtin_alias_type_name_err.out │ │ │ ├── builtin_alias_type_name_err.vv │ │ │ ├── builtin_enum_type_name_err.out │ │ │ ├── builtin_enum_type_name_err.vv │ │ │ ├── builtin_sum_type_type_name_err.out │ │ │ ├── builtin_sum_type_type_name_err.vv │ │ │ ├── c_struct_no_embed.out │ │ │ ├── c_struct_no_embed.vv │ │ │ ├── chan_no_type_array_fn_arg_err.out │ │ │ ├── chan_no_type_array_fn_arg_err.vv │ │ │ ├── chan_no_type_err.out │ │ │ ├── chan_no_type_err.vv │ │ │ ├── chan_no_type_fn_arg_err.out │ │ │ ├── chan_no_type_fn_arg_err.vv │ │ │ ├── chan_no_type_map_fn_arg_err.out │ │ │ ├── chan_no_type_map_fn_arg_err.vv │ │ │ ├── chan_no_type_option_err.out │ │ │ ├── chan_no_type_option_err.vv │ │ │ ├── chan_no_type_ref_err.out │ │ │ ├── chan_no_type_ref_err.vv │ │ │ ├── check_undefined_variables_too_deep_nested.out │ │ │ ├── check_undefined_variables_too_deep_nested.vv │ │ │ ├── closure_not_declared.out │ │ │ ├── closure_not_declared.vv │ │ │ ├── closure_not_used.out │ │ │ ├── closure_not_used.vv │ │ │ ├── closure_undefined_var.out │ │ │ ├── closure_undefined_var.vv │ │ │ ├── closure_var_name_conflict.out │ │ │ ├── closure_var_name_conflict.vv │ │ │ ├── comptime_for_invalid_expr_err.out │ │ │ ├── comptime_for_invalid_expr_err.vv │ │ │ ├── comptime_path_not_found_err.out │ │ │ ├── comptime_path_not_found_err.vv │ │ │ ├── comptime_unknown_meta_kind_err.out │ │ │ ├── comptime_unknown_meta_kind_err.vv │ │ │ ├── comptime_veb_without_import_veb_err.out │ │ │ ├── comptime_veb_without_import_veb_err.vv │ │ │ ├── comptime_vweb_without_import_vweb_err.out │ │ │ ├── comptime_vweb_without_import_vweb_err.vv │ │ │ ├── const_decl_err.out │ │ │ ├── const_decl_err.vv │ │ │ ├── const_index.out │ │ │ ├── const_index.vv │ │ │ ├── const_missing_rpar_a.out │ │ │ ├── const_missing_rpar_a.vv │ │ │ ├── const_missing_rpar_b.out │ │ │ ├── const_missing_rpar_b.vv │ │ │ ├── const_only_keyword.out │ │ │ ├── const_only_keyword.vv │ │ │ ├── const_unexpected_eof.out │ │ │ ├── const_unexpected_eof.vv │ │ │ ├── dec_use_as_value.out │ │ │ ├── dec_use_as_value.vv │ │ │ ├── declare_static_fn_as_receiver_method_err.out │ │ │ ├── declare_static_fn_as_receiver_method_err.vv │ │ │ ├── defer_propagate.out │ │ │ ├── defer_propagate.vv │ │ │ ├── defer_propagate2.out │ │ │ ├── defer_propagate2.vv │ │ │ ├── defer_return.out │ │ │ ├── defer_return.vv │ │ │ ├── defer_return2.out │ │ │ ├── defer_return2.vv │ │ │ ├── deprecated_after_without_deprecated.out │ │ │ ├── deprecated_after_without_deprecated.vv │ │ │ ├── dollar_err.out │ │ │ ├── dollar_err.vv │ │ │ ├── duplicate_field_embed_err.out │ │ │ ├── duplicate_field_embed_err.vv │ │ │ ├── duplicate_operator_overload_err.out │ │ │ ├── duplicate_operator_overload_err.vv │ │ │ ├── duplicate_type_a.out │ │ │ ├── duplicate_type_a.vv │ │ │ ├── duplicate_type_b.out │ │ │ ├── duplicate_type_b.vv │ │ │ ├── duplicated_generic_err.out │ │ │ ├── duplicated_generic_err.vv │ │ │ ├── embedded_struct_attribute_err.out │ │ │ ├── embedded_struct_attribute_err.vv │ │ │ ├── empty_name_expr_err.out │ │ │ ├── empty_name_expr_err.vv │ │ │ ├── enum_method_duplicated_err.out │ │ │ ├── enum_method_duplicated_err.vv │ │ │ ├── expected_type_enum_err.out │ │ │ ├── expected_type_enum_err.vv │ │ │ ├── expecting_assign_type_alias.out │ │ │ ├── expecting_assign_type_alias.vv │ │ │ ├── expecting_type_declaration_for_new_attribute_field_followed_by_enum_default_value.out │ │ │ ├── expecting_type_declaration_for_new_attribute_field_followed_by_enum_default_value.vv │ │ │ ├── export_interop_func_err.out │ │ │ ├── export_interop_func_err.vv │ │ │ ├── expr_evaluated_but_not_used_a.out │ │ │ ├── expr_evaluated_but_not_used_a.vv │ │ │ ├── expr_evaluated_but_not_used_b.out │ │ │ ├── expr_evaluated_but_not_used_b.vv │ │ │ ├── expr_evaluated_but_not_used_c.out │ │ │ ├── expr_evaluated_but_not_used_c.vv │ │ │ ├── expr_evaluated_but_not_used_d.out │ │ │ ├── expr_evaluated_but_not_used_d.vv │ │ │ ├── expr_evaluated_but_not_used_e.out │ │ │ ├── expr_evaluated_but_not_used_e.vv │ │ │ ├── expr_evaluated_but_not_used_if.out │ │ │ ├── expr_evaluated_but_not_used_if.vv │ │ │ ├── expr_evaluated_but_not_used_or.out │ │ │ ├── expr_evaluated_but_not_used_or.vv │ │ │ ├── fixed_arr_len_cap_attr_err.out │ │ │ ├── fixed_arr_len_cap_attr_err.vv │ │ │ ├── fixed_array_init_result_err.out │ │ │ ├── fixed_array_init_result_err.vv │ │ │ ├── fixed_array_size_using_non_constant_err.out │ │ │ ├── fixed_array_size_using_non_constant_err.vv │ │ │ ├── fn_alias_arg_variadic_mut_err.out │ │ │ ├── fn_alias_arg_variadic_mut_err.vv │ │ │ ├── fn_arg_variadic_mut_err.out │ │ │ ├── fn_arg_variadic_mut_err.vv │ │ │ ├── fn_attributes_duplicate_multiple.out │ │ │ ├── fn_attributes_duplicate_multiple.vv │ │ │ ├── fn_attributes_duplicate_single.out │ │ │ ├── fn_attributes_duplicate_single.vv │ │ │ ├── fn_attributes_empty_err.out │ │ │ ├── fn_attributes_empty_err.vv │ │ │ ├── fn_body_start_pos.out │ │ │ ├── fn_body_start_pos.vv │ │ │ ├── fn_call_args_without_comma_1_err.out │ │ │ ├── fn_call_args_without_comma_1_err.vv │ │ │ ├── fn_call_args_without_comma_2_err.out │ │ │ ├── fn_call_args_without_comma_2_err.vv │ │ │ ├── fn_call_unexpected_eof_comma_multi_arg_err.out │ │ │ ├── fn_call_unexpected_eof_comma_multi_arg_err.vv │ │ │ ├── fn_call_unexpected_eof_rpar_after_fn_arg_err.out │ │ │ ├── fn_call_unexpected_eof_rpar_after_fn_arg_err.vv │ │ │ ├── fn_call_unexpected_eof_rpar_err.out │ │ │ ├── fn_call_unexpected_eof_rpar_err.vv │ │ │ ├── fn_call_unexpected_eof_rpar_multi_arg_too_many_err.out │ │ │ ├── fn_call_unexpected_eof_rpar_multi_arg_too_many_err.vv │ │ │ ├── fn_call_unexpected_eof_rpar_multi_line_err.out │ │ │ ├── fn_call_unexpected_eof_rpar_multi_line_err.vv │ │ │ ├── fn_call_unexpected_eof_rpar_too_many_err.out │ │ │ ├── fn_call_unexpected_eof_rpar_too_many_err.vv │ │ │ ├── fn_decl_invalid_body_opener_lsbr_err.out │ │ │ ├── fn_decl_invalid_body_opener_lsbr_err.vv │ │ │ ├── fn_decl_multi_return_types_err.out │ │ │ ├── fn_decl_multi_return_types_err.vv │ │ │ ├── fn_decl_return_type_err_a.out │ │ │ ├── fn_decl_return_type_err_a.vv │ │ │ ├── fn_decl_return_type_err_b.out │ │ │ ├── fn_decl_return_type_err_b.vv │ │ │ ├── fn_decl_unexpected_eof.out │ │ │ ├── fn_decl_unexpected_eof.vv │ │ │ ├── fn_param_name_cap.out │ │ │ ├── fn_param_name_cap.vv │ │ │ ├── fn_type_decl_same_return_type.out │ │ │ ├── fn_type_decl_same_return_type.vv │ │ │ ├── fn_type_del_same_param_type.out │ │ │ ├── fn_type_del_same_param_type.vv │ │ │ ├── fn_type_only_args_in_interfaces.out │ │ │ ├── fn_type_only_args_in_interfaces.vv │ │ │ ├── fn_type_only_args_no_body.out │ │ │ ├── fn_type_only_args_no_body.vv │ │ │ ├── fn_type_only_args_unknown_name.out │ │ │ ├── fn_type_only_args_unknown_name.vv │ │ │ ├── fn_use_builtin_err.out │ │ │ ├── fn_use_builtin_err.vv │ │ │ ├── for_in_mut_index_of_array.out │ │ │ ├── for_in_mut_index_of_array.vv │ │ │ ├── for_in_mut_key_of_map.out │ │ │ ├── for_in_mut_key_of_map.vv │ │ │ ├── for_index_in_range.out │ │ │ ├── for_index_in_range.vv │ │ │ ├── for_mut_in_range.out │ │ │ ├── for_mut_in_range.vv │ │ │ ├── for_val_in_array_err.out │ │ │ ├── for_val_in_array_err.vv │ │ │ ├── forbidden_language_support_c.c.out │ │ │ ├── forbidden_language_support_c.c.vv │ │ │ ├── forbidden_language_support_js.js.out │ │ │ ├── forbidden_language_support_js.js.vv │ │ │ ├── forbidden_language_support_js.out │ │ │ ├── function_prototype_in_struct.out │ │ │ ├── function_prototype_in_struct.vv │ │ │ ├── function_variadic_arg_non_final.out │ │ │ ├── function_variadic_arg_non_final.vv │ │ │ ├── generic_fn_export_err.out │ │ │ ├── generic_fn_export_err.vv │ │ │ ├── generic_fn_type_decl_err.out │ │ │ ├── generic_fn_type_decl_err.vv │ │ │ ├── generic_imp_symbol_struct_field_err.out │ │ │ ├── generic_imp_symbol_struct_field_err.vv │ │ │ ├── generic_interface_decl_err.out │ │ │ ├── generic_interface_decl_err.vv │ │ │ ├── generic_lowercase_err.out │ │ │ ├── generic_lowercase_err.vv │ │ │ ├── generic_return_invalid_err.out │ │ │ ├── generic_return_invalid_err.vv │ │ │ ├── generic_struct_parameter_err.out │ │ │ ├── generic_struct_parameter_err.vv │ │ │ ├── generic_struct_type_decl_err.out │ │ │ ├── generic_struct_type_decl_err.vv │ │ │ ├── generic_struct_type_using_multi_return_err.out │ │ │ ├── generic_struct_type_using_multi_return_err.vv │ │ │ ├── generic_symbol_err.out │ │ │ ├── generic_symbol_err.vv │ │ │ ├── generic_type_alias_decl.out │ │ │ ├── generic_type_alias_decl.vv │ │ │ ├── global_reserved_name_err.out │ │ │ ├── global_reserved_name_err.vv │ │ │ ├── hash_empty_flag_value.out │ │ │ ├── hash_empty_flag_value.vv │ │ │ ├── if_guard_cond_err.out │ │ │ ├── if_guard_cond_err.vv │ │ │ ├── if_guard_redefinition.out │ │ │ ├── if_guard_redefinition.vv │ │ │ ├── if_guard_undefined_variable_err.out │ │ │ ├── if_guard_undefined_variable_err.vv │ │ │ ├── import_alias_selective_fn_used.out │ │ │ ├── import_alias_selective_fn_used.vv │ │ │ ├── import_alias_selective_symbol_used.out │ │ │ ├── import_alias_selective_symbol_used.vv │ │ │ ├── import_sym_fn_unused_warning_err.out │ │ │ ├── import_sym_fn_unused_warning_err.vv │ │ │ ├── inc_use_as_value.out │ │ │ ├── inc_use_as_value.vv │ │ │ ├── index_expr_option_err.out │ │ │ ├── index_expr_option_err.vv │ │ │ ├── inline_sum_type_option_err.out │ │ │ ├── inline_sum_type_option_err.vv │ │ │ ├── inline_sum_type_return_type_too_many_variants.out │ │ │ ├── inline_sum_type_return_type_too_many_variants.vv │ │ │ ├── interface_duplicate_interface_method.out │ │ │ ├── interface_duplicate_interface_method.vv │ │ │ ├── interface_duplicate_method.out │ │ │ ├── interface_duplicate_method.vv │ │ │ ├── interface_mutability_receiver.out │ │ │ ├── interface_mutability_receiver.vv │ │ │ ├── interface_name_err.out │ │ │ ├── interface_name_err.vv │ │ │ ├── interop_func_body_err.out │ │ │ ├── interop_func_body_err.vv │ │ │ ├── interop_js_func_body_err.out │ │ │ ├── interop_js_func_body_err.vv │ │ │ ├── invalid_attribute_a.out │ │ │ ├── invalid_attribute_a.vv │ │ │ ├── invalid_attribute_b.out │ │ │ ├── invalid_attribute_b.vv │ │ │ ├── invalid_attribute_c.out │ │ │ ├── invalid_attribute_c.vv │ │ │ ├── invalid_attribute_d.out │ │ │ ├── invalid_attribute_d.vv │ │ │ ├── invalid_enum_decl_script_err.out │ │ │ ├── invalid_enum_decl_script_err.vv │ │ │ ├── invalid_field_name_err.out │ │ │ ├── invalid_field_name_err.vv │ │ │ ├── invalid_fn_decl_script_err.out │ │ │ ├── invalid_fn_decl_script_err.vv │ │ │ ├── invalid_interface_decl_script_err.out │ │ │ ├── invalid_interface_decl_script_err.vv │ │ │ ├── invalid_recursive_struct1_err.out │ │ │ ├── invalid_recursive_struct1_err.vv │ │ │ ├── invalid_recursive_struct2_err.out │ │ │ ├── invalid_recursive_struct2_err.vv │ │ │ ├── invalid_struct_decl_script_err.out │ │ │ ├── invalid_struct_decl_script_err.vv │ │ │ ├── invalid_struct_decl_with_attr_script_err.out │ │ │ ├── invalid_struct_decl_with_attr_script_err.vv │ │ │ ├── invalid_using_atomic.out │ │ │ ├── invalid_using_atomic.vv │ │ │ ├── invalid_using_mut.out │ │ │ ├── invalid_using_mut.vv │ │ │ ├── invalid_using_shared.out │ │ │ ├── invalid_using_shared.vv │ │ │ ├── invalid_using_static.out │ │ │ ├── invalid_using_static.vv │ │ │ ├── invalid_using_volatile.out │ │ │ ├── invalid_using_volatile.vv │ │ │ ├── keyword_sql_used_as_name_err.out │ │ │ ├── keyword_sql_used_as_name_err.vv │ │ │ ├── lock_var_name_assign_err.out │ │ │ ├── lock_var_name_assign_err.vv │ │ │ ├── long_generic_err.out │ │ │ ├── long_generic_err.vv │ │ │ ├── main_and_script_err.out │ │ │ ├── main_and_script_err.vv │ │ │ ├── map_init.out │ │ │ ├── map_init.vv │ │ │ ├── map_init_void.out │ │ │ ├── map_init_void.vv │ │ │ ├── map_init_void2.out │ │ │ ├── map_init_void2.vv │ │ │ ├── map_key_twice_err.out │ │ │ ├── map_key_twice_err.vv │ │ │ ├── map_syntax_err.out │ │ │ ├── map_syntax_err.vv │ │ │ ├── match_range_dotdot_err.out │ │ │ ├── match_range_dotdot_err.vv │ │ │ ├── method_call_receiver_err.out │ │ │ ├── method_call_receiver_err.vv │ │ │ ├── method_decl_on_non_local_array.out │ │ │ ├── method_decl_on_non_local_array.vv │ │ │ ├── method_decl_on_non_local_map.out │ │ │ ├── method_decl_on_non_local_map.vv │ │ │ ├── method_decl_on_non_local_type.out │ │ │ ├── method_decl_on_non_local_type.vv │ │ │ ├── module_import_same_symbol2_err.out │ │ │ ├── module_import_same_symbol2_err.vv │ │ │ ├── module_import_same_symbol_err.out │ │ │ ├── module_import_same_symbol_err.vv │ │ │ ├── module_multiple_names_err.out │ │ │ ├── module_multiple_names_err.vv │ │ │ ├── module_syntax_err.out │ │ │ ├── module_syntax_err.vv │ │ │ ├── multi_argumented_assign_err.out │ │ │ ├── multi_argumented_assign_err.vv │ │ │ ├── mut_args_warning.out │ │ │ ├── mut_args_warning.vv │ │ │ ├── mut_blank_ident_err.out │ │ │ ├── mut_blank_ident_err.vv │ │ │ ├── named_sum_type_none_err.out │ │ │ ├── named_sum_type_none_err.vv │ │ │ ├── nested_defer.out │ │ │ ├── nested_defer.vv │ │ │ ├── nested_unsafe_expr.out │ │ │ ├── nested_unsafe_expr.vv │ │ │ ├── nested_unsafe_stmt.out │ │ │ ├── nested_unsafe_stmt.vv │ │ │ ├── no_chan_type_provided_err.out │ │ │ ├── no_chan_type_provided_err.vv │ │ │ ├── not_using_if_comptime_in_comptime_err.out │ │ │ ├── not_using_if_comptime_in_comptime_err.vv │ │ │ ├── operator_normal_fn.out │ │ │ ├── operator_normal_fn.vv │ │ │ ├── option_alias_option_type_err.out │ │ │ ├── option_alias_option_type_err.vv │ │ │ ├── option_result_err.out │ │ │ ├── option_result_err.vv │ │ │ ├── option_sum_type_return_err.out │ │ │ ├── option_sum_type_return_err.vv │ │ │ ├── or_default_missing.out │ │ │ ├── or_default_missing.vv │ │ │ ├── orm_delete_where_invalid_inifx_err.out │ │ │ ├── orm_delete_where_invalid_inifx_err.vv │ │ │ ├── orm_no_error_handler.out │ │ │ ├── orm_no_error_handler.vv │ │ │ ├── postfix_err_a.out │ │ │ ├── postfix_err_a.vv │ │ │ ├── postfix_err_b.out │ │ │ ├── postfix_err_b.vv │ │ │ ├── prefix_dec_bare_err.out │ │ │ ├── prefix_dec_bare_err.vv │ │ │ ├── prefix_dec_err.out │ │ │ ├── prefix_dec_err.vv │ │ │ ├── prefix_dec_expr_err.out │ │ │ ├── prefix_dec_expr_err.vv │ │ │ ├── prefix_err_1.out │ │ │ ├── prefix_err_1.vv │ │ │ ├── prefix_err_2.out │ │ │ ├── prefix_err_2.vv │ │ │ ├── prefix_inc_err.out │ │ │ ├── prefix_inc_err.vv │ │ │ ├── prohibit_redeclaration_of_builtin_types.out │ │ │ ├── prohibit_redeclaration_of_builtin_types.vv │ │ │ ├── redeclaration_of_imported_fn.out │ │ │ ├── redeclaration_of_imported_fn.vv │ │ │ ├── ref_array_pos_err.out │ │ │ ├── ref_array_pos_err.vv │ │ │ ├── register_ierror_interface.out │ │ │ ├── register_ierror_interface.vv │ │ │ ├── register_ierror_struct.out │ │ │ ├── register_ierror_struct.vv │ │ │ ├── register_imported_alias.out │ │ │ ├── register_imported_alias.vv │ │ │ ├── register_imported_enum.out │ │ │ ├── register_imported_enum.vv │ │ │ ├── register_imported_interface.out │ │ │ ├── register_imported_interface.vv │ │ │ ├── register_imported_struct.out │ │ │ ├── register_imported_struct.vv │ │ │ ├── result_option_err.out │ │ │ ├── result_option_err.vv │ │ │ ├── select_bad_key_1.out │ │ │ ├── select_bad_key_1.vv │ │ │ ├── select_bad_key_2.out │ │ │ ├── select_bad_key_2.vv │ │ │ ├── select_bad_key_3.out │ │ │ ├── select_bad_key_3.vv │ │ │ ├── select_bad_key_4.out │ │ │ ├── select_bad_key_4.vv │ │ │ ├── select_else_1.out │ │ │ ├── select_else_1.vv │ │ │ ├── select_else_2.out │ │ │ ├── select_else_2.vv │ │ │ ├── shared_blank_ident_err.out │ │ │ ├── shared_blank_ident_err.vv │ │ │ ├── sql_no_db_expr_a.out │ │ │ ├── sql_no_db_expr_a.vv │ │ │ ├── sql_no_db_expr_b.out │ │ │ ├── sql_no_db_expr_b.vv │ │ │ ├── sql_undefined_variables_in_complex_exprs.out │ │ │ ├── sql_undefined_variables_in_complex_exprs.vv │ │ │ ├── string_invalid_prefix_err.out │ │ │ ├── string_invalid_prefix_err.vv │ │ │ ├── struct_anon_invalid_embed_err.out │ │ │ ├── struct_anon_invalid_embed_err.vv │ │ │ ├── struct_embed_duplicate.out │ │ │ ├── struct_embed_duplicate.vv │ │ │ ├── struct_embed_unknown_module.out │ │ │ ├── struct_embed_unknown_module.vv │ │ │ ├── struct_embed_wrong_pos_in_pub_err.out │ │ │ ├── struct_embed_wrong_pos_in_pub_err.vv │ │ │ ├── struct_embed_wrong_pos_long_err.out │ │ │ ├── struct_embed_wrong_pos_long_err.vv │ │ │ ├── struct_embed_wrong_pos_short_err.out │ │ │ ├── struct_embed_wrong_pos_short_err.vv │ │ │ ├── struct_field_expected.out │ │ │ ├── struct_field_expected.vv │ │ │ ├── struct_field_mut_type_err.out │ │ │ ├── struct_field_mut_type_err.vv │ │ │ ├── struct_field_required_fn_option_type.out │ │ │ ├── struct_field_required_fn_option_type.vv │ │ │ ├── struct_field_required_fn_result_type.out │ │ │ ├── struct_field_required_fn_result_type.vv │ │ │ ├── struct_field_unknown_module_a.out │ │ │ ├── struct_field_unknown_module_a.vv │ │ │ ├── struct_field_unknown_module_b.out │ │ │ ├── struct_field_unknown_module_b.vv │ │ │ ├── struct_field_unknown_module_c.out │ │ │ ├── struct_field_unknown_module_c.vv │ │ │ ├── struct_init_array_field_with_curly_braces_err.out │ │ │ ├── struct_init_array_field_with_curly_braces_err.vv │ │ │ ├── struct_init_from_another_mod_err.out │ │ │ ├── struct_init_from_another_mod_err.vv │ │ │ ├── struct_module_section.out │ │ │ ├── struct_module_section.vv │ │ │ ├── struct_no_body_err.out │ │ │ ├── struct_no_body_err.vv │ │ │ ├── struct_update_err.out │ │ │ ├── struct_update_err.vv │ │ │ ├── struct_with_empty_pub_mut_section.out │ │ │ ├── struct_with_empty_pub_mut_section.vv │ │ │ ├── sum_type_exists_err.out │ │ │ ├── sum_type_exists_err.vv │ │ │ ├── too_many_generics_err.out │ │ │ ├── too_many_generics_err.vv │ │ │ ├── too_many_layers_embedded_generic_type_err.out │ │ │ ├── too_many_layers_embedded_generic_type_err.vv │ │ │ ├── type_alias_same_type_err.out │ │ │ ├── type_alias_same_type_err.vv │ │ │ ├── type_decl_name_err.out │ │ │ ├── type_decl_name_err.vv │ │ │ ├── type_fn_eof_on_same_line.out │ │ │ ├── type_fn_eof_on_same_line.vv │ │ │ ├── uncomplete_module_call_err.out │ │ │ ├── uncomplete_module_call_err.vv │ │ │ ├── unexpected_expr.out │ │ │ ├── unexpected_expr.vv │ │ │ ├── unexpected_name_err.out │ │ │ ├── unexpected_name_err.vv │ │ │ ├── unexpected_token.out │ │ │ └── unexpected_token.vv │ │ ├── v_parser_test.v │ │ ├── v_print_v_files_works_test.v │ │ └── v_silent_works_test.v │ ├── pkgconfig/ │ │ ├── README.md │ │ ├── bin/ │ │ │ ├── pkgconfig.v │ │ │ └── pkgconfig_test.v │ │ ├── main.v │ │ ├── pkgconfig.v │ │ ├── pkgconfig_test.v │ │ ├── test_samples/ │ │ │ ├── alsa.pc │ │ │ ├── atk.pc │ │ │ ├── autoopts.pc │ │ │ ├── dep-resolution-fail.pc │ │ │ ├── expat.pc │ │ │ ├── form.pc │ │ │ ├── gio-2.0.pc │ │ │ ├── gio-unix-2.0.pc │ │ │ ├── glib-2.0.pc │ │ │ ├── gmodule-2.0.pc │ │ │ ├── gmodule-no-export-2.0.pc │ │ │ ├── gobject-2.0.pc │ │ │ ├── hogweed.pc │ │ │ ├── libffi.pc │ │ │ ├── libpcre.pc │ │ │ ├── ncurses.pc │ │ │ ├── nettle.pc │ │ │ ├── openssl-3.3.2.pc │ │ │ ├── sdl2.pc │ │ │ └── zlib.pc │ │ └── v.mod │ ├── pref/ │ │ ├── arch.c.v │ │ ├── build_flags.v │ │ ├── default.v │ │ ├── line_info.v │ │ ├── options_test.v │ │ ├── os.v │ │ ├── pref.v │ │ ├── pref_test.v │ │ ├── should_compile.v │ │ └── vsh_envbang_test.v │ ├── preludes/ │ │ ├── README.md │ │ ├── embed_file/ │ │ │ ├── embed_file.v │ │ │ └── zlib/ │ │ │ └── embed_file_zlib.v │ │ ├── live.v │ │ ├── live_main.v │ │ ├── live_shared.v │ │ ├── profiled_program.v │ │ ├── test_runner.c.v │ │ ├── test_runner_dump.v │ │ ├── test_runner_normal.v │ │ ├── test_runner_simple.v │ │ ├── test_runner_tap.v │ │ ├── test_runner_teamcity.v │ │ ├── tests_with_stats.v │ │ └── trace_calls.v │ ├── preludes_js/ │ │ ├── profiled_program.v │ │ ├── stats_import.js.v │ │ ├── test_runner.v │ │ ├── test_runner_normal.v │ │ ├── test_runner_simple.v │ │ ├── test_runner_tap.v │ │ └── tests_with_stats.v │ ├── profile/ │ │ └── api.v │ ├── reflection/ │ │ └── reflection.v │ ├── scanner/ │ │ ├── scanner.v │ │ ├── scanner_test.v │ │ └── tests/ │ │ ├── bin_consecutively_separator_err.out │ │ ├── bin_consecutively_separator_err.vv │ │ ├── bin_separator_in_front_err.out │ │ ├── bin_separator_in_front_err.vv │ │ ├── comments_not_terminated_err.out │ │ ├── comments_not_terminated_err.vv │ │ ├── dec_consecutively_separator_err.out │ │ ├── dec_consecutively_separator_err.vv │ │ ├── empty_character_literal_err.out │ │ ├── empty_character_literal_err.vv │ │ ├── float_literals_dot_err.out │ │ ├── float_literals_dot_err.vv │ │ ├── hex_consecutively_separator_err.out │ │ ├── hex_consecutively_separator_err.vv │ │ ├── hex_separator_in_front_err.out │ │ ├── hex_separator_in_front_err.vv │ │ ├── invalid_character_literal_err_1.out │ │ ├── invalid_character_literal_err_1.vv │ │ ├── invalid_character_literal_err_2.out │ │ ├── invalid_character_literal_err_2.vv │ │ ├── invalid_unicode_16_err.out │ │ ├── invalid_unicode_16_err.vv │ │ ├── invalid_unicode_32_err.out │ │ ├── invalid_unicode_32_err.vv │ │ ├── newline_character_literal_err.out │ │ ├── newline_character_literal_err.vv │ │ ├── oct_consecutively_separator_err.out │ │ ├── oct_consecutively_separator_err.vv │ │ ├── oct_separator_in_front_err.out │ │ ├── oct_separator_in_front_err.vv │ │ ├── position_0_err.out │ │ ├── position_0_err.vv │ │ ├── shebang_outside_vsh_err.out │ │ ├── shebang_outside_vsh_err.vv │ │ ├── undefined_ident_in_string_literal_err.out │ │ ├── undefined_ident_in_string_literal_err.vv │ │ ├── unfinished_string_literal_err.out │ │ ├── unfinished_string_literal_err.vv │ │ ├── unknown_comptime_var_err.out │ │ ├── unknown_comptime_var_err.vv │ │ ├── unknown_escape_sequence_err.out │ │ ├── unknown_escape_sequence_err.vv │ │ ├── unknown_escape_sequence_in_ident_char_1_err.out │ │ ├── unknown_escape_sequence_in_ident_char_1_err.vv │ │ ├── unknown_escape_sequence_in_ident_char_2_err.out │ │ └── unknown_escape_sequence_in_ident_char_2_err.vv │ ├── slow_tests/ │ │ ├── assembly/ │ │ │ ├── asm_empty_statement_test.v │ │ │ ├── asm_no_tcc_test.amd64.v │ │ │ ├── asm_test.amd64.v │ │ │ ├── asm_test.arm64.v │ │ │ ├── asm_test.i386.v │ │ │ ├── asm_test.loongarch64.v │ │ │ ├── asm_test.ppc64le.v │ │ │ ├── asm_test.rv64.v │ │ │ ├── asm_test.s390x.v │ │ │ ├── naked_attr_test.amd64.v │ │ │ ├── naked_attr_test.i386.v │ │ │ ├── stmt_separator_test.amd64.v │ │ │ └── util/ │ │ │ └── dot_amd64_util.amd64.v │ │ ├── comptime_if_expr_threads_test.v │ │ ├── crun_mode/ │ │ │ └── crun_test.v │ │ ├── inout/ │ │ │ ├── .gitignore │ │ │ ├── cast_to_reference_type.out │ │ │ ├── cast_to_reference_type.vv │ │ │ ├── closure_with_fn_variables.out │ │ │ ├── closure_with_fn_variables.vv │ │ │ ├── closure_with_nested_closure_var.out │ │ │ ├── closure_with_nested_closure_var.vv │ │ │ ├── compiler_test.v │ │ │ ├── comptime_bool_fields.out │ │ │ ├── comptime_bool_fields.vv │ │ │ ├── comptime_if_script_mode.out │ │ │ ├── comptime_if_script_mode.vv │ │ │ ├── comptime_iterate.out │ │ │ ├── comptime_iterate.vv │ │ │ ├── comptime_ptr.out │ │ │ ├── comptime_ptr.vv │ │ │ ├── comptime_selector_of_interface.out │ │ │ ├── comptime_selector_of_interface.vv │ │ │ ├── comptime_smartcast_variant.out │ │ │ ├── comptime_smartcast_variant.vv │ │ │ ├── data_obj.v.templ │ │ │ ├── dump_array_of_ref.out │ │ │ ├── dump_array_of_ref.vv │ │ │ ├── dump_expression.out │ │ │ ├── dump_expression.vv │ │ │ ├── dump_expressions_with_literals.out │ │ │ ├── dump_expressions_with_literals.vv │ │ │ ├── dump_fixed_array_of_option.out │ │ │ ├── dump_fixed_array_of_option.vv │ │ │ ├── dump_generic_fn_mut_arg.out │ │ │ ├── dump_generic_fn_mut_arg.vv │ │ │ ├── dump_generic_interface_ref_arg.out │ │ │ ├── dump_generic_interface_ref_arg.vv │ │ │ ├── dump_match_expr.out │ │ │ ├── dump_match_expr.vv │ │ │ ├── dump_multi_fixed_array_init.out │ │ │ ├── dump_multi_fixed_array_init.vv │ │ │ ├── dump_multiple_ptr.out │ │ │ ├── dump_multiple_ptr.vv │ │ │ ├── dump_nested_generic_fn_call_ref_arg.out │ │ │ ├── dump_nested_generic_fn_call_ref_arg.vv │ │ │ ├── dump_nil_voidptr.out │ │ │ ├── dump_nil_voidptr.vv │ │ │ ├── dump_none.out │ │ │ ├── dump_none.vv │ │ │ ├── dump_shared_arg.out │ │ │ ├── dump_shared_arg.vv │ │ │ ├── dump_sumtype_of_fntype.out │ │ │ ├── dump_sumtype_of_fntype.vv │ │ │ ├── embedded.html │ │ │ ├── enum_print.out │ │ │ ├── enum_print.vv │ │ │ ├── file.html │ │ │ ├── file.md │ │ │ ├── footer.md │ │ │ ├── for_channel_or_expr_block.out │ │ │ ├── for_channel_or_expr_block.vv │ │ │ ├── generic_fn_with_alias_arg.out │ │ │ ├── generic_fn_with_alias_arg.vv │ │ │ ├── generic_fn_with_array_arg.out │ │ │ ├── generic_fn_with_array_arg.vv │ │ │ ├── go_print.out │ │ │ ├── go_print.vv │ │ │ ├── header.md │ │ │ ├── hello.out │ │ │ ├── hello.vv │ │ │ ├── hello_devs.out │ │ │ ├── hello_devs.vv │ │ │ ├── import_sym_field_no_warn.out │ │ │ ├── import_sym_field_no_warn.vv │ │ │ ├── in_expr_callexpr.out │ │ │ ├── in_expr_callexpr.vv │ │ │ ├── interface_field_initialised_struct_update_expr.out │ │ │ ├── interface_field_initialised_struct_update_expr.vv │ │ │ ├── math_easing_tables.out │ │ │ ├── math_easing_tables.vv │ │ │ ├── nested_generic_fn_call.out │ │ │ ├── nested_generic_fn_call.vv │ │ │ ├── nested_structs.out │ │ │ ├── nested_structs.vv │ │ │ ├── oneliner_with_semicolons.out │ │ │ ├── oneliner_with_semicolons.vv │ │ │ ├── option_fn_arg.out │ │ │ ├── option_fn_arg.vv │ │ │ ├── option_panic.out │ │ │ ├── option_panic.vv │ │ │ ├── option_unwrap_err.out │ │ │ ├── option_unwrap_err.vv │ │ │ ├── or_block_with_rvoid.out │ │ │ ├── or_block_with_rvoid.vv │ │ │ ├── orm_panic_for_insert_into_not_created_table.out │ │ │ ├── orm_panic_for_insert_into_not_created_table.vv │ │ │ ├── orm_panic_for_select_from_not_created_table.out │ │ │ ├── orm_panic_for_select_from_not_created_table.vv │ │ │ ├── os.out │ │ │ ├── os.vv │ │ │ ├── panic_array_decompose_extra_args.out │ │ │ ├── panic_array_decompose_extra_args.vv │ │ │ ├── panic_on_bad_st_as.out │ │ │ ├── panic_on_bad_st_as.vv │ │ │ ├── panic_on_fixed_array_index.out │ │ │ ├── panic_on_fixed_array_index.vv │ │ │ ├── panic_on_fixed_array_slice.out │ │ │ ├── panic_on_fixed_array_slice.vv │ │ │ ├── panic_with_cg.out │ │ │ ├── panic_with_cg.vv │ │ │ ├── printing_alias_has_str_method.out │ │ │ ├── printing_alias_has_str_method.vv │ │ │ ├── printing_aliases_of_multi_fixed_array.out │ │ │ ├── printing_aliases_of_multi_fixed_array.vv │ │ │ ├── printing_complex_if_exprs_output.out │ │ │ ├── printing_complex_if_exprs_output.vv │ │ │ ├── printing_comptime_if.out │ │ │ ├── printing_comptime_if.vv │ │ │ ├── printing_const_array.out │ │ │ ├── printing_const_array.vv │ │ │ ├── printing_fixed_array_of_pointers.out │ │ │ ├── printing_fixed_array_of_pointers.vv │ │ │ ├── printing_for_mut_v_in_a.out │ │ │ ├── printing_for_mut_v_in_a.vv │ │ │ ├── printing_for_v_in_a.out │ │ │ ├── printing_for_v_in_a.vv │ │ │ ├── printing_interpolating_float.out │ │ │ ├── printing_interpolating_float.vv │ │ │ ├── printing_multi_fixed_array.out │ │ │ ├── printing_multi_fixed_array.vv │ │ │ ├── printing_multi_fixed_array_init.out │ │ │ ├── printing_multi_fixed_array_init.vv │ │ │ ├── printing_nested_generic_struct.out │ │ │ ├── printing_nested_generic_struct.vv │ │ │ ├── printing_option_in_if_expr.out │ │ │ ├── printing_option_in_if_expr.vv │ │ │ ├── printing_recursive_array_of_reference_struct.out │ │ │ ├── printing_recursive_array_of_reference_struct.vv │ │ │ ├── printing_reference_alias.out │ │ │ ├── printing_reference_alias.vv │ │ │ ├── printing_reference_enum.out │ │ │ ├── printing_reference_enum.vv │ │ │ ├── printing_reference_struct.out │ │ │ ├── printing_reference_struct.vv │ │ │ ├── printing_result_in_infix_expr.out │ │ │ ├── printing_result_in_infix_expr.vv │ │ │ ├── printing_result_in_infix_expr2.out │ │ │ ├── printing_result_in_infix_expr2.vv │ │ │ ├── printing_result_or_expr_with_map_val.out │ │ │ ├── printing_result_or_expr_with_map_val.vv │ │ │ ├── printing_slice_of_fn_call_string.out │ │ │ ├── printing_slice_of_fn_call_string.vv │ │ │ ├── printing_slice_of_multiline_raw_string.out │ │ │ ├── printing_slice_of_multiline_raw_string.vv │ │ │ ├── printing_struct_with_arrays_of_anon_struct_field.out │ │ │ ├── printing_struct_with_arrays_of_anon_struct_field.vv │ │ │ ├── printing_struct_with_skip_fields.out │ │ │ ├── printing_struct_with_skip_fields.vv │ │ │ ├── printing_struct_with_thread_field.out │ │ │ ├── printing_struct_with_thread_field.vv │ │ │ ├── printing_sumtype_with_none.out │ │ │ ├── publish_shared_object_method_call.out │ │ │ ├── publish_shared_object_method_call.vv │ │ │ ├── push_on_closed_channel.out │ │ │ ├── push_on_closed_channel.vv │ │ │ ├── push_work_on_channel.out │ │ │ ├── push_work_on_channel.vv │ │ │ ├── smart_quote.out │ │ │ ├── smart_quote.vv │ │ │ ├── strconv_v_printf.out │ │ │ ├── string_interp.out │ │ │ ├── string_interp.vv │ │ │ ├── struct_dump_option_fields.out │ │ │ ├── struct_dump_option_fields.vv │ │ │ ├── struct_field_option.out │ │ │ ├── struct_field_option.vv │ │ │ ├── struct_with_embed_field_init.out │ │ │ ├── struct_with_embed_field_init.vv │ │ │ ├── sumtype_with_fntype.out │ │ │ ├── sumtype_with_fntype.vv │ │ │ ├── thread_uninitialized_err.out │ │ │ ├── thread_uninitialized_err.vv │ │ │ ├── tmpl_all_in_one_folder.out │ │ │ ├── tmpl_expand_v_source_code.out │ │ │ ├── tmpl_parse_html.out │ │ │ ├── vscript_using_constants_in_os.out │ │ │ ├── vscript_using_constants_in_os.vsh │ │ │ ├── vscript_using_generics_in_os.out │ │ │ └── vscript_using_generics_in_os.vsh │ │ ├── keep_args_alive_test.c.v │ │ ├── keep_args_alive_test_c.h │ │ ├── map_issue_16285_test.v │ │ ├── map_issue_22139_clear_test.v │ │ ├── map_issue_22143_clear_test.v │ │ ├── map_issue_22145_clear_test.v │ │ ├── map_issue_22148_clear_test.v │ │ ├── modules/ │ │ │ └── acommentedmodule/ │ │ │ └── commentedfile.v │ │ ├── prod/ │ │ │ ├── .gitignore │ │ │ ├── asserts_should_be_skipped.prod.v │ │ │ ├── asserts_should_be_skipped.prod.v.expected.txt │ │ │ ├── assoc.prod.v │ │ │ ├── assoc.prod.v.expected.txt │ │ │ ├── f64_literals_and_simple_expressions_should_not_round_as_f32.prod.v │ │ │ └── f64_literals_and_simple_expressions_should_not_round_as_f32.prod.v.expected.txt │ │ ├── prod_test.v │ │ ├── profile/ │ │ │ ├── profile_test.v │ │ │ ├── profile_test_1.v │ │ │ ├── profile_test_2.v │ │ │ ├── profile_test_3.v │ │ │ └── profile_test_interrupted.v │ │ ├── repl/ │ │ │ ├── .gitattributes │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── array_filter.repl │ │ │ ├── array_init.repl │ │ │ ├── array_method.repl │ │ │ ├── bad_in_type.repl.skip │ │ │ ├── chained_fields/ │ │ │ │ ├── bd.repl.skip │ │ │ │ ├── c.repl.skip │ │ │ │ ├── c2.repl.skip │ │ │ │ ├── d.repl.skip │ │ │ │ └── ef.repl.skip │ │ │ ├── comptime_for.repl │ │ │ ├── comptime_tmpl.repl │ │ │ ├── conditional_blocks/ │ │ │ │ ├── for.repl │ │ │ │ ├── if.repl │ │ │ │ └── if_else.repl │ │ │ ├── const.repl │ │ │ ├── default_printing.repl │ │ │ ├── empty_struct.repl.skip │ │ │ ├── entire_commented_module.repl │ │ │ ├── enum.repl │ │ │ ├── error.repl │ │ │ ├── error_and_continue_print.repl │ │ │ ├── error_eval_script.repl │ │ │ ├── error_exitasdfasdf.repl │ │ │ ├── error_multi_line_fn_decl.repl │ │ │ ├── error_nosave.repl.skip │ │ │ ├── error_single_line_fn_decl.repl │ │ │ ├── fn_calls.repl │ │ │ ├── from_import.repl │ │ │ ├── if_and_for_with_print_inside_them.repl │ │ │ ├── if_expr_oneline.repl │ │ │ ├── immutable_len_fields/ │ │ │ │ ├── fields.1.repl.skip │ │ │ │ ├── fields.2.repl.skip │ │ │ │ └── fields.3.repl.skip │ │ │ ├── import.repl │ │ │ ├── import_alias.repl │ │ │ ├── infix_shift_op.repl │ │ │ ├── input.repl │ │ │ ├── interface.repl │ │ │ ├── line_comment.repl │ │ │ ├── method_call1.repl │ │ │ ├── method_call2.repl │ │ │ ├── naked_strings.repl │ │ │ ├── newlines.repl │ │ │ ├── newlines_should_not_exit_the_repl.repl │ │ │ ├── nomain.repl │ │ │ ├── nothing.repl │ │ │ ├── open_close_string_check.repl │ │ │ ├── option.repl.skip │ │ │ ├── option_call.repl │ │ │ ├── postfix_operators.repl │ │ │ ├── print_and_fn_call.repl │ │ │ ├── print_output_warning.repl │ │ │ ├── println.repl │ │ │ ├── repl_test.v │ │ │ ├── runner/ │ │ │ │ └── runner.v │ │ │ ├── struct_def_later.repl │ │ │ ├── type_decl.repl │ │ │ ├── var_decl.repl │ │ │ ├── var_starts_with_print.repl │ │ │ └── void_vlib_fncall.repl │ │ ├── run_project_folders/ │ │ │ ├── compile_obj_file_and_link_separately/ │ │ │ │ ├── abc/ │ │ │ │ │ └── module_in_v.v │ │ │ │ ├── main.v │ │ │ │ └── main_in_c.c │ │ │ └── go_fns_in_different_files_over_the_same_struct/ │ │ │ ├── f1.v │ │ │ ├── f2.v │ │ │ └── main.v │ │ ├── run_project_folders_test.v │ │ └── valgrind/ │ │ ├── 1.strings_and_arrays.v │ │ ├── 2.heap_objects.v │ │ ├── array_init_with_string_variable.v │ │ ├── autofree_match_sumtype_test.v │ │ ├── autofree_match_test.v │ │ ├── autofree_or_block_string_interp.v │ │ ├── base64.v │ │ ├── buffer_passed_in_fn_that_uses_tos_on_it.v │ │ ├── comptime_selector.v │ │ ├── cross_var_assign.v │ │ ├── dump_nested_structs.v │ │ ├── fn_call_result_arg.v │ │ ├── fn_returning_string_param.v │ │ ├── fn_with_return_should_free_local_vars.v │ │ ├── free_heap_foos.c.v │ │ ├── free_variables_in_reverse_order_of_creation.c.v │ │ ├── if_expr.v │ │ ├── if_expr_autofree_optional.v │ │ ├── if_expr_skip.v │ │ ├── import_os_and_use_its_constants.v │ │ ├── import_x_json2.v │ │ ├── logging.v │ │ ├── multiple_fn_calls.v │ │ ├── nil_interface.v │ │ ├── option_reassigned.v │ │ ├── option_simple.v │ │ ├── rand_module.v │ │ ├── rune_methods.v │ │ ├── simple_interpolation.v │ │ ├── simple_interpolation_script_mode.v │ │ ├── simple_interpolation_script_mode_more_scopes.v │ │ ├── string_plus_string_plus.v │ │ ├── string_str_method.v │ │ ├── strings_builder.v │ │ ├── struct_field.v │ │ ├── struct_of_array_of_same_struct.v │ │ ├── sync.v │ │ └── valgrind_test.v │ ├── tests/ │ │ ├── alias_cast_to_fixed_array_test.v │ │ ├── aliases/ │ │ │ ├── alias_array_built_in_methods_test.v │ │ │ ├── alias_array_fixed_sumtype_test.v │ │ │ ├── alias_array_fixed_test.v │ │ │ ├── alias_array_has_method_test.v │ │ │ ├── alias_array_no_cast_init_test.v │ │ │ ├── alias_array_operator_overloading_test.v │ │ │ ├── alias_array_plus_operator_test.v │ │ │ ├── alias_array_push_test.v │ │ │ ├── alias_assigned_in_increment_part_of_for_c_loop_test.v │ │ │ ├── alias_basic_types_test.v │ │ │ ├── alias_bool_not_op_test.v │ │ │ ├── alias_char_type_reference_test.v │ │ │ ├── alias_compare_non_alias_test.v │ │ │ ├── alias_const_array_fixed_test.v │ │ │ ├── alias_custom_type_map_test.v │ │ │ ├── alias_eq_op_test.v │ │ │ ├── alias_fixed_arr_test.v │ │ │ ├── alias_fixed_array_append_to_array_test.v │ │ │ ├── alias_fixed_array_compare_test.v │ │ │ ├── alias_fixed_array_infix_expr_test.v │ │ │ ├── alias_fixed_array_init_test.v │ │ │ ├── alias_fixed_array_of_struct_test.v │ │ │ ├── alias_fixed_array_test.v │ │ │ ├── alias_generic_parent_operator_overloading_test.v │ │ │ ├── alias_generic_struct_test.v │ │ │ ├── alias_in_a_struct_field_autostr_test.v │ │ │ ├── alias_interface_test.v │ │ │ ├── alias_map_clone_test.v │ │ │ ├── alias_map_keys_test.v │ │ │ ├── alias_map_operator_overloading_test.v │ │ │ ├── alias_map_test.v │ │ │ ├── alias_operator_overloading_test.v │ │ │ ├── alias_option_test.v │ │ │ ├── alias_parent_operator_overloading_issue_26416_test.v │ │ │ ├── alias_pointer_struct_field_default_nil_test.v │ │ │ ├── alias_primitive_operator_overloading_test.v │ │ │ ├── alias_set_elem_to_alias_of_fixed_array_test.v │ │ │ ├── alias_string_match_test.v │ │ │ ├── alias_sumtype_method_call_test.v │ │ │ ├── alias_to_ptr_arg_test.v │ │ │ ├── alias_to_sum_with_enum_test.v │ │ │ ├── alias_updated_expr_test.v │ │ │ ├── alias_with_op_overloading_test.v │ │ │ ├── aliased_array_method_call_test.v │ │ │ ├── aliased_array_operations_test.v │ │ │ ├── aliased_field_access_test.v │ │ │ ├── aliased_fixed_array_option_fn_call_test.v │ │ │ ├── aliased_option_fn_call_test.v │ │ │ ├── array_alias_test.v │ │ │ ├── modules/ │ │ │ │ ├── geometry/ │ │ │ │ │ └── geometry.v │ │ │ │ └── value/ │ │ │ │ ├── value.v │ │ │ │ └── value_test.v │ │ │ ├── type_alias_of_fn_with_mut_args_test.v │ │ │ ├── type_alias_of_pointer_types_test.v │ │ │ ├── type_alias_str_method_override_test.v │ │ │ ├── type_alias_test.v │ │ │ └── unaliased_typ_checking_test.v │ │ ├── aliasing_c_structs/ │ │ │ ├── cstructs.h │ │ │ ├── eq_operator_overload_of_c_struct_alias_test.c.v │ │ │ └── v.mod │ │ ├── array_fixed_filter_test.v │ │ ├── array_fixed_none_init_test.v │ │ ├── array_fixed_ternary_test.v │ │ ├── array_insert_array_fixed_test.v │ │ ├── array_len_int_alias_test.v │ │ ├── array_map_anon_return_fixed_array_test.v │ │ ├── arrays_closure_fixed_array_test.v │ │ ├── arrays_reverse_ref_test.v │ │ ├── assert_alias_array_test.v │ │ ├── assign/ │ │ │ ├── array_fixed_init_with_call_test.v │ │ │ ├── assert_fn_call_with_parentheses_test.v │ │ │ ├── assert_fn_ret_option_test.v │ │ │ ├── assert_if_guard_expr_test.v │ │ │ ├── assert_should_evaluate_args_just_once_test.v │ │ │ ├── assert_sumtype_test.v │ │ │ ├── assert_with_array_ref_test.v │ │ │ ├── assert_with_newlines_test.v │ │ │ ├── assign_array_fixed_from_union_test.v │ │ │ ├── assign_array_of_aliases_test.v │ │ │ ├── assign_bitops_with_type_aliases_test.v │ │ │ ├── assign_literal_with_closure_test.v │ │ │ ├── assign_map_value_of_fixed_array_test.v │ │ │ ├── assign_mut_for_var_test.v │ │ │ ├── assign_option_of_array_index_test.v │ │ │ ├── assign_option_of_fixed_array_test.v │ │ │ ├── assign_option_of_multi_return_with_heap_test.v │ │ │ ├── assign_option_of_struct_fntype_field_test.v │ │ │ ├── assign_shared_test.v │ │ │ ├── assign_static_method_to_anon_fn_test.v │ │ │ ├── assign_type_checking_with_generics_test.v │ │ │ ├── assign_with_in_module_sumtype_test.v │ │ │ ├── bool_assign_operator_test.v │ │ │ ├── complex_assign_test.v │ │ │ ├── cross_assign_aliased_array_test.v │ │ │ ├── cross_assign_fixed_array_test.v │ │ │ ├── cross_assign_test.v │ │ │ ├── cross_assign_with_generic_fn_call_test.v │ │ │ ├── cross_assign_with_parentheses_test.v │ │ │ ├── modules/ │ │ │ │ └── aa/ │ │ │ │ └── aa.v │ │ │ ├── multiple_assign_array_index_test.v │ │ │ └── multiple_assign_test.v │ │ ├── at_in_url_template.html │ │ ├── attribute_test.v │ │ ├── autofree_arrays_reverse_iter_test.v │ │ ├── autofree_discarded_call_return_value_test.v │ │ ├── autofree_generic_math_test.v │ │ ├── autofree_if_expr_call_arg_with_struct_init_test.v │ │ ├── autofree_net_addr_len_test.v │ │ ├── autofree_result_method_chain_test.v │ │ ├── backtrace_test.v │ │ ├── bench/ │ │ │ ├── bench_compare_tokens.v │ │ │ ├── bench_gc_enable_disable_collect.v │ │ │ ├── bench_json_vs_json2.v │ │ │ ├── bench_rand_fill_buffer_from_set.v │ │ │ ├── bench_random_number_generation.c.v │ │ │ ├── bench_stbi_load.v │ │ │ ├── bench_string_int.v │ │ │ ├── bench_string_key_in_map_vs_string_value_in_array.v │ │ │ ├── bench_strings_similarity.v │ │ │ ├── gcboehm/ │ │ │ │ ├── GC_Ryzen_3800X_Linux.svg.xz │ │ │ │ ├── GC_bench.plt │ │ │ │ ├── GC_bench.v │ │ │ │ ├── GC_bench_full.plt │ │ │ │ ├── GC_bench_incr.plt │ │ │ │ ├── GC_bench_non_opt.plt │ │ │ │ ├── GC_bench_opt.plt │ │ │ │ ├── Makefile │ │ │ │ ├── Resources.plt │ │ │ │ ├── Resources_Ryzen_3800X_Linux.svg.xz │ │ │ │ └── resources.txt │ │ │ ├── math_big_gcd/ │ │ │ │ ├── bench_euclid.v │ │ │ │ ├── prime/ │ │ │ │ │ ├── .skip_should_compile_all │ │ │ │ │ └── maker.v │ │ │ │ └── primes.toml │ │ │ └── val_vs_ptr.c │ │ ├── blank_ident_test.v │ │ ├── bool_cast_int_test.v │ │ ├── builtin_arrays/ │ │ │ ├── array_2d_append_empty_array_test.v │ │ │ ├── array_access_optimisation_test.v │ │ │ ├── array_append_map_with_or_expr_test.v │ │ │ ├── array_append_short_struct_test.v │ │ │ ├── array_as_interface_test.v │ │ │ ├── array_cast_test.v │ │ │ ├── array_clear_test.v │ │ │ ├── array_count_test.v │ │ │ ├── array_delete_last_test.v │ │ │ ├── array_delete_many_test.v │ │ │ ├── array_elements_with_option_test.v │ │ │ ├── array_equality_test.v │ │ │ ├── array_filter_of_fn_mut_arg_test.v │ │ │ ├── array_filter_using_direct_closure_test.v │ │ │ ├── array_fixed_auto_clone_test.v │ │ │ ├── array_fixed_c_test.c.v │ │ │ ├── array_fixed_empty_struct_test.v │ │ │ ├── array_fixed_for_loop_test.v │ │ │ ├── array_fixed_from_unsafe_test.v │ │ │ ├── array_fixed_init_node_test.v │ │ │ ├── array_fixed_map_values_test.v │ │ │ ├── array_fixed_op_overload_test.v │ │ │ ├── array_fixed_ptr_test.v │ │ │ ├── array_fixed_struct_field_test.v │ │ │ ├── array_get_anon_fn_value_test.v │ │ │ ├── array_grow_cap_test.v │ │ │ ├── array_index_option_test.v │ │ │ ├── array_init_element_size_equal_array_size_test.v │ │ │ ├── array_init_fixed_array_ret_test.v │ │ │ ├── array_init_fixed_test.v │ │ │ ├── array_init_i32_test.v │ │ │ ├── array_init_test.v │ │ │ ├── array_init_with_fields_test.v │ │ │ ├── array_insert_as_mut_receiver_test.v │ │ │ ├── array_insert_variadic_arg_variable_test.v │ │ │ ├── array_map_cast_interface_test.v │ │ │ ├── array_map_or_test.v │ │ │ ├── array_map_ref_test.v │ │ │ ├── array_map_to_fixed_array_test.v │ │ │ ├── array_method_using_it_in_defer_test.v │ │ │ ├── array_methods_test.v │ │ │ ├── array_nested_call_test.v │ │ │ ├── array_of_alias_op_overload_test.v │ │ │ ├── array_of_alias_pop_test.v │ │ │ ├── array_of_alias_slice_test.v │ │ │ ├── array_of_anon_fn_call_test.v │ │ │ ├── array_of_fixed_array_map_test.v │ │ │ ├── array_of_fixed_array_test.v │ │ │ ├── array_of_fns_index_call_with_direct_array_access_test.v │ │ │ ├── array_of_fns_index_call_with_embeded_array_call_test.v │ │ │ ├── array_of_functions_direct_call_test.v │ │ │ ├── array_of_interface_init_test.v │ │ │ ├── array_of_interfaces_builtin_method_test.v │ │ │ ├── array_of_interfaces_equality_test.v │ │ │ ├── array_of_map_with_default_test.v │ │ │ ├── array_of_option_array_test.v │ │ │ ├── array_of_option_fixed_array_test.v │ │ │ ├── array_of_ptrs_test.v │ │ │ ├── array_of_reference_sumtype_test.v │ │ │ ├── array_of_sumtype_append_aggregate_type_test.v │ │ │ ├── array_of_sumtype_append_alias_test.v │ │ │ ├── array_of_sumtype_append_array_of_sumtype_test.v │ │ │ ├── array_of_sumtype_append_literal_type_test.v │ │ │ ├── array_of_sumtype_init_test.v │ │ │ ├── array_of_sumtype_with_default_test.v │ │ │ ├── array_of_sumtypes_test.v │ │ │ ├── array_of_threads_wait_test.v │ │ │ ├── array_ops_create_just_one_closure_test.c.v │ │ │ ├── array_prepend_generic_test.v │ │ │ ├── array_ptr_compare_test.v │ │ │ ├── array_slice_assign_test.v │ │ │ ├── array_slice_test.v │ │ │ ├── array_sort_lt_overload_test.v │ │ │ ├── array_sort_with_call_test.v │ │ │ ├── array_sort_with_compare_sanitize_test.v │ │ │ ├── array_sort_with_fn_call_test.v │ │ │ ├── array_sort_with_interface_fn_call_test.v │ │ │ ├── array_string_test.v │ │ │ ├── array_sumtype_init_test.v │ │ │ ├── array_test.v │ │ │ ├── array_to_string_test.v │ │ │ ├── array_type_alias_test.v │ │ │ ├── array_with_fixed_array_test.v │ │ │ ├── array_with_it_test.v │ │ │ ├── arraydecompose_nonvariadic_test.v │ │ │ ├── arrays_and_maps_of_empty_structs_should_work_test.v │ │ │ ├── dump_fixed_array_on_array_append_test.v │ │ │ ├── fixed_array_2_test.v │ │ │ ├── fixed_array_chan_test.v │ │ │ ├── fixed_array_const_size_test.v │ │ │ ├── fixed_array_explicit_decompose_test.v │ │ │ ├── fixed_array_generic_ini_test.v │ │ │ ├── fixed_array_generic_ret_test.v │ │ │ ├── fixed_array_in_op_test.v │ │ │ ├── fixed_array_init_test.v │ │ │ ├── fixed_array_literal_index_test.v │ │ │ ├── fixed_array_literal_infix_test.v │ │ │ ├── fixed_array_literal_range_index_test.v │ │ │ ├── fixed_array_map_test.v │ │ │ ├── fixed_array_of_alias_struct_test.v │ │ │ ├── fixed_array_of_builtin_struct_with_fn_call_test.v │ │ │ ├── fixed_array_of_fn_test.v │ │ │ ├── fixed_array_of_interfaces_equality_test.v │ │ │ ├── fixed_array_of_option_multi_size_test.v │ │ │ ├── fixed_array_of_option_test.v │ │ │ ├── fixed_array_of_threads_test.v │ │ │ ├── fixed_array_of_threads_wait_test.v │ │ │ ├── fixed_array_op_overload_test.v │ │ │ ├── fixed_array_return_decl_test.v │ │ │ ├── fixed_array_test.v │ │ │ ├── fixed_array_to_fixed_size_method_test.v │ │ │ ├── fixed_array_to_string_test.v │ │ │ ├── fixed_array_with_map_test.v │ │ │ ├── mixed_fixed_array_and_array_init_test.v │ │ │ ├── multiple_arr_fixed_test.v │ │ │ ├── multiple_fixed_array_var_init_test.v │ │ │ ├── slice_rval_test.v │ │ │ ├── sorting_by_different_criteria_test.v │ │ │ ├── sorting_by_references_test.v │ │ │ ├── sorting_compare_fn_with_mut_reference_test.v │ │ │ ├── static_arrays_using_const_for_size_test.v │ │ │ ├── swap_array_test.v │ │ │ └── unsafe_fixed_array_test.v │ │ ├── builtin_maps/ │ │ │ ├── complex_map_op_test.v │ │ │ ├── datatypes_set_public_elements_test.v │ │ │ ├── map_alias_key_test.v │ │ │ ├── map_and_array_with_fns_test.v │ │ │ ├── map_assign_array_of_interface_test.v │ │ │ ├── map_assign_interface_values_with_implicit_casts_test.v │ │ │ ├── map_auto_str_ptr_test.v │ │ │ ├── map_builtin_call_test.v │ │ │ ├── map_clear_test.v │ │ │ ├── map_complex_array_test.v │ │ │ ├── map_complex_fixed_array_test.v │ │ │ ├── map_enum_keys_test.v │ │ │ ├── map_equality_test.v │ │ │ ├── map_fixed_array_if_guard_test.v │ │ │ ├── map_fn_test.v │ │ │ ├── map_generic_call_test.v │ │ │ ├── map_generic_keys_with_in_op_test.v │ │ │ ├── map_get_anon_fn_value_test.v │ │ │ ├── map_get_anon_fn_value_with_mut_arg_test.v │ │ │ ├── map_get_assign_blank_test.v │ │ │ ├── map_high_order_assign_test.v │ │ │ ├── map_init_with_enum_keys_test.v │ │ │ ├── map_init_with_multi_enum_keys_test.v │ │ │ ├── map_init_with_update_test.v │ │ │ ├── map_key_alias_test.v │ │ │ ├── map_key_expr_test.v │ │ │ ├── map_literals_method_call_test.v │ │ │ ├── map_mut_fn_test.v │ │ │ ├── map_reference_value_test.v │ │ │ ├── map_selector_assign_test.v │ │ │ ├── map_sumtype_value_init_test.v │ │ │ ├── map_sumtype_values_test.v │ │ │ ├── map_to_string_test.v │ │ │ ├── map_type_alias_test.v │ │ │ ├── map_value_init_test.v │ │ │ ├── map_value_ref_interp_test.v │ │ │ ├── map_value_with_option_result_test.v │ │ │ ├── map_with_selector_test.v │ │ │ ├── maps_equal_test.v │ │ │ ├── modules/ │ │ │ │ └── geometry/ │ │ │ │ └── geometry.v │ │ │ └── unsafe_pointers_to_map_values_test.v │ │ ├── builtin_overflow_test.v │ │ ├── builtin_strings_and_interpolation/ │ │ │ ├── cstrings_test.c.v │ │ │ ├── high_ascii_const_rune_test.v │ │ │ ├── num_lit_call_method_test.v │ │ │ ├── ptr_str_method_test.v │ │ │ ├── raw_string_test.v │ │ │ ├── str_array_of_reference_test.v │ │ │ ├── str_circular_test.v │ │ │ ├── str_gen_test.v │ │ │ ├── str_reference_struct_test.v │ │ │ ├── string_alias_of_struct_test.v │ │ │ ├── string_alias_test.v │ │ │ ├── string_array_of_ref_type_test.v │ │ │ ├── string_escape_backslash_test.v │ │ │ ├── string_index_in_for_mut_in_test.v │ │ │ ├── string_index_or_test.v │ │ │ ├── string_interpolation_alias_test.v │ │ │ ├── string_interpolation_array_test.v │ │ │ ├── string_interpolation_custom_str_test.v │ │ │ ├── string_interpolation_float_fmt_test.v │ │ │ ├── string_interpolation_floats_test.v │ │ │ ├── string_interpolation_function_test.v │ │ │ ├── string_interpolation_inner_cbr_test.v │ │ │ ├── string_interpolation_match_expr_test.v │ │ │ ├── string_interpolation_multi_level_test.v │ │ │ ├── string_interpolation_multi_return_test.v │ │ │ ├── string_interpolation_multistmt_test.v │ │ │ ├── string_interpolation_of_array_of_structs_test.v │ │ │ ├── string_interpolation_shared_test.v │ │ │ ├── string_interpolation_string_args_test.v │ │ │ ├── string_interpolation_string_lit_with_fmt_test.v │ │ │ ├── string_interpolation_struct_test.v │ │ │ ├── string_interpolation_struct_with_usize_field_test.v │ │ │ ├── string_interpolation_sumtype_test.v │ │ │ ├── string_interpolation_test.v │ │ │ ├── string_interpolation_variadic_test.v │ │ │ ├── string_interpolation_with_escape_test.v │ │ │ ├── string_interpolation_with_inner_quotes_test.v │ │ │ ├── string_map_with_generic_struct_value_test.v │ │ │ ├── string_option_none_test.v │ │ │ ├── string_ref_struct_test.v │ │ │ ├── string_struct_interpolation_test.v │ │ │ ├── strings_builder_shift_array_reverse_test.v │ │ │ ├── strings_unicode_test.v │ │ │ ├── tag_autostr_allowrecurse_test.v │ │ │ └── vargs_auto_str_method_and_println_test.v │ │ ├── c_array_test.c │ │ ├── c_array_test.c.v │ │ ├── c_const_u8_test.v │ │ ├── c_function/ │ │ │ ├── array.c │ │ │ ├── code.c │ │ │ ├── code_test.c.v │ │ │ ├── pass_ref_test.c.v │ │ │ └── v.mod │ │ ├── c_function_mut_param/ │ │ │ ├── code.c │ │ │ ├── code_test.c.v │ │ │ ├── option_args_test.c.v │ │ │ └── v.mod │ │ ├── c_struct_free/ │ │ │ ├── c_struct_free_property_test.c.v │ │ │ └── free_struct.c │ │ ├── c_struct_with_reserved_field_name_test.v │ │ ├── c_structs/ │ │ │ ├── anon.h │ │ │ ├── csize.h │ │ │ ├── cstruct.h │ │ │ ├── cstruct_alias.h │ │ │ ├── cstruct_alias_test.c.v │ │ │ ├── cstruct_alias_test.v │ │ │ ├── cstruct_anon_eq_test.c.v │ │ │ ├── cstruct_anon_test.c.v │ │ │ ├── cstruct_arr_map_test.c.v │ │ │ ├── cstruct_default_value_test.c.v │ │ │ ├── cstruct_fields_are_pub_test.c.v │ │ │ ├── cstruct_iterator_test.c.v │ │ │ ├── cstruct_nested_anon_test.c.v │ │ │ ├── cstruct_ref_test.c.v │ │ │ ├── cstruct_str_test.c.v │ │ │ ├── cstruct_sumtype_test.c.v │ │ │ ├── cstruct_test.c.v │ │ │ ├── deep.h │ │ │ ├── iterator.h │ │ │ ├── return_csize_test.v │ │ │ └── v.mod │ │ ├── casts/ │ │ │ ├── as_cast_already_smartcast_sumtype_test.v │ │ │ ├── as_cast_is_expr_sumtype_fn_result_test.v │ │ │ ├── as_cast_literal_test.v │ │ │ ├── as_cast_selector_test.v │ │ │ ├── autocast_in_if_conds_1_test.v │ │ │ ├── autocast_in_if_conds_2_test.v │ │ │ ├── autocast_in_if_conds_3_test.v │ │ │ ├── autocast_in_if_conds_4_test.v │ │ │ ├── autocast_in_if_conds_5_test.v │ │ │ ├── cast_bool_to_int_test.v │ │ │ ├── cast_comptime_test.v │ │ │ ├── cast_empty_struct_to_option.v │ │ │ ├── cast_f64_to_u64_boundary_test.v │ │ │ ├── cast_fixed_array_to_ptr_ptr_test.v │ │ │ ├── cast_in_comptime_if_test.v │ │ │ ├── cast_in_index_of_ref_fixed_array_test.v │ │ │ ├── cast_int_to_interface_test.v │ │ │ ├── cast_interface_to_impl_test.v │ │ │ ├── cast_interface_value_in_match_test.v │ │ │ ├── cast_none_to_option_test.v │ │ │ ├── cast_option_to_interface_test.v │ │ │ ├── cast_precedence_test.v │ │ │ ├── cast_sumtype_as_generic_test.v │ │ │ ├── cast_sumtype_fixed_array_test.v │ │ │ ├── cast_test.js.v │ │ │ ├── cast_to_alias_test.v │ │ │ ├── cast_to_array_test.v │ │ │ ├── cast_to_byte_test.v │ │ │ ├── cast_to_empty_interface_test.v │ │ │ ├── cast_to_interface_test.v │ │ │ ├── cast_to_interface_with_struct_field_default_test.v │ │ │ ├── cast_to_u8_test.v │ │ │ ├── cast_with_call_in_address_test.v │ │ │ ├── conversions_test.v │ │ │ ├── voidptr_to_u64_cast_a_test.v │ │ │ └── voidptr_to_u64_cast_b_test.v │ │ ├── cflags/ │ │ │ ├── includes/ │ │ │ │ └── myinclude.h │ │ │ ├── v.mod │ │ │ └── vmodroot_and_vroot_test.c.v │ │ ├── chan_same_fn_name_test.v │ │ ├── char_literal_bytes_test.v │ │ ├── clash_var_fn_name_test.v │ │ ├── clash_var_name_of_array_and_map_test.v │ │ ├── closure_with_fn_ref_var_test.v │ │ ├── complex_dim_fixed_array_test.v │ │ ├── comptime/ │ │ │ ├── comptime_aggregate_var_test.v │ │ │ ├── comptime_arch_test.v │ │ │ ├── comptime_arr_type_test.v │ │ │ ├── comptime_array_fixed_field_test.v │ │ │ ├── comptime_at_test.v │ │ │ ├── comptime_attr_test.v │ │ │ ├── comptime_attribute_call_syntax_test.v │ │ │ ├── comptime_attribute_selector_test.v │ │ │ ├── comptime_bittness_and_endianess_test.v │ │ │ ├── comptime_branching_working_without_compile_error_test.v │ │ │ ├── comptime_call_in_fn_call_test.v │ │ │ ├── comptime_call_is_check_test.v │ │ │ ├── comptime_call_map_receiver_test.v │ │ │ ├── comptime_call_method_closure_test.v │ │ │ ├── comptime_call_or_block_test.v │ │ │ ├── comptime_call_slice_arg_test.v │ │ │ ├── comptime_call_test.v │ │ │ ├── comptime_call_tmpl_variable_scope_test.tpl │ │ │ ├── comptime_call_tmpl_variable_scope_test.v │ │ │ ├── comptime_call_type_test.v │ │ │ ├── comptime_call_void_test.v │ │ │ ├── comptime_closure_field_access_test.v │ │ │ ├── comptime_concrete_type_register_test.v │ │ │ ├── comptime_const_def_test.v │ │ │ ├── comptime_default_value_indexexpr_test.v │ │ │ ├── comptime_default_value_test.v │ │ │ ├── comptime_deref_or_ref_test.v │ │ │ ├── comptime_dump_test.v │ │ │ ├── comptime_else_map_init_markused_test.v │ │ │ ├── comptime_enum_test.v │ │ │ ├── comptime_enum_values_test.v │ │ │ ├── comptime_eq_test.v │ │ │ ├── comptime_field_attrs_quotes_test.v │ │ │ ├── comptime_field_indirections_test.v │ │ │ ├── comptime_field_name_check_test.v │ │ │ ├── comptime_field_selector_test.v │ │ │ ├── comptime_for_alias_methods_test.v │ │ │ ├── comptime_for_alias_type_test.v │ │ │ ├── comptime_for_break_test.v │ │ │ ├── comptime_for_empty_loop_eval_stmts_test.v │ │ │ ├── comptime_for_fixed_array_field_test.v │ │ │ ├── comptime_for_if_cond_check_test.v │ │ │ ├── comptime_for_in_field_selector_test.v │ │ │ ├── comptime_for_in_field_typeof_test.v │ │ │ ├── comptime_for_in_field_with_generic_fn_test.v │ │ │ ├── comptime_for_in_fields_FieldData_test.v │ │ │ ├── comptime_for_in_options_struct_test.v │ │ │ ├── comptime_for_lock_field_test.v │ │ │ ├── comptime_for_map_arg_test.v │ │ │ ├── comptime_for_method_call_in_print_call_test.v │ │ │ ├── comptime_for_method_call_test.v │ │ │ ├── comptime_for_method_call_with_args_test.v │ │ │ ├── comptime_for_method_param_test.v │ │ │ ├── comptime_for_mod_name_test.v │ │ │ ├── comptime_for_over_struct_with_C_reserved_word_fields_test.v │ │ │ ├── comptime_for_selector_array_test.v │ │ │ ├── comptime_for_selector_test.v │ │ │ ├── comptime_for_struct_field_infix_expr_test.v │ │ │ ├── comptime_for_test.v │ │ │ ├── comptime_generic_arg_test.v │ │ │ ├── comptime_generic_container_test.v │ │ │ ├── comptime_generic_map_test.v │ │ │ ├── comptime_generic_ret_test.v │ │ │ ├── comptime_generic_test.v │ │ │ ├── comptime_generic_unaliased_typ_test.v │ │ │ ├── comptime_if_assign_test.v │ │ │ ├── comptime_if_at_expr_test.v │ │ │ ├── comptime_if_check_const_test.v │ │ │ ├── comptime_if_expr_evaluate_test.v │ │ │ ├── comptime_if_expr_generic_typ_is_type_test.v │ │ │ ├── comptime_if_expr_in_const_decl_test.v │ │ │ ├── comptime_if_expr_in_struct_field_default_test.v │ │ │ ├── comptime_if_expr_test.v │ │ │ ├── comptime_if_expr_with_result_call_test.v │ │ │ ├── comptime_if_generic_shift_test.v │ │ │ ├── comptime_if_glibc_test.v │ │ │ ├── comptime_if_is_interface_test.v │ │ │ ├── comptime_if_is_pointer_test.v │ │ │ ├── comptime_if_is_test.v │ │ │ ├── comptime_if_pkgconfig_test.v │ │ │ ├── comptime_if_sizeof_test.v │ │ │ ├── comptime_if_test.v │ │ │ ├── comptime_if_threads_no_test.v │ │ │ ├── comptime_if_threads_yes_test.v │ │ │ ├── comptime_if_top_1_test.v │ │ │ ├── comptime_if_top_2_test.v │ │ │ ├── comptime_if_top_3_test.v │ │ │ ├── comptime_in_type_checking_test.v │ │ │ ├── comptime_indirection_check_test.v │ │ │ ├── comptime_indirections_test.v │ │ │ ├── comptime_infer_generic_map_test.v │ │ │ ├── comptime_infix_assign_test.v │ │ │ ├── comptime_infix_test.v │ │ │ ├── comptime_is_check_test.v │ │ │ ├── comptime_is_interface_check_test.v │ │ │ ├── comptime_kinds_test.v │ │ │ ├── comptime_map_fields_decode_test.v │ │ │ ├── comptime_map_generic_test.v │ │ │ ├── comptime_map_it_test.v │ │ │ ├── comptime_map_part_generic_test.v │ │ │ ├── comptime_map_test.v │ │ │ ├── comptime_match_assign_test.v │ │ │ ├── comptime_match_at_expr_test.v │ │ │ ├── comptime_match_eval_only_true_branch_test.v │ │ │ ├── comptime_match_fntype_test.v │ │ │ ├── comptime_match_for_field_type_test.v │ │ │ ├── comptime_match_for_field_value_test.v │ │ │ ├── comptime_match_generic_inside_if_test.v │ │ │ ├── comptime_match_generic_type_test.v │ │ │ ├── comptime_match_ret_test.v │ │ │ ├── comptime_match_type_2_test.v │ │ │ ├── comptime_match_type_check_test.v │ │ │ ├── comptime_match_type_test.v │ │ │ ├── comptime_match_unaliased_typ_test.v │ │ │ ├── comptime_match_value_check_test.v │ │ │ ├── comptime_method_args_test.v │ │ │ ├── comptime_method_call_test.v │ │ │ ├── comptime_method_call_with_check_test.v │ │ │ ├── comptime_method_test.v │ │ │ ├── comptime_methods_generic_struct_test.v │ │ │ ├── comptime_multiline_attr_test.v │ │ │ ├── comptime_name_check_test.v │ │ │ ├── comptime_on_generics_func_test.v │ │ │ ├── comptime_on_method_arg_test.v │ │ │ ├── comptime_option_field_test.v │ │ │ ├── comptime_params_test.v │ │ │ ├── comptime_println_test.v │ │ │ ├── comptime_propagate_test.v │ │ │ ├── comptime_ptr_field_test.v │ │ │ ├── comptime_ref_arg_test.v │ │ │ ├── comptime_selector_assign_test.v │ │ │ ├── comptime_selector_generic_arg_test.v │ │ │ ├── comptime_selector_member_test.v │ │ │ ├── comptime_selector_mut_test.v │ │ │ ├── comptime_selector_ptr_test.v │ │ │ ├── comptime_shared_field_test.v │ │ │ ├── comptime_smart_receiver_test.v │ │ │ ├── comptime_smartcast_assert_test.v │ │ │ ├── comptime_smartcast_test.v │ │ │ ├── comptime_smartcast_var_test.v │ │ │ ├── comptime_sumtype_cast_2_test.v │ │ │ ├── comptime_sumtype_cast_3_test.v │ │ │ ├── comptime_sumtype_cast_test.v │ │ │ ├── comptime_test_ident_test.v │ │ │ ├── comptime_type_test.v │ │ │ ├── comptime_typeof_value_test.v │ │ │ ├── comptime_unaliased_typ_test.v │ │ │ ├── comptime_unwrap_test.v │ │ │ ├── comptime_value_d_default_test.v │ │ │ ├── comptime_var_assignment_test.v │ │ │ ├── comptime_var_is_check_test.v │ │ │ ├── comptime_var_on_multiple_args_test.v │ │ │ ├── comptime_var_param_test.v │ │ │ ├── comptime_var_unwrap_test.v │ │ │ ├── comptime_variant_interp_test.v │ │ │ ├── comptime_variant_test.v │ │ │ └── comptime_voidptr_unsafe_nil_test.v │ │ ├── comptime_generic_comptime_variant_test.v │ │ ├── comptime_pseudo_fn_with_dollar_test.v │ │ ├── concurrency/ │ │ │ ├── atomic_test.v │ │ │ ├── autolock_array1_test.v │ │ │ ├── autolock_array2_test.v │ │ │ ├── break_in_lock_test.v │ │ │ ├── chan_fixed_test.v │ │ │ ├── chan_generic_test.v │ │ │ ├── chan_interface_test.v │ │ │ ├── chan_push_enum_test.v │ │ │ ├── chan_try_push_int_test.v │ │ │ ├── chan_try_push_literal_test.v │ │ │ ├── channels_test.v │ │ │ ├── default_thread_stack_size_test.v │ │ │ ├── inherited_vars_test.v │ │ │ ├── lock_selector_test.v │ │ │ ├── mut_receiver_gowrapper_test.v │ │ │ ├── select_auto_sync_test.v │ │ │ ├── selector_shared_var_test.v │ │ │ ├── semaphore_test.v │ │ │ ├── semaphore_timed_test.v │ │ │ ├── shared_arg_test.v │ │ │ ├── shared_array_any_filter_map_all_test.v │ │ │ ├── shared_array_append_many_test.v │ │ │ ├── shared_array_indexing_test.v │ │ │ ├── shared_array_last_test.v │ │ │ ├── shared_array_ptr_test.v │ │ │ ├── shared_array_slice_test.v │ │ │ ├── shared_array_sort_test.v │ │ │ ├── shared_array_test.v │ │ │ ├── shared_assign_test.v │ │ │ ├── shared_autolock_test.v │ │ │ ├── shared_elem_test.v │ │ │ ├── shared_fixed_array_init_test.v │ │ │ ├── shared_fn_return_test.v │ │ │ ├── shared_generic_test.v │ │ │ ├── shared_if_expr_test.v │ │ │ ├── shared_in_test.v │ │ │ ├── shared_interface_test.v │ │ │ ├── shared_lock_2_test.v │ │ │ ├── shared_lock_3_test.v │ │ │ ├── shared_lock_4_test.v │ │ │ ├── shared_lock_5_test.v │ │ │ ├── shared_lock_6_test.v │ │ │ ├── shared_lock_expr_assert_test.v │ │ │ ├── shared_lock_expr_test.v │ │ │ ├── shared_lock_test.v │ │ │ ├── shared_map_delete_test.v │ │ │ ├── shared_map_ptr_test.v │ │ │ ├── shared_map_test.v │ │ │ ├── shared_option_test.v │ │ │ ├── shared_str_test.v │ │ │ ├── shared_struct_field_test.v │ │ │ ├── shared_struct_method_call_test.v │ │ │ ├── shared_unordered_mixed_test.v │ │ │ ├── spawn_array_mut_test.v │ │ │ ├── spawn_method_on_generic_struct_test.v │ │ │ ├── spawn_with_cond_fncall_test.v │ │ │ ├── spawn_with_different_method_receivers_test.v │ │ │ ├── thread_array_test.v │ │ │ ├── thread_ptr_ret_test.v │ │ │ ├── thread_returns_test.v │ │ │ ├── thread_to_string_test.v │ │ │ ├── thread_type_test.v │ │ │ ├── thread_wait_ptr_test.v │ │ │ └── volatile_vars_test.v │ │ ├── conditions/ │ │ │ ├── ifs/ │ │ │ │ ├── check_in_is_consistency_test.v │ │ │ │ ├── if_assign_test.v │ │ │ │ ├── if_cond_with_alias_test.v │ │ │ │ ├── if_cond_with_option_test.v │ │ │ │ ├── if_expr_nested_with_option_result_test.v │ │ │ │ ├── if_expr_of_multi_stmts_test.v │ │ │ │ ├── if_expr_of_option_test.v │ │ │ │ ├── if_expr_with_array_call_test.v │ │ │ │ ├── if_expr_with_compound_conds_1_test.v │ │ │ │ ├── if_expr_with_compound_conds_2_test.v │ │ │ │ ├── if_expr_with_compound_conds_3_test.v │ │ │ │ ├── if_expr_with_compound_conds_4_test.v │ │ │ │ ├── if_expr_with_condition_using_tmp_var_test.v │ │ │ │ ├── if_expr_with_continue_in_branch_test.v │ │ │ │ ├── if_expr_with_empty_array_init_test.v │ │ │ │ ├── if_expr_with_enum_test.v │ │ │ │ ├── if_expr_with_fn_call_result_test.v │ │ │ │ ├── if_expr_with_generic_sumtype_test.v │ │ │ │ ├── if_expr_with_index_expr_test.v │ │ │ │ ├── if_expr_with_method_call_option_test.v │ │ │ │ ├── if_expr_with_multi_array_call_test.v │ │ │ │ ├── if_expr_with_nested_array_call_test.v │ │ │ │ ├── if_expr_with_nested_match_expr_test.v │ │ │ │ ├── if_expr_with_result_test.v │ │ │ │ ├── if_expr_with_struct_init_test.v │ │ │ │ ├── if_expr_with_sumtype_map_test.v │ │ │ │ ├── if_expr_with_sumtype_test.v │ │ │ │ ├── if_expression_test.v │ │ │ │ ├── if_guard_test.v │ │ │ │ ├── if_guard_with_multi_return_test.v │ │ │ │ ├── if_guard_with_struct_option_fntype_field_test.v │ │ │ │ ├── if_match_branches_with_call_expr_with_or_block_test.v │ │ │ │ ├── if_smartcast_likely_test.v │ │ │ │ ├── if_smartcast_multi_conds_test.v │ │ │ │ ├── if_smartcast_nested_selector_exprs_test.v │ │ │ │ ├── if_smartcast_test.v │ │ │ │ ├── ifexpr_with_option_result_test.v │ │ │ │ └── in_expression_test.v │ │ │ └── matches/ │ │ │ ├── match_aliases_test.v │ │ │ ├── match_array_of_reference_sumtype_test.v │ │ │ ├── match_branch_with_array_expression_test.v │ │ │ ├── match_case_with_struct_init_test.v │ │ │ ├── match_compound_type_cond_test.v │ │ │ ├── match_const_range_test.v │ │ │ ├── match_error_to_none_test.v │ │ │ ├── match_expr_in_infix_expr_test.v │ │ │ ├── match_expr_nested_test.v │ │ │ ├── match_expr_nested_with_option_result1_test.v │ │ │ ├── match_expr_nested_with_option_result2_test.v │ │ │ ├── match_expr_result_test.v │ │ │ ├── match_expr_returning_option_test.v │ │ │ ├── match_expr_returning_sumtype_test.v │ │ │ ├── match_expr_skip_in_infix_expr_test.v │ │ │ ├── match_expr_with_assign_sumtype_test.v │ │ │ ├── match_expr_with_auto_promote_number_test.v │ │ │ ├── match_expr_with_branch_returning_1_test.v │ │ │ ├── match_expr_with_branch_returning_2_test.v │ │ │ ├── match_expr_with_empty_array_init_test.v │ │ │ ├── match_expr_with_enum_test.v │ │ │ ├── match_expr_with_if_or_match_expr_test.v │ │ │ ├── match_expr_with_last_branch_aggregate_test.v │ │ │ ├── match_expr_with_non_last_if_expr_test.v │ │ │ ├── match_expr_with_one_branch_test.v │ │ │ ├── match_expr_with_opt_result_test.v │ │ │ ├── match_expr_with_promote_number_test.v │ │ │ ├── match_expr_with_result_test.v │ │ │ ├── match_expr_with_string_fn_test.v │ │ │ ├── match_expr_with_struct_init_test.v │ │ │ ├── match_expression_for_types_test.v │ │ │ ├── match_expression_with_fn_names_in_branches_test.v │ │ │ ├── match_expression_with_for_loop_test.v │ │ │ ├── match_in_fn_call_test.v │ │ │ ├── match_in_if_expression_test.v │ │ │ ├── match_in_map_init_test.v │ │ │ ├── match_in_map_or_expr_test.v │ │ │ ├── match_interface_test.v │ │ │ ├── match_reference_sumtype_var_test.v │ │ │ ├── match_return_fn_test.v │ │ │ ├── match_return_reference_test.v │ │ │ ├── match_smartcast_test.v │ │ │ ├── match_struct_type_test.v │ │ │ ├── match_sumtype_arr_test.v │ │ │ ├── match_sumtype_var_aggregate_test.v │ │ │ ├── match_sumtype_var_aggregate_var_str_test.v │ │ │ ├── match_sumtype_var_return_sumtype_test.v │ │ │ ├── match_sumtype_var_shadow_and_as_test.v │ │ │ ├── match_test.v │ │ │ ├── match_with_complex_exprs_in_branches_test.v │ │ │ ├── match_with_complex_sumtype_exprs_add_print_test.v │ │ │ ├── match_with_complex_sumtype_exprs_test.v │ │ │ ├── match_with_comptime_if_expr_in_branch_test.v │ │ │ ├── match_with_multi_sumtype_exprs_test.v │ │ │ ├── match_with_mut_cond_var_test.v │ │ │ ├── match_with_return_result_test.v │ │ │ └── multiple_matchs_in_one_expr_test.v │ │ ├── consts/ │ │ │ ├── const_and_global_with_same_name_test.v │ │ │ ├── const_array_fixed_test.v │ │ │ ├── const_array_init_order_test.v │ │ │ ├── const_array_struct_test.v │ │ │ ├── const_array_test.v │ │ │ ├── const_as_enum_value_test.v │ │ │ ├── const_c_string_test.v │ │ │ ├── const_call_expr_order_test.v │ │ │ ├── const_can_use_options_results_test.v │ │ │ ├── const_comptime_eval_before_vinit_test.v │ │ │ ├── const_cstr_test.v │ │ │ ├── const_depend_update_expr_test.v │ │ │ ├── const_embed_test.v │ │ │ ├── const_eval_simple_int_expressions_at_comptime_test.v │ │ │ ├── const_fixed_array_containing_references_to_itself_test.v │ │ │ ├── const_fixed_array_of_reference_value_test.v │ │ │ ├── const_fixed_array_of_string_value_msvc_test.v │ │ │ ├── const_fixed_array_return_unresolved_test.v │ │ │ ├── const_fixed_array_return_unresolved_test_reordered.v │ │ │ ├── const_fixed_array_test.v │ │ │ ├── const_fixed_array_with_type_alias_test.v │ │ │ ├── const_fixed_array_with_var_item_test.v │ │ │ ├── const_from_bytes_test.v │ │ │ ├── const_from_comptime_if_expr_test.v │ │ │ ├── const_from_multi_branchs_of_if_expr_test.v │ │ │ ├── const_function_call_init_order_test.v │ │ │ ├── const_global_arr_test.v │ │ │ ├── const_if_fixed_array_test.v │ │ │ ├── const_indexexpr_dep_test.v │ │ │ ├── const_init_array_index_test.v │ │ │ ├── const_init_order_test.v │ │ │ ├── const_many_pluses_with_raw_string_literal_test.v │ │ │ ├── const_map_init_order_test.v │ │ │ ├── const_markused_test.v │ │ │ ├── const_name_equals_fn_name_test.v │ │ │ ├── const_order_with_str_interp_test.v │ │ │ ├── const_propagate_result_test.v │ │ │ ├── const_reference_argument_test.v │ │ │ ├── const_representation_test.v │ │ │ ├── const_resolution_test.v │ │ │ ├── const_selector_expr_order_test.v │ │ │ ├── const_test.v │ │ │ ├── const_use_nested_options_test.v │ │ │ ├── const_with_fn_param_with_the_same_name_test.v │ │ │ ├── constant_array_size_test.v │ │ │ └── my_utils/ │ │ │ └── my_utils.v │ │ ├── create_dll/ │ │ │ ├── create_win_dll.c.v │ │ │ └── create_win_dll_test.v │ │ ├── defer/ │ │ │ ├── defer_fixed_array_test.v │ │ │ ├── defer_if_comptime_test.v │ │ │ ├── defer_return_test.v │ │ │ ├── defer_static_test.v │ │ │ ├── defer_test.v │ │ │ ├── defer_use_returned_value_test.v │ │ │ ├── defer_with_fn_var_test.v │ │ │ └── scoped_defer_test.v │ │ ├── empty_array_push_test.v │ │ ├── enum_packed_test.v │ │ ├── enums/ │ │ │ ├── enum_aliases_test.v │ │ │ ├── enum_array_field_test.v │ │ │ ├── enum_array_init_test.v │ │ │ ├── enum_assign_on_anon_fn_test.v │ │ │ ├── enum_attr_2_test.v │ │ │ ├── enum_attr_test.v │ │ │ ├── enum_bitfield_64bit_test.v │ │ │ ├── enum_bitfield_test.v │ │ │ ├── enum_bitfield_works_with_comptime_conditional_in_the_same_scope_test.v │ │ │ ├── enum_custom_static_from_string_test.v │ │ │ ├── enum_default_test.v │ │ │ ├── enum_default_value_in_struct_test.v │ │ │ ├── enum_explicit_size_big_and_small_test.v │ │ │ ├── enum_field_name_same_as_cpp_keywords_test.v │ │ │ ├── enum_field_name_same_as_keyword_test.v │ │ │ ├── enum_flag_alias_op_test.v │ │ │ ├── enum_flag_from_test.v │ │ │ ├── enum_flag_test.v │ │ │ ├── enum_from_generic_static_call_test.v │ │ │ ├── enum_from_generic_static_method_test.v │ │ │ ├── enum_hex_test.v │ │ │ ├── enum_max_test.v │ │ │ ├── enum_on_array_init_test.v │ │ │ ├── enum_print_test.v │ │ │ ├── enum_self_reference_test.v │ │ │ ├── enum_short_infix_commutative_test.v │ │ │ ├── enum_static_from_string_test.v │ │ │ ├── enum_test.v │ │ │ ├── enum_val_test.v │ │ │ ├── enum_with_comptime_const_test.v │ │ │ ├── enum_with_comptime_fn_calls_test.v │ │ │ ├── enum_with_const_test.v │ │ │ ├── fullname_enumval_as_arg_test.v │ │ │ ├── map_with_enum_keys_test.v │ │ │ ├── maps_with_enum_flag_keys_test.v │ │ │ ├── short_enum_syntax_across_module_test.v │ │ │ └── vargs_with_enum_value_test.v │ │ ├── error_void_test.v │ │ ├── eval_shared_library_tcc_test.v │ │ ├── failing_tests_test.v │ │ ├── field_publicity/ │ │ │ └── embed.v │ │ ├── filtering_tests/ │ │ │ ├── filtering_android_outside_termux_test.v │ │ │ ├── filtering_macos_test.v │ │ │ ├── filtering_nix_test.v │ │ │ └── filtering_windows_test.v │ │ ├── fixed_array_2_dims_embed_test.v │ │ ├── fixed_array_2_dims_init_test.v │ │ ├── fixed_array_init_with_init_test.v │ │ ├── fixed_array_init_with_option_array_test.v │ │ ├── fixed_array_multi_return_test.v │ │ ├── fixed_array_on_array_test.v │ │ ├── fixed_array_update_embed_expr_test.v │ │ ├── fixed_array_update_expr_test.v │ │ ├── fns/ │ │ │ ├── aliased_interface_methods_test.v │ │ │ ├── aliased_static_method_test.v │ │ │ ├── anon_c_keywords_closure_test.v │ │ │ ├── anon_fn_call_test.v │ │ │ ├── anon_fn_decl_inside_ternary_test.v │ │ │ ├── anon_fn_decl_with_anon_fn_params_test.v │ │ │ ├── anon_fn_direct_call_with_option_test.v │ │ │ ├── anon_fn_fixed_arr_test.v │ │ │ ├── anon_fn_in_containers_test.v │ │ │ ├── anon_fn_in_generic_call_with_match_and_inner_generic_call_test.v │ │ │ ├── anon_fn_option_call_in_if_expr_test.v │ │ │ ├── anon_fn_option_test.v │ │ │ ├── anon_fn_redefinition_test.v │ │ │ ├── anon_fn_returning_question_test.v │ │ │ ├── anon_fn_test.v │ │ │ ├── anon_fn_with_alias_args_test.v │ │ │ ├── anon_fn_with_array_arguments_test.v │ │ │ ├── anon_fn_with_nested_anon_fn_args_test.v │ │ │ ├── anon_fn_with_option_test.v │ │ │ ├── anon_with_prefix_test.v │ │ │ ├── array_fixed_unresolved_ret_test.v │ │ │ ├── builtin_fn_var_test.v │ │ │ ├── call_args_variadic_sumtype_test.v │ │ │ ├── call_args_variadic_sumtype_with_it_array_variant_test.v │ │ │ ├── call_nested_test.v │ │ │ ├── call_on_anon_test.v │ │ │ ├── call_option_param_test.v │ │ │ ├── call_or_empty_block_test.v │ │ │ ├── call_result_test.v │ │ │ ├── call_struct_params_with_keyword_test.v │ │ │ ├── call_to_str_on_option_test.v │ │ │ ├── call_with_nil_test.v │ │ │ ├── calling_module_functions_with_maps_of_arrays_test.v │ │ │ ├── closure_data_with_gc_test.c.v │ │ │ ├── closure_fn_arg_in_map_test.v │ │ │ ├── closure_generator_test.v │ │ │ ├── closure_in_if_guard_1_test.v │ │ │ ├── closure_in_if_guard_2_test.v │ │ │ ├── closure_of_instance_method_passed_to_voidptr_parameter_test.v │ │ │ ├── closure_of_method_defined_on_alias_test.v │ │ │ ├── closure_option_direct_call_test.v │ │ │ ├── closure_struct_init_cov_regression_test.v │ │ │ ├── closure_test.v │ │ │ ├── closure_variable_in_smartcast_test.v │ │ │ ├── closure_with_fixed_array_var_test.v │ │ │ ├── closure_with_sumtype_var_test.v │ │ │ ├── const_call_or_expr_test.v │ │ │ ├── cross_method_call_test.v │ │ │ ├── decompose_variadic_test.v │ │ │ ├── filter_in_map_test.v │ │ │ ├── filter_test.v │ │ │ ├── fixed_array_on_voidptr_test.v │ │ │ ├── fixed_array_result_return_test.v │ │ │ ├── fn_assignment_test.v │ │ │ ├── fn_call_comptime_array_arg_test.v │ │ │ ├── fn_call_fixed_array_literal_args_test.v │ │ │ ├── fn_call_generic_array_arg_test.v │ │ │ ├── fn_call_interface_args_test.v │ │ │ ├── fn_call_mut_array_of_aliases_args_test.v │ │ │ ├── fn_call_mut_ref_args_test.v │ │ │ ├── fn_call_mut_sumtype_args_test.v │ │ │ ├── fn_call_using_anon_fn_call_args_test.v │ │ │ ├── fn_call_with_newline_opening_brace_test.v │ │ │ ├── fn_cross_assign_test.v │ │ │ ├── fn_expecting_ref_but_returning_struct_test.v │ │ │ ├── fn_expecting_ref_but_returning_struct_time_module_test.v │ │ │ ├── fn_fixed_array_ret_test.v │ │ │ ├── fn_generic_option_none_test.v │ │ │ ├── fn_generic_resolve_test.v │ │ │ ├── fn_heap_promoted_test.v │ │ │ ├── fn_high_test.v │ │ │ ├── fn_index_direct_call_test.v │ │ │ ├── fn_literal_type_test.v │ │ │ ├── fn_multi_return_test.v │ │ │ ├── fn_multiple_returns_test.v │ │ │ ├── fn_mut_arg_of_array_test.v │ │ │ ├── fn_mut_arg_of_interface_test.v │ │ │ ├── fn_mut_arg_of_sumtype_ref_test.v │ │ │ ├── fn_mut_args_test.v │ │ │ ├── fn_name_using_keyword_test.v │ │ │ ├── fn_optional_arg_alias_optional_param_test.v │ │ │ ├── fn_ptr_call_test.v │ │ │ ├── fn_ptr_deref_test.v │ │ │ ├── fn_return_alias_of_ptr_test.v │ │ │ ├── fn_return_fn_test.v │ │ │ ├── fn_return_match_expr_with_result_test.v │ │ │ ├── fn_return_mut_sumtype_test.v │ │ │ ├── fn_return_opt_or_res_of_array_test.v │ │ │ ├── fn_return_result_fixed_array_return_fn_propagate_result_test.v │ │ │ ├── fn_return_typeof_test.v │ │ │ ├── fn_shared_return_test.v │ │ │ ├── fn_test.c.v │ │ │ ├── fn_type_aliases_test.v │ │ │ ├── fn_type_call_of_match_expr_test.v │ │ │ ├── fn_type_only_argument_test.v │ │ │ ├── fn_var_name_using_reserved_test.v │ │ │ ├── fn_variadic_test.v │ │ │ ├── fn_voidptr_param_call_with_nonpointer_rvalue_test.v │ │ │ ├── fn_with_array_of_aliases_argument_test.v │ │ │ ├── fn_with_fixed_array_args_test.v │ │ │ ├── fn_with_fixed_array_function_args_test.v │ │ │ ├── fn_with_opt_or_res_of_multi_return_test.v │ │ │ ├── generic_fn_order_issue_25889_test.v │ │ │ ├── generic_static_method_call_test.v │ │ │ ├── go_anon_fn_call_with_ref_arg_test.v │ │ │ ├── go_anon_fn_variable_call_test.v │ │ │ ├── go_array_wait_test.v │ │ │ ├── go_array_wait_without_go_test.v │ │ │ ├── go_call_anon_fn_with_closure_test.v │ │ │ ├── go_call_fn_return_test.v │ │ │ ├── go_call_fn_using_map_value_test.v │ │ │ ├── go_call_fn_with_anon_fn_arg_test.v │ │ │ ├── go_call_fn_with_anon_fn_array_arg_test.v │ │ │ ├── go_call_generic_fn_test.v │ │ │ ├── go_call_interface_method_test.v │ │ │ ├── go_handle_for_functions_returning_array_test.v │ │ │ ├── go_wait_1_test.v │ │ │ ├── go_wait_2_test.v │ │ │ ├── go_wait_3_test.v │ │ │ ├── go_wait_option_test.v │ │ │ ├── go_wait_with_fn_of_interface_parameter_test.v │ │ │ ├── iface_method_fixed_arr_test.v │ │ │ ├── interface_methods_fixed_arr_test.v │ │ │ ├── iter_alias_fn_test.v │ │ │ ├── lambda_as_struct_field_value_test.v │ │ │ ├── lambda_expr_test.v │ │ │ ├── lambda_expr_with_mut_param_test.v │ │ │ ├── lambda_expr_with_result_test.v │ │ │ ├── lambda_generic_test.v │ │ │ ├── map_index_call_test.v │ │ │ ├── method_call_chained_test.v │ │ │ ├── method_call_none_check_test.v │ │ │ ├── method_call_on_aggregate_test.v │ │ │ ├── method_call_on_rangeexpr_test.v │ │ │ ├── method_call_resolve_test.v │ │ │ ├── method_call_var_comp_test.v │ │ │ ├── method_first_last_call_test.v │ │ │ ├── methods_as_fields_test.v │ │ │ ├── methods_on_interfaces_test.v │ │ │ ├── multi_return_array_fixed_test.v │ │ │ ├── param_fixed_array_const_test.v │ │ │ ├── return_multi_aliased_fixed_array_test.v │ │ │ ├── return_multi_fixed_arr_test.v │ │ │ ├── sort_fn_def_test.v │ │ │ ├── static_call_on_match_test.v │ │ │ ├── translated_variadic_test.v │ │ │ ├── unused_fn_fixed_array_ret_test.v │ │ │ ├── variadic_fn_chain_test.v │ │ │ └── variadic_sumtype_test.v │ │ ├── for_in_iterator_next_test.v │ │ ├── generic_calls/ │ │ │ ├── country.v │ │ │ ├── country_cases.v │ │ │ ├── currency.v │ │ │ ├── currency_to_code.v │ │ │ ├── curreny_cases.v │ │ │ ├── faker.v │ │ │ ├── faker_country_name.v │ │ │ ├── faker_currency_code.v │ │ │ ├── top_level_domain.v │ │ │ └── top_level_domain_cases.v │ │ ├── generic_selector_ptr_test.v │ │ ├── generics/ │ │ │ ├── checks_for_operator_overrides_should_happen_on_the_concrete_types_when_using_generics_test.v │ │ │ ├── concrete_type_as_generic_fn_type_1_test.v │ │ │ ├── concrete_type_as_generic_fn_type_2_test.v │ │ │ ├── default_type_with_ref_test.v │ │ │ ├── foo.h │ │ │ ├── generic_alias_callback_test.v │ │ │ ├── generic_alias_fn_op_call_test.v │ │ │ ├── generic_alias_map_type_test.v │ │ │ ├── generic_anon_fn_inside_generic_fn_test.v │ │ │ ├── generic_array_clone_test.v │ │ │ ├── generic_array_init_test.v │ │ │ ├── generic_array_of_alias_test.v │ │ │ ├── generic_array_of_sumtype_push_test.v │ │ │ ├── generic_array_pass_test.v │ │ │ ├── generic_array_ret_test.v │ │ │ ├── generic_array_test.v │ │ │ ├── generic_arrays_sum_test.v │ │ │ ├── generic_as_cast_on_map_test.v │ │ │ ├── generic_call_mixing_args_test.v │ │ │ ├── generic_chan_test.v │ │ │ ├── generic_comparison_for_conditional_assign_test.v │ │ │ ├── generic_complex_sumtype_test.v │ │ │ ├── generic_comptime_arg_test.v │ │ │ ├── generic_comptime_map_test.v │ │ │ ├── generic_comptime_test.v │ │ │ ├── generic_default_expression_in_or_block_test.v │ │ │ ├── generic_different_type_test.v │ │ │ ├── generic_dump_test.v │ │ │ ├── generic_empty_interface_to_multi_struct_test.v │ │ │ ├── generic_empty_interface_to_struct_test.v │ │ │ ├── generic_fn_array_infer_var_test.v │ │ │ ├── generic_fn_assign_generics_struct_test.v │ │ │ ├── generic_fn_call_by_generic_fn_test.v │ │ │ ├── generic_fn_call_map_keys_values_test.v │ │ │ ├── generic_fn_call_with_reference_argument_test.v │ │ │ ├── generic_fn_cast_to_alias_test.v │ │ │ ├── generic_fn_infer_fixed_array_test.v │ │ │ ├── generic_fn_infer_fn_type_argument_test.v │ │ │ ├── generic_fn_infer_fn_type_using_ref_arg_test.v │ │ │ ├── generic_fn_infer_map_argument_test.v │ │ │ ├── generic_fn_infer_map_test.v │ │ │ ├── generic_fn_infer_modifier_test.v │ │ │ ├── generic_fn_infer_multi_paras_test.v │ │ │ ├── generic_fn_infer_nested_generic_fn_test.v │ │ │ ├── generic_fn_infer_nested_struct_test.v │ │ │ ├── generic_fn_infer_struct_test.v │ │ │ ├── generic_fn_infer_test.v │ │ │ ├── generic_fn_infer_variadic_test.v │ │ │ ├── generic_fn_method_call_on_generic_param_test.v │ │ │ ├── generic_fn_multi_mutable_struct_test.v │ │ │ ├── generic_fn_multi_return_test.v │ │ │ ├── generic_fn_param_test.v │ │ │ ├── generic_fn_ref_level_test.v │ │ │ ├── generic_fn_returning_option_and_result_test.v │ │ │ ├── generic_fn_returning_type_with_T_test.v │ │ │ ├── generic_fn_struct_test.v │ │ │ ├── generic_fn_type_with_different_generic_type_test.v │ │ │ ├── generic_fn_typeof_name_test.v │ │ │ ├── generic_fn_upper_name_type_test.v │ │ │ ├── generic_fn_using_generic_type_in_if_test.v │ │ │ ├── generic_fn_with_anon_fn_test.v │ │ │ ├── generic_fn_with_comptime_for_test.v │ │ │ ├── generic_fn_with_nested_generic_fn_call_test.v │ │ │ ├── generic_fn_with_short_generic_struct_init_syntax_1_test.v │ │ │ ├── generic_fn_with_short_generic_struct_init_syntax_2_test.v │ │ │ ├── generic_for_mut_val_test.v │ │ │ ├── generic_function_error_propagation_test.v │ │ │ ├── generic_functions_with_normal_function_test.v │ │ │ ├── generic_if_ret_test.v │ │ │ ├── generic_init_syntax_test.v │ │ │ ├── generic_interface_array_type_infer_test.v │ │ │ ├── generic_interface_field_test.v │ │ │ ├── generic_interface_implements_concrete_type_test.v │ │ │ ├── generic_interface_infer_test.v │ │ │ ├── generic_interface_multi_type_params_test.v │ │ │ ├── generic_interface_test.v │ │ │ ├── generic_lambda_expr_test.v │ │ │ ├── generic_lambda_inference_test.v │ │ │ ├── generic_map_alias_test.v │ │ │ ├── generic_match_expr_test.v │ │ │ ├── generic_method_lambda_arg_test.v │ │ │ ├── generic_method_with_variadic_generic_args_test.v │ │ │ ├── generic_muls_test.v │ │ │ ├── generic_operator_overload_test.v │ │ │ ├── generic_options_with_reserved_ident_test.v │ │ │ ├── generic_receiver_embed_test.v │ │ │ ├── generic_recursive_fn_test.v │ │ │ ├── generic_resolve_test.v │ │ │ ├── generic_return_array_generic_test.v │ │ │ ├── generic_return_test.v │ │ │ ├── generic_selector_field_test.v │ │ │ ├── generic_selector_indexexpr_test.v │ │ │ ├── generic_selector_infix_test.v │ │ │ ├── generic_selector_len_test.v │ │ │ ├── generic_selector_test.v │ │ │ ├── generic_selector_type_test.v │ │ │ ├── generic_smartcast_test.v │ │ │ ├── generic_spawn_test.v │ │ │ ├── generic_static_call_test.v │ │ │ ├── generic_static_method_test.v │ │ │ ├── generic_struct_cstruct_test.v │ │ │ ├── generic_struct_field_unwrap_test.v │ │ │ ├── generic_struct_init_ptr_test.v │ │ │ ├── generic_struct_init_with_field_struct_init_test.v │ │ │ ├── generic_struct_init_with_generic_cast_test.v │ │ │ ├── generic_struct_init_with_reference_struct_type_test.v │ │ │ ├── generic_struct_init_with_update_expr_test.v │ │ │ ├── generic_struct_recursive_test.v │ │ │ ├── generic_struct_return_test.v │ │ │ ├── generic_struct_test.v │ │ │ ├── generic_struct_with_linked_list_of_refs_field_test.v │ │ │ ├── generic_sumtype_cast_test.v │ │ │ ├── generic_sumtype_init_in_generic_fn_call_test.v │ │ │ ├── generic_sumtype_insts_test.v │ │ │ ├── generic_sumtype_method_test.v │ │ │ ├── generic_sumtype_of_alias_generic_struct_test.v │ │ │ ├── generic_sumtype_repeated_test.v │ │ │ ├── generic_sumtype_str_test.v │ │ │ ├── generic_sumtype_test.v │ │ │ ├── generic_typeof_idx_test.v │ │ │ ├── generic_typeof_test.v │ │ │ ├── generic_var_loop_test.v │ │ │ ├── generic_with_ptr_as_param_test.v │ │ │ ├── generics_T_typ_test.v │ │ │ ├── generics_anon_fn_decl_with_type_only_arg_test.v │ │ │ ├── generics_array_append_test.v │ │ │ ├── generics_array_builtin_method_call_test.v │ │ │ ├── generics_array_delete_test.v │ │ │ ├── generics_array_drop_test.v │ │ │ ├── generics_array_init_test.v │ │ │ ├── generics_array_map_with_generic_callback_test.v │ │ │ ├── generics_array_method_call_with_multi_types_test.v │ │ │ ├── generics_array_of_interface_method_call_test.v │ │ │ ├── generics_array_of_threads_test.v │ │ │ ├── generics_array_typedef_test.v │ │ │ ├── generics_assign_reference_generic_struct_test.v │ │ │ ├── generics_call_with_fixed_array_arg_test.v │ │ │ ├── generics_call_with_interface_arg_test.v │ │ │ ├── generics_call_with_reference_arg_test.v │ │ │ ├── generics_chans_select_test.v │ │ │ ├── generics_closure_fn_direct_call_test.v │ │ │ ├── generics_closure_fn_test.v │ │ │ ├── generics_closures_with_different_generic_types_test.v │ │ │ ├── generics_fixed_array_assign_test.v │ │ │ ├── generics_fn_return_generic_interface_test.v │ │ │ ├── generics_fn_return_result_test.v │ │ │ ├── generics_fn_return_types_with_generic_struct_test.v │ │ │ ├── generics_fn_variable_1_test.v │ │ │ ├── generics_fn_variable_2_test.v │ │ │ ├── generics_fn_variable_3_test.v │ │ │ ├── generics_for_in_iterate_test.v │ │ │ ├── generics_from_modules/ │ │ │ │ ├── genericmodule/ │ │ │ │ │ └── take.v │ │ │ │ ├── infer_generic_struct_test.v │ │ │ │ ├── inference_test.v │ │ │ │ └── newmodule/ │ │ │ │ └── newmodule.v │ │ │ ├── generics_in_big_struct_method_test.v │ │ │ ├── generics_in_generics_test.v │ │ │ ├── generics_indirect_test.v │ │ │ ├── generics_interface_decl_test.v │ │ │ ├── generics_interface_method_test.v │ │ │ ├── generics_interface_with_generic_method_using_generic_struct_test.v │ │ │ ├── generics_interface_with_generic_sumtype_test.v │ │ │ ├── generics_interface_with_multi_generic_structs_test.v │ │ │ ├── generics_interface_with_multi_generic_types_test.v │ │ │ ├── generics_interface_with_non_generic_method_test.v │ │ │ ├── generics_map_with_generic_type_key_test.v │ │ │ ├── generics_map_with_reference_arg_test.v │ │ │ ├── generics_method_call_with_short_syntax_args_test.v │ │ │ ├── generics_method_chaining_call_test.v │ │ │ ├── generics_method_on_alias_struct_receiver_test.v │ │ │ ├── generics_method_on_embed_struct_test.v │ │ │ ├── generics_method_on_generic_structs_test.v │ │ │ ├── generics_method_on_nested_struct2_test.v │ │ │ ├── generics_method_on_nested_struct_test.v │ │ │ ├── generics_method_on_receiver_aliases_types_test.v │ │ │ ├── generics_method_on_receiver_types_test.v │ │ │ ├── generics_method_ordering_test.v │ │ │ ├── generics_method_returning_option_test.v │ │ │ ├── generics_method_str_overload_test.v │ │ │ ├── generics_method_test.v │ │ │ ├── generics_method_variable_test.v │ │ │ ├── generics_method_with_diff_generic_names_test.v │ │ │ ├── generics_method_with_embedded_structs_test.v │ │ │ ├── generics_method_with_generic_anon_fn_argument_test.v │ │ │ ├── generics_method_with_multi_types_test.v │ │ │ ├── generics_method_with_nested_generic_method_test.v │ │ │ ├── generics_method_with_sumtype_args_test.v │ │ │ ├── generics_multi_array_in_test.v │ │ │ ├── generics_multi_type_comptime_call_test.v │ │ │ ├── generics_multi_types_struct_init_test.v │ │ │ ├── generics_mutual_recursive_struct_reference_test.v │ │ │ ├── generics_nested_struct_init_test.v │ │ │ ├── generics_return_closure_test.v │ │ │ ├── generics_return_fixed_array_test.v │ │ │ ├── generics_return_generics_struct_test.v │ │ │ ├── generics_return_inconsistent_types_generics_struct_test.v │ │ │ ├── generics_return_multi_array_test.v │ │ │ ├── generics_return_multiple_generics_struct_test.v │ │ │ ├── generics_return_recursive_generics_struct_test.v │ │ │ ├── generics_return_reference_generics_struct_test.v │ │ │ ├── generics_return_result_maps_test.v │ │ │ ├── generics_stack_of_sumtype_push_test.v │ │ │ ├── generics_str_intp_test.v │ │ │ ├── generics_struct_anon_fn_fields_test.v │ │ │ ├── generics_struct_anon_fn_type_test.v │ │ │ ├── generics_struct_field_with_default_fn_type_test.v │ │ │ ├── generics_struct_field_with_default_struct_value_test.v │ │ │ ├── generics_struct_field_with_generics_struct_elements_test.v │ │ │ ├── generics_struct_free_test.v │ │ │ ├── generics_struct_init_in_generic_fn_test.v │ │ │ ├── generics_struct_init_test.v │ │ │ ├── generics_struct_init_with_generic_struct_items_test.v │ │ │ ├── generics_struct_init_with_inconsistent_generic_types_1_test.v │ │ │ ├── generics_struct_init_with_inconsistent_generic_types_2_test.v │ │ │ ├── generics_struct_init_with_inconsistent_generic_types_4_test.v │ │ │ ├── generics_struct_init_with_inconsistent_generic_types_5_test.v │ │ │ ├── generics_struct_init_with_inconsistent_generic_types_6_test.v │ │ │ ├── generics_struct_init_with_inconsistent_generic_types_7_test.v │ │ │ ├── generics_struct_inst_method_call_test.v │ │ │ ├── generics_struct_method_params_is_generics_struct_and_not_called_test.v │ │ │ ├── generics_struct_no_key_init_test.v │ │ │ ├── generics_struct_parent_has_str_to_string_test.v │ │ │ ├── generics_struct_to_string_test.v │ │ │ ├── generics_struct_types_infer_test.v │ │ │ ├── generics_struct_with_array_test.v │ │ │ ├── generics_struct_with_inconsistent_generic_types_1_test.v │ │ │ ├── generics_struct_with_non_generic_interface_test.v │ │ │ ├── generics_struct_with_option_fn_test.v │ │ │ ├── generics_test.v │ │ │ ├── generics_union_dump_test.v │ │ │ ├── generics_with_anon_generics_fn_test.v │ │ │ ├── generics_with_assign_nested_generics_call_test.v │ │ │ ├── generics_with_cascaded_multiple_nested_generics_fn_test.v │ │ │ ├── generics_with_complex_nested_generics_type_test.v │ │ │ ├── generics_with_embed_generics_method_call_test.v │ │ │ ├── generics_with_embed_generics_structs_test.v │ │ │ ├── generics_with_embed_generics_test.v │ │ │ ├── generics_with_empty_array_arg_test.v │ │ │ ├── generics_with_fixed_array_type_test.v │ │ │ ├── generics_with_generics_fn_return_generics_fn_type_test.v │ │ │ ├── generics_with_generics_fn_return_generics_map_type_test.v │ │ │ ├── generics_with_generics_fn_type_parameter_test.v │ │ │ ├── generics_with_generics_struct_init_test.v │ │ │ ├── generics_with_generics_struct_receiver_test.v │ │ │ ├── generics_with_multi_generics_fn_name_test.v │ │ │ ├── generics_with_multi_generics_struct_types_test.v │ │ │ ├── generics_with_multi_nested_generic_method_call_ref_arg_test.v │ │ │ ├── generics_with_multi_nested_generic_method_call_test.v │ │ │ ├── generics_with_multiple_generics_struct_receiver_test.v │ │ │ ├── generics_with_nested_external_generics_fn_test.v │ │ │ ├── generics_with_nested_generic_method_call_test.v │ │ │ ├── generics_with_nested_generic_struct_init_test.v │ │ │ ├── generics_with_nested_generic_type_parameter_test.v │ │ │ ├── generics_with_nested_generics_fn_infer_call_test.v │ │ │ ├── generics_with_nested_generics_fn_inst_call_test.v │ │ │ ├── generics_with_nested_generics_fn_test.v │ │ │ ├── generics_with_pointer_index_test.v │ │ │ ├── generics_with_recursive_generics_fn_test.v │ │ │ ├── generics_with_recursive_generics_struct_test.v │ │ │ ├── generics_with_reference_generic_args_test.v │ │ │ ├── generics_with_variadic_generic_args_test.v │ │ │ ├── infer_generic_array_type_in_nested_call_test.v │ │ │ ├── lamda_param_and_ret_test.v │ │ │ ├── modules/ │ │ │ │ ├── ecs/ │ │ │ │ │ └── ecs.v │ │ │ │ └── simplemodule/ │ │ │ │ ├── importing_test.v │ │ │ │ └── simplemodule.v │ │ │ ├── multiple_generic_resolve_test.v │ │ │ ├── return_closure_f64_test.v │ │ │ ├── return_closure_int_test.v │ │ │ ├── struct_generic_map_index_test.v │ │ │ └── v.mod │ │ ├── global_fixed_arr_init_test.v │ │ ├── global_generic_sumtype_test.v │ │ ├── global_init_array_test.v │ │ ├── global_init_test.v │ │ ├── goto_test.v │ │ ├── if_elseif_else_test.v │ │ ├── if_expr_in_or_block_test.v │ │ ├── if_guard_elseif_test.v │ │ ├── import_aliases_test.v │ │ ├── import_order_1_test.v │ │ ├── import_order_2_test.v │ │ ├── imported_symbols_test.v │ │ ├── in_op_array_fixed_test.v │ │ ├── include_c_gen_fn_headers/ │ │ │ ├── cheader.h │ │ │ └── include_c.v │ │ ├── index_on_loop_test.v │ │ ├── indexexpr_or_test.v │ │ ├── indexexpr_with_anon_fn_test.v │ │ ├── indexexpr_with_assign_test.v │ │ ├── indexexpr_with_if_expr_test.v │ │ ├── infix_expr_and_or_operate_unnecessary_eval_test.v │ │ ├── infix_expr_test.v │ │ ├── infix_expr_with_overflow_test.v │ │ ├── init_global_test.v │ │ ├── int_cmp_test.v │ │ ├── integer_size_test.v │ │ ├── interface_generic_implements_test.v │ │ ├── interface_string_ref_arg_test.v │ │ ├── interfaces/ │ │ │ ├── append_struct_to_interface_array_test.v │ │ │ ├── appending_to_mut_array_in_fn_param_test.v │ │ │ ├── array_init_with_interface_test.v │ │ │ ├── big_array_allocation_test.v │ │ │ ├── empty_interface_is_another_empty_interface_check_test.v │ │ │ ├── empty_interface_test.v │ │ │ ├── interface_and_embedded_struct_build_test.v │ │ │ ├── interface_arg_test.v │ │ │ ├── interface_arr_auto_str_test.v │ │ │ ├── interface_arr_for_mut_iter_index_test.v │ │ │ ├── interface_arr_init_test.v │ │ │ ├── interface_array_init_test.v │ │ │ ├── interface_array_methods_test.v │ │ │ ├── interface_as_cast_in_anon_fn_test.v │ │ │ ├── interface_auto_str_gen_test.v │ │ │ ├── interface_auto_str_test.v │ │ │ ├── interface_closure_test.v │ │ │ ├── interface_edge_cases/ │ │ │ │ ├── array_of_interfaces_test.v │ │ │ │ ├── array_of_interfaces_with_utility_fn_test.v │ │ │ │ ├── assign_to_interface_field_test.v │ │ │ │ ├── empty_interface_1_test.v │ │ │ │ ├── empty_interface_println_test.v │ │ │ │ ├── fn_returning_voidptr_casted_as_interface_test.v │ │ │ │ ├── i1_test.v │ │ │ │ ├── i2_test.v │ │ │ │ ├── i3_test.v │ │ │ │ ├── i4_test.v │ │ │ │ ├── i5_test.v │ │ │ │ ├── i6_test.v │ │ │ │ ├── i7_test.v │ │ │ │ ├── i8_test.v │ │ │ │ ├── i9_test.v │ │ │ │ ├── interface_many_named_test.v │ │ │ │ ├── pass_voidptr_as_interface_reference_test.v │ │ │ │ └── voidptr_casted_as_an_interface_test.v │ │ │ ├── interface_embedding_call_test.v │ │ │ ├── interface_embedding_complex_test.v │ │ │ ├── interface_embedding_deep_nesting_test.v │ │ │ ├── interface_embedding_method_call_test.v │ │ │ ├── interface_embedding_recursive_test.v │ │ │ ├── interface_embedding_smartcast_test.v │ │ │ ├── interface_embedding_test.v │ │ │ ├── interface_embedding_with_interface_para_test.v │ │ │ ├── interface_eq_methods_with_option_and_ref_test.v │ │ │ ├── interface_equality_test.v │ │ │ ├── interface_err_msg_print_test.v │ │ │ ├── interface_fields_test.v │ │ │ ├── interface_fields_typearray_test.v │ │ │ ├── interface_fixed_array_ret_test.v │ │ │ ├── interface_fn_return_array_of_interface_test.v │ │ │ ├── interface_fn_return_with_struct_init_test.v │ │ │ ├── interface_generic_multi_return_test.v │ │ │ ├── interface_generic_test.v │ │ │ ├── interface_int_test.v │ │ │ ├── interface_method_closure_test.v │ │ │ ├── interface_method_using_struct_embed_test.v │ │ │ ├── interface_method_with_params_implemented_with_type_aliased_params_test.v │ │ │ ├── interface_method_with_struct_embed_test.v │ │ │ ├── interface_multi_return_test.v │ │ │ ├── interface_mut_value_update_test.v │ │ │ ├── interface_nested_field_test.v │ │ │ ├── interface_nil_cmp_test.v │ │ │ ├── interface_only_decl_with_option_test.v │ │ │ ├── interface_runtime_conversions_test.v │ │ │ ├── interface_smartcast_call_test.v │ │ │ ├── interface_str_method_test.v │ │ │ ├── interface_struct_embedding_test.v │ │ │ ├── interface_struct_test.v │ │ │ ├── interface_test.v │ │ │ ├── interface_uninitialized_field_str_test.v │ │ │ ├── interface_var_selector_test.v │ │ │ ├── interface_var_test.v │ │ │ ├── interface_variadic_test.v │ │ │ ├── interface_with_multi_nested_embed_1_test.v │ │ │ ├── interface_with_multi_nested_embed_2_test.v │ │ │ ├── interface_with_multi_nested_embed_3_test.v │ │ │ ├── interface_with_option_field_test.v │ │ │ ├── interfaces_map_test.v │ │ │ ├── modules/ │ │ │ │ ├── module_a/ │ │ │ │ │ └── module_a.v │ │ │ │ └── module_b/ │ │ │ │ └── module_b.v │ │ │ └── multiple_embed_external_interface_test.v │ │ ├── interop_test.c.v │ │ ├── interop_test.js.v │ │ ├── keyword_as_params_field_test.v │ │ ├── keyword_escaping_test.v │ │ ├── known_errors/ │ │ │ ├── known_errors_test.v │ │ │ └── testdata/ │ │ │ ├── README.md │ │ │ ├── cast_aliases_on_generics_type.vv │ │ │ └── shared_in_alias_test.vv │ │ ├── last_stmt_fn_call_or_expr_test.v │ │ ├── last_stmt_semicolon_or_expr_test.v │ │ ├── left_padding_test.v │ │ ├── left_shift_array_fixed_test.v │ │ ├── local/ │ │ │ └── local.v │ │ ├── local_test.v │ │ ├── loops/ │ │ │ ├── for_c_init_with_var_assign_test.v │ │ │ ├── for_c_init_with_var_inc_test.v │ │ │ ├── for_c_multi_vars_test.v │ │ │ ├── for_c_multiple_expressions_in_increment_test.v │ │ │ ├── for_c_stmt_with_option_call_test.v │ │ │ ├── for_c_stmt_with_result_call_test.v │ │ │ ├── for_cond_test.v │ │ │ ├── for_in_alias_test.v │ │ │ ├── for_in_array_with_struct_init_test.v │ │ │ ├── for_in_containers_of_fixed_array_test.v │ │ │ ├── for_in_iterator_of_generic_struct_1_test.v │ │ │ ├── for_in_iterator_of_generic_struct_2_test.v │ │ │ ├── for_in_iterator_of_generic_struct_3_test.v │ │ │ ├── for_in_iterator_test.v │ │ │ ├── for_in_map_of_pointers_test.v │ │ │ ├── for_in_mut_array_index_test.v │ │ │ ├── for_in_mut_array_with_infix_expr_test.v │ │ │ ├── for_in_mut_array_with_mul_test.v │ │ │ ├── for_in_mut_iterator_val_test.v │ │ │ ├── for_in_mut_mutable_app_field_test.v │ │ │ ├── for_in_mut_reference_selector_val_test.v │ │ │ ├── for_in_mut_struct_val_test.v │ │ │ ├── for_in_mut_val_test.v │ │ │ ├── for_in_mut_val_with_if_val_in_test.v │ │ │ ├── for_in_mut_with_ptrs_test.v │ │ │ ├── for_in_option_test.v │ │ │ ├── for_in_ref_arr_test.v │ │ │ ├── for_in_ref_map_test.v │ │ │ ├── for_label_continue_break_test.v │ │ │ ├── for_loop_with_option2_test.v │ │ │ ├── for_loop_with_option_test.v │ │ │ ├── for_loops_2_test.v │ │ │ ├── for_loops_test.v │ │ │ ├── for_mut_var_argument_op_test.v │ │ │ ├── for_select_test.v │ │ │ ├── for_smartcast_test.v │ │ │ ├── for_sumtype_arr_test.v │ │ │ └── for_t_fields_with_comptime_if_test.v │ │ ├── map_cast_test.v │ │ ├── mark_as_referenced_test.v │ │ ├── match_array_fixed_test.v │ │ ├── match_branch_par_expr_test.v │ │ ├── match_multi_return_closure_heap_test.v │ │ ├── match_on_return_test.v │ │ ├── match_or_expr_test.v │ │ ├── module_test.v │ │ ├── module_type_cast_test.v │ │ ├── modules/ │ │ │ ├── alias_to_another_module/ │ │ │ │ └── alias.v │ │ │ ├── amodule/ │ │ │ │ ├── another_internal_module_test.v │ │ │ │ ├── internal_module_test.v │ │ │ │ └── module.v │ │ │ ├── another_module/ │ │ │ │ └── module.v │ │ │ ├── callback_consumer_module/ │ │ │ │ ├── callback_consumer_test.v │ │ │ │ ├── main.v │ │ │ │ ├── mod1/ │ │ │ │ │ └── faulty.v │ │ │ │ ├── mod2/ │ │ │ │ │ └── faulty.v │ │ │ │ └── v.mod │ │ │ ├── consts_with_complex_init/ │ │ │ │ ├── config.v │ │ │ │ └── consts_should_not_conflict_test.v │ │ │ ├── consts_with_or_blocks_in_different_files/ │ │ │ │ ├── config.v │ │ │ │ └── consts_should_not_conflict_test.v │ │ │ ├── enum_from_string_in_different_mods/ │ │ │ │ ├── src/ │ │ │ │ │ ├── main_test.v │ │ │ │ │ ├── mod/ │ │ │ │ │ │ └── mod.v │ │ │ │ │ └── mod2/ │ │ │ │ │ └── mod2.v │ │ │ │ └── v.mod │ │ │ ├── geometry/ │ │ │ │ └── geometry.v │ │ │ ├── interface_from_another_module/ │ │ │ │ ├── ifam_test.v │ │ │ │ └── mod/ │ │ │ │ └── mod.v │ │ │ ├── methods_struct_another_module/ │ │ │ │ ├── import_symbol_static_method_test.v │ │ │ │ └── methods_struct_test.v │ │ │ ├── sub/ │ │ │ │ ├── foo/ │ │ │ │ │ ├── c/ │ │ │ │ │ │ ├── foo.h │ │ │ │ │ │ ├── foo.v │ │ │ │ │ │ └── v.mod │ │ │ │ │ └── const.v │ │ │ │ ├── foo.c.v │ │ │ │ ├── global_fixed_array_test.v │ │ │ │ └── sub_test.v │ │ │ └── submodules/ │ │ │ ├── submodules.v │ │ │ ├── submodules_test.v │ │ │ └── test/ │ │ │ ├── test.v │ │ │ └── test2/ │ │ │ └── test2.v │ │ ├── multi_line_with_options_test.v │ │ ├── multi_return_nil_voidptr_test.v │ │ ├── multi_return_test.v │ │ ├── multiple_comptime_tmpl_in_one_fn_test.v │ │ ├── multiple_paths_in_vmodules/ │ │ │ ├── main.vv │ │ │ ├── path1/ │ │ │ │ ├── .gitignore │ │ │ │ └── xxx/ │ │ │ │ └── m.v │ │ │ ├── path2/ │ │ │ │ └── yyy/ │ │ │ │ └── m.v │ │ │ ├── path3/ │ │ │ │ └── zzz/ │ │ │ │ └── m.v │ │ │ ├── path4/ │ │ │ │ ├── .cache/ │ │ │ │ │ └── README.md │ │ │ │ └── hunam6/ │ │ │ │ └── voak/ │ │ │ │ ├── foo/ │ │ │ │ │ └── foo.v │ │ │ │ ├── v.mod │ │ │ │ └── voak.v │ │ │ ├── submodule_of_third_party_main.vv │ │ │ └── vmodules_overrides_test.v │ │ ├── multiret_in_or_expr_test.v │ │ ├── multiret_with_maps_test.v │ │ ├── multiret_with_ptrtype_test.v │ │ ├── multiret_with_result_test.v │ │ ├── multiret_with_sumtype_test.v │ │ ├── mut_arg_struct_pointer_rebind_test.v │ │ ├── named_break_continue_test.v │ │ ├── nest_defer_fn_test.v │ │ ├── nested_anonfunc_and_for_break_test.v │ │ ├── nested_fors_with_labels_test.v │ │ ├── nested_if_expr_method_call_test.v │ │ ├── nested_if_return_test.v │ │ ├── nested_map_index_test.v │ │ ├── nested_map_of_fn_call_test.v │ │ ├── nested_map_test.v │ │ ├── nested_multiline_comments_test.v │ │ ├── nested_or_in_assign_decl_test.v │ │ ├── no_closures/ │ │ │ ├── method_closure.out │ │ │ ├── method_closure.vv │ │ │ ├── simple_closure.out │ │ │ └── simple_closure.vv │ │ ├── old_generic_scanner_test.v │ │ ├── options/ │ │ │ ├── check_init_value_for_arrays_of_option_test.v │ │ │ ├── concat_option_test.v │ │ │ ├── modules/ │ │ │ │ ├── another_module/ │ │ │ │ │ └── module.v │ │ │ │ └── mymod/ │ │ │ │ ├── mod.v │ │ │ │ └── mod_test.v │ │ │ ├── nested_option_call_test.v │ │ │ ├── nested_option_struct_init_test.v │ │ │ ├── nested_or_expr_call_test.v │ │ │ ├── none_checking_test.v │ │ │ ├── option_2_test.v │ │ │ ├── option_alias_eq_test.v │ │ │ ├── option_alias_fn_ret_test.v │ │ │ ├── option_anon_struct_test.v │ │ │ ├── option_arr_auto_str_test.v │ │ │ ├── option_array_compare_test.v │ │ │ ├── option_array_dump_in_generic_fn_test.v │ │ │ ├── option_array_fixed_struct_test.v │ │ │ ├── option_array_fixed_test.v │ │ │ ├── option_array_init_mix_test.v │ │ │ ├── option_array_init_test.v │ │ │ ├── option_array_push_test.v │ │ │ ├── option_array_submodule_test.v │ │ │ ├── option_array_test.v │ │ │ ├── option_assign_none_test.v │ │ │ ├── option_auto_eq_test.v │ │ │ ├── option_auto_heap_test.v │ │ │ ├── option_call_on_orexpr_test.v │ │ │ ├── option_call_propagation_test.v │ │ │ ├── option_case_test.v │ │ │ ├── option_cast_primitive_test.v │ │ │ ├── option_cast_test.v │ │ │ ├── option_compvar_types_test.v │ │ │ ├── option_compvar_val_test.v │ │ │ ├── option_concat_str_test.v │ │ │ ├── option_concatexpr_test.v │ │ │ ├── option_const_test.v │ │ │ ├── option_default_values_test.v │ │ │ ├── option_diff_alias_arg_test.v │ │ │ ├── option_dump_test.v │ │ │ ├── option_embed_field_test.v │ │ │ ├── option_empty_map_test.v │ │ │ ├── option_enum_compare_none_test.v │ │ │ ├── option_expr_with_array_value_test.v │ │ │ ├── option_fixed_arr_const_test.v │ │ │ ├── option_fixed_array_2_test.v │ │ │ ├── option_fixed_array_test.v │ │ │ ├── option_fn_alias_test.v │ │ │ ├── option_fn_guard_test.v │ │ │ ├── option_fn_multi_ret_test.v │ │ │ ├── option_fn_struct_init_test.v │ │ │ ├── option_fn_test.v │ │ │ ├── option_fn_var_test.v │ │ │ ├── option_fn_variadic_test.v │ │ │ ├── option_fn_voidptr_test.v │ │ │ ├── option_fntype_assign_test.v │ │ │ ├── option_for_mut_test.v │ │ │ ├── option_for_or_block_test.v │ │ │ ├── option_free_method_test.v │ │ │ ├── option_generic_alias_test.v │ │ │ ├── option_generic_array_field_test.v │ │ │ ├── option_generic_array_mut_test.v │ │ │ ├── option_generic_array_test.v │ │ │ ├── option_generic_cast_none_test.v │ │ │ ├── option_generic_param_test.v │ │ │ ├── option_generic_ptr_return_test.v │ │ │ ├── option_generic_return_test.v │ │ │ ├── option_generic_selector_unwrap_test.v │ │ │ ├── option_generic_sumtype_test.v │ │ │ ├── option_heap_var_test.v │ │ │ ├── option_if_assign_and_fallthrough_test.v │ │ │ ├── option_if_expr_test.v │ │ │ ├── option_if_expr_with_panic_call_test.v │ │ │ ├── option_if_infer_test.v │ │ │ ├── option_if_option_test.v │ │ │ ├── option_if_unwrap_test.v │ │ │ ├── option_ifguard_array_of_option_test.v │ │ │ ├── option_import_struct_test.v │ │ │ ├── option_in_loop_test.v │ │ │ ├── option_index_amp_test.v │ │ │ ├── option_indexexpr_eq_test.v │ │ │ ├── option_init_ptr_test.v │ │ │ ├── option_init_test.v │ │ │ ├── option_interface_test.v │ │ │ ├── option_last_call_test.v │ │ │ ├── option_map_fn_type_value_test.v │ │ │ ├── option_map_fn_value_test.v │ │ │ ├── option_map_init_test.v │ │ │ ├── option_map_none_test.v │ │ │ ├── option_map_set_test.v │ │ │ ├── option_map_val_test.v │ │ │ ├── option_map_value_test.v │ │ │ ├── option_match_case_cast_test.v │ │ │ ├── option_match_case_enum_test.v │ │ │ ├── option_match_case_test.v │ │ │ ├── option_match_cases_test.v │ │ │ ├── option_match_eq_test.v │ │ │ ├── option_match_expr_test.v │ │ │ ├── option_match_none_test.v │ │ │ ├── option_match_test.v │ │ │ ├── option_method_selector_test.v │ │ │ ├── option_multi_ret_test.v │ │ │ ├── option_multi_return_assign_test.v │ │ │ ├── option_multi_return_if_test.v │ │ │ ├── option_multi_return_opt_test.v │ │ │ ├── option_multi_return_test.v │ │ │ ├── option_mut_generic_array_test.v │ │ │ ├── option_mut_if_none_test.v │ │ │ ├── option_mut_param_test.v │ │ │ ├── option_mut_struct_init_test.v │ │ │ ├── option_nested_fixed_array_test.v │ │ │ ├── option_nested_selector_test.v │ │ │ ├── option_nested_selector_unwrap_test.v │ │ │ ├── option_nested_struct_test.v │ │ │ ├── option_nested_unwrapping_test.v │ │ │ ├── option_none_to_anon_struct_test.v │ │ │ ├── option_operator_overload_test.v │ │ │ ├── option_or_block_test.v │ │ │ ├── option_or_expr_dump_test.v │ │ │ ├── option_or_expr_with_non_opt_test.v │ │ │ ├── option_or_result_fixed_arr_test.v │ │ │ ├── option_print_errors_test.v │ │ │ ├── option_print_ptr_test.v │ │ │ ├── option_ptr_arg_heap_test.v │ │ │ ├── option_ptr_arg_none_test.v │ │ │ ├── option_ptr_arg_test.v │ │ │ ├── option_ptr_cast_test.v │ │ │ ├── option_ptr_field_test.v │ │ │ ├── option_ptr_generic_test.v │ │ │ ├── option_ptr_iface_test.v │ │ │ ├── option_ptr_init_empty_test.v │ │ │ ├── option_ptr_init_test.v │ │ │ ├── option_ptr_nil_test.v │ │ │ ├── option_ptr_ptr_test.v │ │ │ ├── option_ptr_test.v │ │ │ ├── option_ptr_unwrap_selector_test.v │ │ │ ├── option_ptr_unwrap_test.v │ │ │ ├── option_ptr_zero_test.v │ │ │ ├── option_push_array_opt_test.v │ │ │ ├── option_reference_params_test.v │ │ │ ├── option_result_interface_ret_test.v │ │ │ ├── option_ret_ptr_generic_test.v │ │ │ ├── option_return_fixed_arr_test.v │ │ │ ├── option_selector_assign_test.v │ │ │ ├── option_selector_cast_test.v │ │ │ ├── option_selector_fn_none_test.v │ │ │ ├── option_selector_interface_ptr_test.v │ │ │ ├── option_selector_nested_unwrap_test.v │ │ │ ├── option_selector_nested_unwrapped_test.v │ │ │ ├── option_selector_none_unwrap_test.v │ │ │ ├── option_selector_test.v │ │ │ ├── option_selector_unwrap_test.v │ │ │ ├── option_selector_unwrap_types_test.v │ │ │ ├── option_selector_unwrapping_test.v │ │ │ ├── option_struct_compare_test.v │ │ │ ├── option_struct_default_test.v │ │ │ ├── option_struct_field_init_test.v │ │ │ ├── option_struct_init_default_test.v │ │ │ ├── option_struct_init_interface_test.v │ │ │ ├── option_struct_init_on_if_test.v │ │ │ ├── option_struct_init_test.v │ │ │ ├── option_struct_init_with_opt_test.v │ │ │ ├── option_struct_init_with_ref_opt_test.v │ │ │ ├── option_sum_type_test.v │ │ │ ├── option_sumtype_explicit_cast_test.v │ │ │ ├── option_sumtype_map_test.v │ │ │ ├── option_sumtype_option_variant_test.v │ │ │ ├── option_sumtype_test.v │ │ │ ├── option_sumtype_unwrap_test.v │ │ │ ├── option_sumtype_variant_test.v │ │ │ ├── option_test.c.v │ │ │ ├── option_unwrap_as_cast_test.v │ │ │ ├── option_unwrap_assign_test.v │ │ │ ├── option_unwrap_fn_test.v │ │ │ ├── option_unwrap_ifexpr_test.v │ │ │ ├── option_unwrap_none_test.v │ │ │ ├── option_unwrap_print_test.v │ │ │ ├── option_unwrap_selector_expr_as_cast_test.v │ │ │ ├── option_unwrap_selector_test.v │ │ │ ├── option_unwrap_selector_write_test.v │ │ │ ├── option_unwrap_test.v │ │ │ ├── option_unwrap_unwrap_or_generic_fn_test.v │ │ │ ├── option_unwrapped_arg_generic_opt_test.v │ │ │ ├── option_var_2_test.v │ │ │ ├── option_var_cast_test.v │ │ │ ├── option_var_map_test.v │ │ │ ├── option_var_mut_test.v │ │ │ ├── option_var_test.v │ │ │ ├── option_void_2_test.v │ │ │ ├── option_void_fn_return_test.v │ │ │ ├── option_with_error_test.v │ │ │ ├── or_expr_with_comptime_test.v │ │ │ ├── or_expr_with_multi_stmts_test.v │ │ │ ├── or_expr_with_nested_match_expr_test.v │ │ │ ├── var_option_arr_test.v │ │ │ ├── var_option_as_arg_test.v │ │ │ ├── var_option_comptime_test.v │ │ │ ├── var_option_opt_arg_test.v │ │ │ ├── var_option_opt_multi_return_test.v │ │ │ ├── var_option_struct_test.v │ │ │ └── var_option_sumtype_test.v │ │ ├── or_block_endwiths_expr_test.v │ │ ├── orm_array_field_test.v │ │ ├── orm_create_several_tables_test.v │ │ ├── orm_enum_test.v │ │ ├── orm_handle_error_for_select_from_not_created_table_test.v │ │ ├── orm_joined_tables_select_test.v │ │ ├── orm_or_test.v │ │ ├── orm_stmt_wrong_return_checking_test.v │ │ ├── orm_sub_array_struct_test.v │ │ ├── orm_sub_struct_test.v │ │ ├── orm_table_name_test.v │ │ ├── orm_type_alias_test.v │ │ ├── orm_update_test.v │ │ ├── panic_on_match_branch_test.v │ │ ├── parse_invalid_map_type_test.v │ │ ├── parse_thread_type_test.v │ │ ├── parse_type_of_ref_array_from_another_mod_test.v │ │ ├── parser_line_test.v │ │ ├── pointers/ │ │ │ ├── addr_test.v │ │ │ ├── autogen_free_test.v │ │ │ ├── deref_mut_variable_in_if_expr_test.v │ │ │ ├── dereference_mut_interface_in_loop_test.v │ │ │ ├── double_ref_deref_test.v │ │ │ ├── heap_interface_test.v │ │ │ ├── heap_reference_test.v │ │ │ ├── heap_struct_member_ptr_test.v │ │ │ ├── heap_struct_test.v │ │ │ ├── infix_expr_in_mut_receiver_method_test.v │ │ │ ├── isreftype_test.v │ │ │ ├── offsetof_test.v │ │ │ ├── pointer_arithmetic_test.v │ │ │ ├── pointers_multilevel_casts_test.v │ │ │ ├── pointers_str_test.v │ │ │ ├── pointers_test.v │ │ │ ├── ptr_arithmetic_test.v │ │ │ ├── ref_array_init_test.v │ │ │ ├── ref_callback_test.v │ │ │ ├── ref_return_test.v │ │ │ ├── ref_struct_test.v │ │ │ ├── reference_return_test.v │ │ │ ├── reference_var_followed_block_expr_test.v │ │ │ ├── reference_variable_str_test.v │ │ │ ├── return_voidptr_test.v │ │ │ ├── selectorexpr_alias_to_ptr_test.v │ │ │ ├── unsafe_test.c.v │ │ │ └── vargs_reference_param_test.v │ │ ├── prefix_expr_test.v │ │ ├── printing/ │ │ │ ├── dump_c_structs/ │ │ │ │ ├── dump_c_struct_test.c.v │ │ │ │ ├── epoll.h │ │ │ │ ├── netdb.h │ │ │ │ └── v.mod │ │ │ ├── dump_fns_test.v │ │ │ ├── dump_interface_circular_test.v │ │ │ ├── dump_on_generic_func_test.v │ │ │ ├── print_address_of_reference_int_test.v │ │ │ ├── print_address_of_reference_struct_test.v │ │ │ ├── print_anon_fn_test.v │ │ │ ├── print_charptr_test.v │ │ │ ├── print_fn_test.v │ │ │ ├── print_option_ref_test.v │ │ │ ├── print_reference_function_test.v │ │ │ ├── print_smartcast_interface_variable_test.v │ │ │ ├── print_smartcast_variable_test.v │ │ │ ├── print_test.v │ │ │ └── print_void_ret_test.v │ │ ├── printing_c_structs/ │ │ │ ├── cstruct.h │ │ │ ├── string_interpolation_test.c.v │ │ │ └── v.mod │ │ ├── project_compiling_to_wasm/ │ │ │ ├── abc_d_wasm32_emscripten.c.v │ │ │ ├── abc_notd_wasm32_emscripten.c.v │ │ │ ├── compilation_to_wasm_works_with_d_and_notd_files_test.v │ │ │ ├── main.v │ │ │ └── v.mod │ │ ├── project_importing_v_keywords/ │ │ │ ├── importing_keywords_works_test.v │ │ │ ├── mymod/ │ │ │ │ └── f.v │ │ │ └── v.mod │ │ ├── project_issue_21476/ │ │ │ ├── foo.v │ │ │ ├── main.v │ │ │ ├── project_compiles_test.v │ │ │ └── v.mod │ │ ├── project_with_c_code/ │ │ │ ├── .gitignore │ │ │ ├── main.v │ │ │ ├── main1_test.v │ │ │ ├── mod1/ │ │ │ │ ├── c/ │ │ │ │ │ ├── header.h │ │ │ │ │ └── implementation.c │ │ │ │ └── wrapper.c.v │ │ │ ├── relative.h │ │ │ └── v.mod │ │ ├── project_with_c_code_2/ │ │ │ ├── .gitignore │ │ │ ├── main.v │ │ │ ├── main2_test.v │ │ │ ├── modc/ │ │ │ │ ├── header.h │ │ │ │ ├── impl.c │ │ │ │ └── wrapper.c.v │ │ │ └── v.mod │ │ ├── project_with_c_code_3/ │ │ │ ├── .gitignore │ │ │ ├── main.v │ │ │ ├── main3_test.v │ │ │ ├── mod1/ │ │ │ │ ├── wrapper.c.v │ │ │ │ ├── wrapper.js.v │ │ │ │ └── wrapper.v │ │ │ └── v.mod │ │ ├── project_with_c_code_ct_ifs/ │ │ │ ├── a_linux.h │ │ │ ├── a_nonlinux.h │ │ │ ├── ctimeifblock.c.v │ │ │ └── v.mod │ │ ├── project_with_cpp_code/ │ │ │ ├── compiling_cpp_files_with_a_cplusplus_compiler_test.c.v │ │ │ ├── implementation.cpp │ │ │ ├── implementation.h │ │ │ └── v.mod │ │ ├── project_with_modules_having_submodules/ │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── bin/ │ │ │ │ ├── a_program_under_bin_can_find_mod1_test.v │ │ │ │ └── main.vsh │ │ │ ├── mod1/ │ │ │ │ ├── m.v │ │ │ │ ├── mod11/ │ │ │ │ │ └── m.v │ │ │ │ ├── mod12/ │ │ │ │ │ └── m.v │ │ │ │ ├── mod13/ │ │ │ │ │ └── m.v │ │ │ │ ├── mod14/ │ │ │ │ │ └── m.v │ │ │ │ ├── submodule/ │ │ │ │ │ └── m.v │ │ │ │ └── v.mod │ │ │ ├── tests/ │ │ │ │ └── submodule_test.v │ │ │ └── v.mod │ │ ├── project_with_tests_for_main/ │ │ │ ├── README.md │ │ │ ├── main.v │ │ │ ├── my_other_test.v │ │ │ ├── my_test.v │ │ │ └── v.mod │ │ ├── projects_that_should_compile_test.v │ │ ├── range_expr_logical_and_test.v │ │ ├── range_expr_with_int_test.v │ │ ├── raw_string_ending_withs_backslash_test.v │ │ ├── reflection_attr_quotes_test.v │ │ ├── reflection_sym_test.v │ │ ├── reflection_test.v │ │ ├── reliability/ │ │ │ └── semaphore_wait.v │ │ ├── repeated_multiret_values_test.v │ │ ├── reserved_keyword_asm_test.v │ │ ├── reserved_keywords_array_test.v │ │ ├── reserved_keywords_as_struct_field_test.v │ │ ├── reserved_keywords_can_be_escaped_with_at_test.v │ │ ├── reserved_keywords_if_guard_test.v │ │ ├── resolve_generic_2_test.v │ │ ├── result_call_or_block_with_stmts_test.v │ │ ├── result_with_index_expr_test.v │ │ ├── results_multi_return_test.v │ │ ├── results_test.v │ │ ├── retry_test.v │ │ ├── return_aliases_of_fixed_array_test.v │ │ ├── return_comptime_call_test.v │ │ ├── return_error_in_if_expr_test.v │ │ ├── return_fixed_array_test.v │ │ ├── return_if_expr_with_custom_error_test.v │ │ ├── return_in_lock_test.v │ │ ├── return_map_index_with_or_block_test.v │ │ ├── return_match_expr_of_sumtype_do_not_cast_to_ierror_test.v │ │ ├── return_match_expr_of_sumtype_result_test.v │ │ ├── return_match_expr_with_custom_error_test.v │ │ ├── return_match_expr_with_nest_match_expr_test.v │ │ ├── return_option_call_in_non_option_fn_test.v │ │ ├── return_option_call_test.v │ │ ├── return_option_test.v │ │ ├── return_result_in_or_block_test.v │ │ ├── reusable_mut_multiret_values_test.v │ │ ├── run_v_code_from_stdin_test.v │ │ ├── runes_test.v │ │ ├── scanner_and_and_not_test.v │ │ ├── script_with_no_extension │ │ ├── selector_as_cast_test.v │ │ ├── selector_call_with_reserved_c_name_test.v │ │ ├── selector_generic_fn_test.v │ │ ├── selector_indexexpr_fn_type_assign_test.v │ │ ├── selectorexpt_field_name_test.v │ │ ├── serialisation/ │ │ │ ├── json_serialisation_of_fixed_arrays_test.v │ │ │ └── json_with_struct_having_fields_with_default_values_test.v │ │ ├── shared_int_assign_test.v │ │ ├── shared_int_default_val_test.v │ │ ├── shared_str_inp_test.v │ │ ├── shift_test.v │ │ ├── sizeof_2_test.v │ │ ├── sizeof_test.v │ │ ├── skip_sort_arg_check_test.v │ │ ├── skip_unused/ │ │ │ ├── aggregate_call.run.out │ │ │ ├── aggregate_call.vv │ │ │ ├── arr_prepend.run.out │ │ │ ├── arr_prepend.vv │ │ │ ├── array_index.run.out │ │ │ ├── array_index.vv │ │ │ ├── array_init_from_sumtype.run.out │ │ │ ├── array_init_from_sumtype.vv │ │ │ ├── array_insert.run.out │ │ │ ├── array_insert.vv │ │ │ ├── array_map_filter.run.out │ │ │ ├── array_map_filter.vv │ │ │ ├── array_push.run.out │ │ │ ├── array_push.vv │ │ │ ├── array_push_with_interface_array.run.out │ │ │ ├── array_push_with_interface_array.vv │ │ │ ├── assert_of_sumtype_values_works_test.run.out │ │ │ ├── assert_of_sumtype_values_works_test.vv │ │ │ ├── assert_passes_test.run.out │ │ │ ├── assert_passes_test.vv │ │ │ ├── assert_with_extra_message_works_test.run.out │ │ │ ├── assert_with_extra_message_works_test.vv │ │ │ ├── assert_works_test.run.out │ │ │ ├── assert_works_test.vv │ │ │ ├── auto_str.run.out │ │ │ ├── auto_str.vv │ │ │ ├── auto_string.run.out │ │ │ ├── auto_string.vv │ │ │ ├── call_arguments.run.out │ │ │ ├── call_arguments.vv │ │ │ ├── comptime_for_fields.run.out │ │ │ ├── comptime_for_fields.vv │ │ │ ├── const_used_in_struct_default_init_recursive.run.out │ │ │ ├── const_used_in_struct_default_init_recursive.vv │ │ │ ├── for_c_stmt.run.out │ │ │ ├── for_c_stmt.vv │ │ │ ├── for_linked_list.run.out │ │ │ ├── for_linked_list.vv │ │ │ ├── generic_call_from_json.run.out │ │ │ ├── generic_call_from_json.vv │ │ │ ├── generic_iterator_loop.run.out │ │ │ ├── generic_iterator_loop.vv │ │ │ ├── generics_array_delete_method.run.out │ │ │ ├── generics_array_delete_method.vv │ │ │ ├── generics_as_receiver.run.out │ │ │ ├── generics_as_receiver.vv │ │ │ ├── generics_method.run.out │ │ │ ├── generics_method.vv │ │ │ ├── gg_code.run.out │ │ │ ├── gg_code.vv │ │ │ ├── hw.run.out │ │ │ ├── hw.vv │ │ │ ├── ident_or_block.run.out │ │ │ ├── ident_or_block.vv │ │ │ ├── ierror_str.run.out │ │ │ ├── ierror_str.vv │ │ │ ├── import_json_only.run.out │ │ │ ├── import_json_only.vv │ │ │ ├── indexexpr_result_propagation.run.out │ │ │ ├── indexexpr_result_propagation.vv │ │ │ ├── interface_struct_unused.run.out │ │ │ ├── interface_struct_unused.vv │ │ │ ├── interface_unused.run.out │ │ │ ├── interface_unused.vv │ │ │ ├── json_decode_u32.run.out │ │ │ ├── json_decode_u32.vv │ │ │ ├── method_as_fn_pointer.run.out │ │ │ ├── method_as_fn_pointer.vv │ │ │ ├── nested_generics_method.run.out │ │ │ ├── nested_generics_method.vv │ │ │ ├── option_array_init.run.out │ │ │ ├── option_array_init.vv │ │ │ ├── option_int_println.run.out │ │ │ ├── option_int_println.vv │ │ │ ├── option_ptr_print.run.out │ │ │ ├── option_ptr_print.vv │ │ │ ├── print_interface_smartcast.run.out │ │ │ ├── print_interface_smartcast.vv │ │ │ ├── println_os_executable.run.out │ │ │ ├── println_os_executable.vv │ │ │ ├── selector_option.run.out │ │ │ ├── selector_option.vv │ │ │ ├── shorthands_for_options_and_results_in_main.run.out │ │ │ ├── shorthands_for_options_and_results_in_main.vv │ │ │ ├── simple_array_init.run.out │ │ │ ├── simple_array_init.vv │ │ │ ├── skip_sumtype_unused.run.out │ │ │ ├── skip_sumtype_unused.vv │ │ │ ├── string_array_methods.run.out │ │ │ ├── string_array_methods.vv │ │ │ ├── struct_field_default_expr.run.out │ │ │ ├── struct_field_default_expr.vv │ │ │ ├── struct_field_none.run.out │ │ │ ├── struct_field_none.vv │ │ │ ├── sumtype_type_name.run.out │ │ │ ├── sumtype_type_name.vv │ │ │ ├── thread_waiter.run.out │ │ │ ├── thread_waiter.vv │ │ │ ├── veb_run_at.run.out │ │ │ ├── veb_run_at.vv │ │ │ ├── vweb_run_at.run.out │ │ │ └── vweb_run_at.vv │ │ ├── sql_statement_inside_fn_call_test.v │ │ ├── static_vars_test.v │ │ ├── structs/ │ │ │ ├── anon_struct_alias_type_decl_embed_test.v │ │ │ ├── anon_struct_array_test.v │ │ │ ├── anon_struct_assign_expr_test.v │ │ │ ├── anon_struct_assign_test.v │ │ │ ├── anon_struct_default_value_test.v │ │ │ ├── anon_struct_type_test.v │ │ │ ├── anon_struct_with_default_expr_test.v │ │ │ ├── custom_str_on_struct_with_too_many_fields_test.v │ │ │ ├── default_expr_array_init_test.v │ │ │ ├── differently_named_structs_test.v │ │ │ ├── embed_error_in_returning_result_test.v │ │ │ ├── embed_method_call_test.v │ │ │ ├── embed_struct_field_default_value_test.v │ │ │ ├── embed_struct_name_test.v │ │ │ ├── embed_struct_with_sumtype_field_test.v │ │ │ ├── empty_struct_compare_test.v │ │ │ ├── empty_struct_test.v │ │ │ ├── free_method_test.v │ │ │ ├── missing_config_struct_arg_test.v │ │ │ ├── modules/ │ │ │ │ └── structs_with_noinit/ │ │ │ │ └── shapes.v │ │ │ ├── multiple_embed_struct_init_test.v │ │ │ ├── multiple_embed_struct_with_duplicate_field_init_test.v │ │ │ ├── mut_receiver_returned_as_reference_test.v │ │ │ ├── mut_test.v │ │ │ ├── nested_struct_embed_method_call_test.v │ │ │ ├── nested_struct_embed_selector_test.v │ │ │ ├── operator_overloading_cmp_test.v │ │ │ ├── operator_overloading_on_struct_with_too_many_fields_test.v │ │ │ ├── operator_overloading_type_alias_generic_parent_test.v │ │ │ ├── operator_overloading_with_reference_operands_test.v │ │ │ ├── operator_overloading_with_string_interpolation_test.v │ │ │ ├── short_struct_param_syntax_test.v │ │ │ ├── struct_aligned_test.v │ │ │ ├── struct_allow_both_field_defaults_and_skip_flag_test.v │ │ │ ├── struct_anon_generic_fn_field_test.v │ │ │ ├── struct_array_generic_field_test.v │ │ │ ├── struct_auto_eq_gen_interface_test.v │ │ │ ├── struct_chained_fields_correct_test.v │ │ │ ├── struct_child_field_default_test.v │ │ │ ├── struct_embed_fn_type_test.v │ │ │ ├── struct_embed_is_interface_test.v │ │ │ ├── struct_embed_option_reference_test.v │ │ │ ├── struct_embed_test.v │ │ │ ├── struct_embedding_with_interface_test.v │ │ │ ├── struct_empty_auto_eq_test.v │ │ │ ├── struct_eq_op_only_test.v │ │ │ ├── struct_eq_op_test.v │ │ │ ├── struct_equality_test.v │ │ │ ├── struct_field_array_index_test.v │ │ │ ├── struct_field_default_fn_type_value_init_test.v │ │ │ ├── struct_field_default_union_of_structs_marked_with_noinit_test.v │ │ │ ├── struct_field_default_value_interface_cast_test.v │ │ │ ├── struct_field_default_value_optional_test.v │ │ │ ├── struct_field_default_value_sumtype_cast_test.v │ │ │ ├── struct_field_fixed_array_init_test.v │ │ │ ├── struct_field_fixed_array_init_with_default_value_test.v │ │ │ ├── struct_field_fn_call_test.v │ │ │ ├── struct_field_init_with_fixed_array_init_test.v │ │ │ ├── struct_field_init_with_fixed_array_opt_test.v │ │ │ ├── struct_field_init_with_generic_anon_fn_test.v │ │ │ ├── struct_field_init_with_generic_fn_test.v │ │ │ ├── struct_field_name_using_c_keyword_test.v │ │ │ ├── struct_field_name_using_keyword_test.v │ │ │ ├── struct_field_named_as_c_keyword_test.v │ │ │ ├── struct_field_option_type_with_default_value_init_test.v │ │ │ ├── struct_field_shared_test.v │ │ │ ├── struct_fields_required_test.v │ │ │ ├── struct_fields_storing_functions_test.v │ │ │ ├── struct_generic_init_test.v │ │ │ ├── struct_generic_sizeof_test.v │ │ │ ├── struct_heap_large_fixed_array_test.v │ │ │ ├── struct_heap_test.v │ │ │ ├── struct_ierror_test.v │ │ │ ├── struct_init_alias_array_fixed_test.v │ │ │ ├── struct_init_and_assign_test.v │ │ │ ├── struct_init_inside_ternary_with_option_field_test.v │ │ │ ├── struct_init_on_for_expr_test.v │ │ │ ├── struct_init_passing_test.v │ │ │ ├── struct_init_update_test.v │ │ │ ├── struct_init_update_with_generics_test.v │ │ │ ├── struct_init_update_with_mutable_receiver_test.v │ │ │ ├── struct_init_with_chan_field_test.v │ │ │ ├── struct_init_with_complex_fields_test.v │ │ │ ├── struct_init_with_embed_update_test.v │ │ │ ├── struct_init_with_fixed_array_field_test.v │ │ │ ├── struct_init_with_interface_field_test.v │ │ │ ├── struct_init_with_interface_pointer_and_embed_test.v │ │ │ ├── struct_init_with_multi_nested_embed_update_test.v │ │ │ ├── struct_init_with_multi_option_fn_type_test.v │ │ │ ├── struct_init_with_update_test.v │ │ │ ├── struct_local_test.v │ │ │ ├── struct_map_method_test.v │ │ │ ├── struct_multi_embed_method_call_test.v │ │ │ ├── struct_of_time_init_with_update_test.v │ │ │ ├── struct_option_field_comparison_test.v │ │ │ ├── struct_option_field_zero_test.v │ │ │ ├── struct_scoped_test.v │ │ │ ├── struct_selector_or_block_test.v │ │ │ ├── struct_shared_field_init_test.v │ │ │ ├── struct_shared_field_with_default_init_test.v │ │ │ ├── struct_test.v │ │ │ ├── struct_transmute_test.v │ │ │ ├── struct_with_alias_embed_test.v │ │ │ ├── struct_with_reference_alias_field_test.v │ │ │ ├── structs_with_voidptr_fields_can_be_printed_test.v │ │ │ └── working_with_an_empty_struct_test.v │ │ ├── sumtype_array_push_array_variant_test.v │ │ ├── sumtype_init_by_name_test.v │ │ ├── sumtypes/ │ │ │ ├── aggregate_is_nodetype_test.v │ │ │ ├── aggregate_with_struct_embed_test.v │ │ │ ├── alias_sumtype_smartcast_test.v │ │ │ ├── init_multiple_branches_test.v │ │ │ ├── mut_receiver_of_sumtype_test.v │ │ │ ├── passing_sumtype_parameter_in_sumtype_matching_results_test.v │ │ │ ├── sumtype_arg_mutable_test.v │ │ │ ├── sumtype_array_methods_test.v │ │ │ ├── sumtype_array_to_vararg_struct_fn_test.v │ │ │ ├── sumtype_as_cast_1_test.v │ │ │ ├── sumtype_as_cast_2_test.v │ │ │ ├── sumtype_assign_test.v │ │ │ ├── sumtype_calls_test.v │ │ │ ├── sumtype_cast_alias_test.v │ │ │ ├── sumtype_cast_from_voidptr_test.v │ │ │ ├── sumtype_common_fields_test.v │ │ │ ├── sumtype_empty_struct_test.v │ │ │ ├── sumtype_equality_test.v │ │ │ ├── sumtype_generic_checking_test.v │ │ │ ├── sumtype_inherited_var_test.v │ │ │ ├── sumtype_init_literal_test.v │ │ │ ├── sumtype_init_test.v │ │ │ ├── sumtype_literal_test.v │ │ │ ├── sumtype_map_set_test.v │ │ │ ├── sumtype_mutable_test.v │ │ │ ├── sumtype_on_match_test.v │ │ │ ├── sumtype_ptr_arg_test.v │ │ │ ├── sumtype_ptr_ptr_test.v │ │ │ ├── sumtype_str_for_subtypes_with_str_test.v │ │ │ ├── sumtype_str_test.v │ │ │ ├── sumtype_test.v │ │ │ ├── sumtype_type_coercion_test.v │ │ │ ├── sumtype_value_pointer_test.v │ │ │ ├── sumtype_with_alias_fntype_fn_call_test.v │ │ │ ├── sumtype_with_alias_fntype_test.v │ │ │ ├── sumtype_with_embedded_struct_of_option_field_test.v │ │ │ ├── sumtype_with_fntype_test.v │ │ │ ├── sumtype_with_reference_test.v │ │ │ ├── sumtype_with_struct_fn_field_call_test.v │ │ │ └── voidptr_sumtype_test.v │ │ ├── supports__likely__test.v │ │ ├── tcc_arm64_atomic_fence_test.v │ │ ├── templates/ │ │ │ └── map_index.txt │ │ ├── test_global_init_test.v │ │ ├── testcase_leak.vv │ │ ├── testdata/ │ │ │ ├── builtin_overflow/ │ │ │ │ ├── gen_overflow_tests.vsh │ │ │ │ ├── panic_on_i16_add_assign_overflow.out │ │ │ │ ├── panic_on_i16_add_assign_overflow.vv │ │ │ │ ├── panic_on_i16_add_overflow.out │ │ │ │ ├── panic_on_i16_add_overflow.vv │ │ │ │ ├── panic_on_i16_dec_overflow.out │ │ │ │ ├── panic_on_i16_dec_overflow.vv │ │ │ │ ├── panic_on_i16_inc_overflow.out │ │ │ │ ├── panic_on_i16_inc_overflow.vv │ │ │ │ ├── panic_on_i16_mul_assign_overflow.out │ │ │ │ ├── panic_on_i16_mul_assign_overflow.vv │ │ │ │ ├── panic_on_i16_mul_overflow.out │ │ │ │ ├── panic_on_i16_mul_overflow.vv │ │ │ │ ├── panic_on_i16_sub_assign_overflow.out │ │ │ │ ├── panic_on_i16_sub_assign_overflow.vv │ │ │ │ ├── panic_on_i16_sub_overflow.out │ │ │ │ ├── panic_on_i16_sub_overflow.vv │ │ │ │ ├── panic_on_i32_add_assign_overflow.out │ │ │ │ ├── panic_on_i32_add_assign_overflow.vv │ │ │ │ ├── panic_on_i32_add_overflow.out │ │ │ │ ├── panic_on_i32_add_overflow.vv │ │ │ │ ├── panic_on_i32_dec_overflow.out │ │ │ │ ├── panic_on_i32_dec_overflow.vv │ │ │ │ ├── panic_on_i32_inc_overflow.out │ │ │ │ ├── panic_on_i32_inc_overflow.vv │ │ │ │ ├── panic_on_i32_mul_assign_overflow.out │ │ │ │ ├── panic_on_i32_mul_assign_overflow.vv │ │ │ │ ├── panic_on_i32_mul_overflow.out │ │ │ │ ├── panic_on_i32_mul_overflow.vv │ │ │ │ ├── panic_on_i32_sub_assign_overflow.out │ │ │ │ ├── panic_on_i32_sub_assign_overflow.vv │ │ │ │ ├── panic_on_i32_sub_overflow.out │ │ │ │ ├── panic_on_i32_sub_overflow.vv │ │ │ │ ├── panic_on_i64_add_assign_overflow.out │ │ │ │ ├── panic_on_i64_add_assign_overflow.vv │ │ │ │ ├── panic_on_i64_add_overflow.out │ │ │ │ ├── panic_on_i64_add_overflow.vv │ │ │ │ ├── panic_on_i64_dec_overflow.out │ │ │ │ ├── panic_on_i64_dec_overflow.vv │ │ │ │ ├── panic_on_i64_inc_overflow.out │ │ │ │ ├── panic_on_i64_inc_overflow.vv │ │ │ │ ├── panic_on_i64_mul_assign_overflow.out │ │ │ │ ├── panic_on_i64_mul_assign_overflow.vv │ │ │ │ ├── panic_on_i64_mul_overflow.out │ │ │ │ ├── panic_on_i64_mul_overflow.vv │ │ │ │ ├── panic_on_i64_sub_assign_overflow.out │ │ │ │ ├── panic_on_i64_sub_assign_overflow.vv │ │ │ │ ├── panic_on_i64_sub_overflow.out │ │ │ │ ├── panic_on_i64_sub_overflow.vv │ │ │ │ ├── panic_on_i8_add_assign_overflow.out │ │ │ │ ├── panic_on_i8_add_assign_overflow.vv │ │ │ │ ├── panic_on_i8_add_overflow.out │ │ │ │ ├── panic_on_i8_add_overflow.vv │ │ │ │ ├── panic_on_i8_dec_overflow.out │ │ │ │ ├── panic_on_i8_dec_overflow.vv │ │ │ │ ├── panic_on_i8_inc_overflow.out │ │ │ │ ├── panic_on_i8_inc_overflow.vv │ │ │ │ ├── panic_on_i8_mul_assign_overflow.out │ │ │ │ ├── panic_on_i8_mul_assign_overflow.vv │ │ │ │ ├── panic_on_i8_mul_overflow.out │ │ │ │ ├── panic_on_i8_mul_overflow.vv │ │ │ │ ├── panic_on_i8_sub_assign_overflow.out │ │ │ │ ├── panic_on_i8_sub_assign_overflow.vv │ │ │ │ ├── panic_on_i8_sub_overflow.out │ │ │ │ ├── panic_on_i8_sub_overflow.vv │ │ │ │ ├── panic_on_u16_add_assign_overflow.out │ │ │ │ ├── panic_on_u16_add_assign_overflow.vv │ │ │ │ ├── panic_on_u16_add_overflow.out │ │ │ │ ├── panic_on_u16_add_overflow.vv │ │ │ │ ├── panic_on_u16_dec_overflow.out │ │ │ │ ├── panic_on_u16_dec_overflow.vv │ │ │ │ ├── panic_on_u16_inc_overflow.out │ │ │ │ ├── panic_on_u16_inc_overflow.vv │ │ │ │ ├── panic_on_u16_mul_assign_overflow.out │ │ │ │ ├── panic_on_u16_mul_assign_overflow.vv │ │ │ │ ├── panic_on_u16_mul_overflow.out │ │ │ │ ├── panic_on_u16_mul_overflow.vv │ │ │ │ ├── panic_on_u16_sub_assign_overflow.out │ │ │ │ ├── panic_on_u16_sub_assign_overflow.vv │ │ │ │ ├── panic_on_u16_sub_overflow.out │ │ │ │ ├── panic_on_u16_sub_overflow.vv │ │ │ │ ├── panic_on_u32_add_assign_overflow.out │ │ │ │ ├── panic_on_u32_add_assign_overflow.vv │ │ │ │ ├── panic_on_u32_add_overflow.out │ │ │ │ ├── panic_on_u32_add_overflow.vv │ │ │ │ ├── panic_on_u32_dec_overflow.out │ │ │ │ ├── panic_on_u32_dec_overflow.vv │ │ │ │ ├── panic_on_u32_inc_overflow.out │ │ │ │ ├── panic_on_u32_inc_overflow.vv │ │ │ │ ├── panic_on_u32_mul_assign_overflow.out │ │ │ │ ├── panic_on_u32_mul_assign_overflow.vv │ │ │ │ ├── panic_on_u32_mul_overflow.out │ │ │ │ ├── panic_on_u32_mul_overflow.vv │ │ │ │ ├── panic_on_u32_sub_assign_overflow.out │ │ │ │ ├── panic_on_u32_sub_assign_overflow.vv │ │ │ │ ├── panic_on_u32_sub_overflow.out │ │ │ │ ├── panic_on_u32_sub_overflow.vv │ │ │ │ ├── panic_on_u64_add_assign_overflow.out │ │ │ │ ├── panic_on_u64_add_assign_overflow.vv │ │ │ │ ├── panic_on_u64_add_overflow.out │ │ │ │ ├── panic_on_u64_add_overflow.vv │ │ │ │ ├── panic_on_u64_dec_overflow.out │ │ │ │ ├── panic_on_u64_dec_overflow.vv │ │ │ │ ├── panic_on_u64_inc_overflow.out │ │ │ │ ├── panic_on_u64_inc_overflow.vv │ │ │ │ ├── panic_on_u64_mul_assign_overflow.out │ │ │ │ ├── panic_on_u64_mul_assign_overflow.vv │ │ │ │ ├── panic_on_u64_mul_overflow.out │ │ │ │ ├── panic_on_u64_mul_overflow.vv │ │ │ │ ├── panic_on_u64_sub_assign_overflow.out │ │ │ │ ├── panic_on_u64_sub_assign_overflow.vv │ │ │ │ ├── panic_on_u64_sub_overflow.out │ │ │ │ ├── panic_on_u64_sub_overflow.vv │ │ │ │ ├── panic_on_u8_add_assign_overflow.out │ │ │ │ ├── panic_on_u8_add_assign_overflow.vv │ │ │ │ ├── panic_on_u8_add_overflow.out │ │ │ │ ├── panic_on_u8_add_overflow.vv │ │ │ │ ├── panic_on_u8_dec_overflow.out │ │ │ │ ├── panic_on_u8_dec_overflow.vv │ │ │ │ ├── panic_on_u8_inc_overflow.out │ │ │ │ ├── panic_on_u8_inc_overflow.vv │ │ │ │ ├── panic_on_u8_mul_assign_overflow.out │ │ │ │ ├── panic_on_u8_mul_assign_overflow.vv │ │ │ │ ├── panic_on_u8_mul_overflow.out │ │ │ │ ├── panic_on_u8_mul_overflow.vv │ │ │ │ ├── panic_on_u8_sub_assign_overflow.out │ │ │ │ ├── panic_on_u8_sub_assign_overflow.vv │ │ │ │ ├── panic_on_u8_sub_overflow.out │ │ │ │ └── panic_on_u8_sub_overflow.vv │ │ │ ├── enum_in_builtin/ │ │ │ │ ├── builtin.v │ │ │ │ ├── c.v │ │ │ │ └── main.v │ │ │ ├── module_named_cache/ │ │ │ │ ├── src/ │ │ │ │ │ └── main.v │ │ │ │ └── v.mod │ │ │ ├── modules_in_src/ │ │ │ │ ├── modules/ │ │ │ │ │ └── somemoduletwo/ │ │ │ │ │ └── somemoduletwo.v │ │ │ │ ├── src/ │ │ │ │ │ ├── main.v │ │ │ │ │ └── modules/ │ │ │ │ │ └── somemodule/ │ │ │ │ │ └── somemodule.v │ │ │ │ └── v.mod │ │ │ ├── sizeof_used_in_assert_test.v │ │ │ ├── test_array_bound.v │ │ │ ├── tests_returning_options_failing_test.v │ │ │ ├── trace_calls/ │ │ │ │ ├── simple.vv │ │ │ │ ├── simple.vv.must_match │ │ │ │ ├── single_println.vv │ │ │ │ ├── single_println.vv.must_match │ │ │ │ ├── with_modules.vv │ │ │ │ └── with_modules.vv.must_match │ │ │ └── usecache_and_mods/ │ │ │ ├── aaa/ │ │ │ │ ├── aa1.v │ │ │ │ └── aaa.v │ │ │ ├── bbb/ │ │ │ │ ├── bb1.v │ │ │ │ └── bbb.v │ │ │ ├── ccc/ │ │ │ │ ├── cc1.v │ │ │ │ ├── cc2.v │ │ │ │ └── ccc.v │ │ │ ├── ddd/ │ │ │ │ ├── dd1.v │ │ │ │ └── ddd.v │ │ │ ├── main.v │ │ │ ├── v.mod │ │ │ ├── xx/ │ │ │ │ ├── x1.v │ │ │ │ └── xx.v │ │ │ ├── yy/ │ │ │ │ ├── y1.v │ │ │ │ └── yy.v │ │ │ └── zz/ │ │ │ ├── z1.v │ │ │ └── zz.v │ │ ├── trace_calls_test.v │ │ ├── translated_test.v │ │ ├── type_idx_test.v │ │ ├── type_name_in_if_test.v │ │ ├── type_name_test.v │ │ ├── type_promotion_test.v │ │ ├── type_voidptr_test.v │ │ ├── typeof_aggregate_test.v │ │ ├── typeof_indirections_test.v │ │ ├── typeof_name_test.v │ │ ├── typeof_simple_types_test.v │ │ ├── typeof_test.v │ │ ├── typeof_type_test.v │ │ ├── typeof_unaliased_typ_test.v │ │ ├── u8_free_test.v │ │ ├── unicode_escape_test.v │ │ ├── unions/ │ │ │ ├── nested_union_test.v │ │ │ └── union_implementing_interface_test.v │ │ ├── unreachable_code_paths_test.v │ │ ├── unsigned_right_shift_test.v │ │ ├── use_alias_from_another_module_in_struct_field_test.v │ │ ├── va_arg_test.v │ │ ├── var_name_using_reserved_test.v │ │ ├── var_name_using_type_test.v │ │ ├── var_type_is_checking2_test.v │ │ ├── var_type_is_checking_test.v │ │ ├── vargs_empty_param_test.v │ │ ├── vls/ │ │ │ ├── autocomplete_module_test.v │ │ │ ├── goto_def_test.v │ │ │ ├── goto_def_test_data.vv │ │ │ ├── multifile_gotodef/ │ │ │ │ ├── main.v │ │ │ │ └── types.v │ │ │ ├── multifile_gotodef_test.v │ │ │ ├── sample_mod1/ │ │ │ │ └── sample.v │ │ │ ├── sample_mod2/ │ │ │ │ └── sample.v │ │ │ ├── sample_text.vv │ │ │ ├── struct_check_test.v │ │ │ └── struct_text.vv │ │ ├── vmod_parser_test.v │ │ ├── websocket_logger_interface_should_compile_test.v │ │ └── windows_system_info_test.v │ ├── token/ │ │ ├── README.md │ │ ├── keywords_matcher_trie.v │ │ ├── keywords_matcher_trie_test.v │ │ ├── pos.v │ │ ├── token.v │ │ └── token_test.v │ ├── trace_calls/ │ │ ├── tracing_calls.c.v │ │ ├── tracing_calls_nix.c.v │ │ └── tracing_calls_windows.c.v │ ├── transformer/ │ │ ├── array.v │ │ ├── index_state.v │ │ ├── tests/ │ │ │ └── const_infix_expr_test.v │ │ └── transformer.v │ ├── type_resolver/ │ │ ├── comptime_resolver.v │ │ ├── generic_resolver.v │ │ └── type_resolver.v │ ├── util/ │ │ ├── check_dflags_test.v │ │ ├── d_value.v │ │ ├── diff/ │ │ │ ├── diff.v │ │ │ └── diff_test.v │ │ ├── env_value.v │ │ ├── errors.v │ │ ├── module.v │ │ ├── quote.v │ │ ├── recompilation/ │ │ │ └── recompilation.v │ │ ├── scanning.v │ │ ├── suggestions.v │ │ ├── surrounder.v │ │ ├── surrounder_test.v │ │ ├── timers.v │ │ ├── util.c.v │ │ ├── util.js.v │ │ ├── util.v │ │ ├── version/ │ │ │ ├── version.c.v │ │ │ ├── version.v │ │ │ └── version_test.v │ │ ├── vflags/ │ │ │ ├── vflags.v │ │ │ └── vflags_test.v │ │ ├── vmod_value.v │ │ └── vtest/ │ │ └── vtest.v │ ├── vcache/ │ │ ├── vcache.v │ │ └── vcache_test.v │ └── vmod/ │ ├── encoder.v │ ├── encoder_test.v │ ├── parser.v │ ├── parser_test.v │ └── vmod.v ├── v2/ │ ├── README.md │ ├── abi/ │ │ ├── abi.v │ │ └── abi_test.v │ ├── ast/ │ │ ├── ast.v │ │ ├── desugar.v │ │ └── flatbackup │ ├── ast_dump/ │ │ └── ast_dump.v │ ├── builder/ │ │ ├── builder.v │ │ ├── cache_headers.v │ │ ├── gen_arm64_parallel.v │ │ ├── gen_cleanc_parallel.v │ │ ├── parse.v │ │ ├── parse_d_parallel.v │ │ ├── ssa_build_parallel.v │ │ ├── transform_parallel.v │ │ ├── type_check.v │ │ ├── type_check_d_parallel.v │ │ ├── type_check_parallel.v │ │ ├── util.v │ │ └── util_nix.c.v │ ├── errors/ │ │ ├── details.v │ │ ├── error.v │ │ └── util.v │ ├── eval/ │ │ ├── eval.v │ │ └── eval_test.v │ ├── gen/ │ │ ├── arm64/ │ │ │ ├── arm64.v │ │ │ ├── asm.v │ │ │ ├── linker.v │ │ │ ├── macho.v │ │ │ └── tests/ │ │ │ ├── run_tests.v │ │ │ └── string_concat.v │ │ ├── c/ │ │ │ ├── c.v │ │ │ └── tests/ │ │ │ └── basictest.v │ │ ├── cleanc/ │ │ │ ├── array.v │ │ │ ├── assign.v │ │ │ ├── cheaders.v │ │ │ ├── cleanc.v │ │ │ ├── cleanc_test.v │ │ │ ├── consts_and_globals.v │ │ │ ├── expr.v │ │ │ ├── fn.v │ │ │ ├── for.v │ │ │ ├── if.v │ │ │ ├── interface.v │ │ │ ├── soa.v │ │ │ ├── stmt.v │ │ │ ├── str_intp.v │ │ │ ├── struct.v │ │ │ ├── tests/ │ │ │ │ ├── array_float_init.v │ │ │ │ ├── assoc_expr.v │ │ │ │ ├── bitwise_shift_precedence.v │ │ │ │ ├── bitwise_shift_precedence_fixed_array_selector.v │ │ │ │ ├── flag_enum.v │ │ │ │ ├── interface_is.v │ │ │ │ ├── interface_is_concrete_method_call.v │ │ │ │ ├── map_empty_init.v │ │ │ │ ├── map_enum_shorthand_keys.v │ │ │ │ ├── map_index_read.v │ │ │ │ ├── run_tests.v │ │ │ │ └── soa_struct.v │ │ │ └── types.v │ │ ├── v/ │ │ │ └── gen.v │ │ └── x64/ │ │ ├── asm.v │ │ ├── elf.v │ │ └── x64.v │ ├── insel/ │ │ └── insel.v │ ├── markused/ │ │ ├── markused.v │ │ └── markused_test.v │ ├── mir/ │ │ └── mir.v │ ├── parser/ │ │ ├── parser.v │ │ └── type.v │ ├── pref/ │ │ ├── module.v │ │ ├── pref.v │ │ └── source_filter.v │ ├── profiler/ │ │ ├── alloc.v │ │ ├── context.v │ │ ├── ipc.v │ │ ├── profiler_alloc.v │ │ └── runtime.v │ ├── scanner/ │ │ └── scanner.v │ ├── ssa/ │ │ ├── block.v │ │ ├── builder.v │ │ ├── function.v │ │ ├── helpers.v │ │ ├── instr.v │ │ ├── module.v │ │ ├── optimize/ │ │ │ ├── blocks.v │ │ │ ├── cfg.v │ │ │ ├── dce.v │ │ │ ├── dominators.v │ │ │ ├── fold.v │ │ │ ├── mem2reg.v │ │ │ ├── optimize.v │ │ │ ├── phi.v │ │ │ ├── phi_test.v │ │ │ ├── verify.v │ │ │ └── verify_test.v │ │ ├── types.v │ │ └── value.v │ ├── tests/ │ │ ├── advance.v_ │ │ ├── generic_a.v_ │ │ ├── generic_fn.v_ │ │ ├── if_a.v │ │ ├── selector_expr.v │ │ ├── string_interpolation.v │ │ ├── syntax.v_ │ │ ├── syntax_ambiguities.v_ │ │ ├── syntax_generics.v_ │ │ └── typeof.v_ │ ├── token/ │ │ ├── position.v │ │ ├── token.v │ │ └── util.v │ ├── transformer/ │ │ ├── expr.v │ │ ├── fn.v │ │ ├── for.v │ │ ├── if.v │ │ ├── interface.v │ │ ├── live.v │ │ ├── struct.v │ │ ├── transformer.v │ │ ├── transformer_test.v │ │ ├── transformer_v2_darwin_test.v │ │ ├── type_propagation.v │ │ └── types.v │ ├── types/ │ │ ├── checker.v │ │ ├── checker_test.v │ │ ├── module.v │ │ ├── object.v │ │ ├── scope.v │ │ ├── types.v │ │ └── universe.v │ └── util/ │ └── worker_pool_d_parallel.v ├── veb/ │ ├── README.md │ ├── assets/ │ │ ├── README.md │ │ ├── assets.v │ │ └── assets_test.v │ ├── auth/ │ │ ├── README.md │ │ ├── auth.v │ │ └── request.v │ ├── chunked_request_body_test.v │ ├── consts.v │ ├── context.v │ ├── controller.v │ ├── csrf/ │ │ ├── README.md │ │ ├── csrf.v │ │ └── csrf_test.v │ ├── escape_html_strings_in_templates.v │ ├── middleware.v │ ├── oauth/ │ │ └── oauth.v │ ├── parse.v │ ├── request_id/ │ │ ├── README.md │ │ ├── request_id.v │ │ └── request_id_test.v │ ├── route_test.v │ ├── sendfile_freebsd.c.v │ ├── sendfile_linux.c.v │ ├── sse/ │ │ ├── README.md │ │ ├── sse.v │ │ └── sse_test.v │ ├── static_handler.v │ ├── tests/ │ │ ├── controller_test.v │ │ ├── cors_2_test.v │ │ ├── cors_regression_test.v │ │ ├── cors_test.v │ │ ├── handle_split_requests_in_chrome_test.v │ │ ├── invalid_return_type_test.v │ │ ├── large_payload_test.v │ │ ├── memory_leak_test.v │ │ ├── memory_leak_test_server.v │ │ ├── middleware_test.v │ │ ├── persistent_connection_test.v │ │ ├── static_compression_test.v │ │ ├── static_handler_test.v │ │ ├── testdata/ │ │ │ ├── about/ │ │ │ │ └── index.html.md │ │ │ ├── about.html.md │ │ │ ├── about.md │ │ │ ├── page.html │ │ │ ├── page.html.md │ │ │ ├── root.txt │ │ │ ├── sub.folder/ │ │ │ │ └── sub_folder/ │ │ │ │ ├── index.htm │ │ │ │ └── sub.txt │ │ │ ├── sub_folder/ │ │ │ │ ├── index.htm │ │ │ │ ├── index.html.md │ │ │ │ └── sub.txt │ │ │ ├── test.md │ │ │ ├── unknown_mime.what │ │ │ └── upper_case.TXT │ │ ├── veb_aliased_app_and_context_test.v │ │ ├── veb_app_test.v │ │ ├── veb_should_listen_on_both_ipv4_and_ipv6_by_default_test.v │ │ ├── veb_test.v │ │ └── veb_test_server.v │ ├── tr.v │ ├── tr_test.v │ ├── translations/ │ │ ├── en.tr │ │ └── pt-br.tr │ ├── veb.v │ ├── veb_d_new_veb.v │ ├── veb_livereload.v │ └── veb_picoev.v ├── vweb/ │ ├── README.md │ ├── assets/ │ │ ├── assets.v │ │ └── assets_test.v │ ├── csrf/ │ │ ├── README.md │ │ ├── csrf.v │ │ └── csrf_test.v │ ├── parse.v │ ├── route_test.v │ ├── sse/ │ │ └── sse.v │ ├── tests/ │ │ ├── controller_duplicate_server.v │ │ ├── controller_test.v │ │ ├── controller_test_server.v │ │ ├── dynamic_template_manager_test_server/ │ │ │ ├── dynamic_template_manager_test_server.v │ │ │ ├── static/ │ │ │ │ └── index.css │ │ │ ├── templates/ │ │ │ │ ├── comment.html │ │ │ │ └── index.html │ │ │ └── vcache_dtm/ │ │ │ └── .gitkeep │ │ ├── middleware_test.v │ │ ├── middleware_test_server.v │ │ ├── vweb_should_listen_on_both_ipv4_and_ipv6_by_default_test.v │ │ ├── vweb_test.v │ │ └── vweb_test_server/ │ │ └── server.v │ ├── vweb.v │ ├── vweb_app_test.v │ ├── vweb_global_map_test.v │ └── vweb_livereload.v ├── wasm/ │ ├── README.md │ ├── constant.v │ ├── encoding.v │ ├── functions.v │ ├── instructions.v │ ├── module.v │ └── tests/ │ ├── arith_test.v │ ├── block_test.v │ ├── call_test.v │ ├── common.v │ ├── debug_test.v │ ├── patch_test.v │ └── var_test.v └── x/ ├── README.md ├── atomics/ │ ├── README.md │ ├── atomics.amd64.v │ ├── atomics.i386.v │ ├── benchmarks/ │ │ ├── README.md │ │ └── atomic_benchmark.v │ ├── examples/ │ │ ├── basic.v │ │ ├── counter.v │ │ └── spinlock.v │ ├── i32_test.v │ ├── i64_test.v │ ├── panic_unaligned.v │ ├── u32_test.v │ └── u64_test.v ├── benchmark/ │ ├── benchmark.v │ └── benchmark_test.v ├── crypto/ │ ├── ascon/ │ │ ├── README.md │ │ ├── aead128.v │ │ ├── aead128_test.v │ │ ├── ascon.v │ │ ├── ascon_test.v │ │ ├── bench/ │ │ │ ├── aead.v │ │ │ ├── hashxof.v │ │ │ └── sum.v │ │ ├── cxof_test.v │ │ ├── digest.v │ │ ├── examples/ │ │ │ ├── use_of_cxof.v │ │ │ ├── use_of_hash26.v │ │ │ └── use_of_xof.v │ │ ├── hash.v │ │ ├── hash_test.v │ │ ├── util.v │ │ ├── xof.v │ │ └── xof_test.v │ ├── chacha20/ │ │ ├── README.md │ │ ├── bench/ │ │ │ └── bench.v │ │ ├── chacha.v │ │ ├── chacha_64bitctr_test.v │ │ ├── chacha_test.v │ │ ├── stream.v │ │ ├── stream_test.v │ │ ├── xchacha.v │ │ └── xchacha_test.v │ ├── chacha20poly1305/ │ │ ├── README.md │ │ ├── bench/ │ │ │ └── bench.v │ │ ├── chacha20poly1305.v │ │ ├── chacha20poly1305_test.v │ │ ├── psiv.v │ │ ├── psiv_test.v │ │ ├── usage_test.v │ │ └── xchacha20poly1305_test.v │ ├── curve25519/ │ │ ├── README.md │ │ ├── curve25519.v │ │ ├── curve25519_test.v │ │ ├── examples/ │ │ │ ├── shared_sec_with_custom_derivator.v │ │ │ └── shared_sec_with_raw_bytes.v │ │ └── usage_test.v │ ├── mldsa/ │ │ ├── LICENSE │ │ ├── README.md │ │ ├── encoding.v │ │ ├── field.v │ │ ├── mldsa.v │ │ ├── mldsa_test.v │ │ ├── ntt.v │ │ ├── params.v │ │ ├── prehash.v │ │ ├── sampling.v │ │ └── testdata/ │ │ ├── gen.go │ │ ├── gen.vsh │ │ └── vectors.json │ ├── poly1305/ │ │ ├── README.md │ │ ├── custom.v │ │ ├── poly1305.v │ │ ├── poly1305_test.v │ │ └── usage_test.v │ ├── slhdsa/ │ │ ├── README.md │ │ ├── base.v │ │ ├── base_test.v │ │ ├── const.c.v │ │ ├── examples/ │ │ │ └── example0.v │ │ ├── install-latest-ssl.md │ │ ├── slhdsa.c.v │ │ ├── slhdsa.v │ │ ├── slhdsa_siggen_test.v │ │ ├── slhdsa_sigver_test.v │ │ └── usage_test.v │ └── sm4/ │ ├── README.md │ ├── sm4.v │ └── sm4_test.v ├── encoding/ │ └── asn1/ │ ├── DOCS.md │ ├── README.md │ ├── any.v │ ├── base128.v │ ├── bench/ │ │ ├── README.md │ │ ├── bench.go │ │ └── bench.v │ ├── bitstring.v │ ├── bitstring_test.v │ ├── boolean.v │ ├── boolean_test.v │ ├── choices.v │ ├── common.v │ ├── core.v │ ├── core_test.v │ ├── element.v │ ├── element_decode.v │ ├── element_decode_test.v │ ├── element_encode.v │ ├── element_encode_test.v │ ├── element_test.v │ ├── enumerated.v │ ├── examples/ │ │ ├── README.md │ │ ├── examples0.v │ │ ├── examples1.v │ │ ├── examples2.v │ │ └── examples3.v │ ├── field_options.v │ ├── field_options_test.v │ ├── generalstring.v │ ├── ia5string.v │ ├── ia5string_test.v │ ├── integer.v │ ├── integer_test.v │ ├── length.v │ ├── length_test.v │ ├── null.v │ ├── numericstring.v │ ├── numericstring_test.v │ ├── octetstring.v │ ├── octetstring_test.v │ ├── oid.v │ ├── oid_test.v │ ├── optional.v │ ├── other_element.v │ ├── parser.v │ ├── printablestring.v │ ├── printablestring_test.v │ ├── public_api_test.v │ ├── sequence.v │ ├── sequence_test.v │ ├── set.v │ ├── set_test.v │ ├── tagged_test.v │ ├── time.v │ ├── time_test.v │ ├── utf8string.v │ ├── utf8string_test.v │ ├── util.v │ ├── util_test.v │ ├── visiblestring.v │ └── visiblestring_test.v ├── json2/ │ ├── README.md │ ├── attr_utils.v │ ├── check.v │ ├── constants.v │ ├── custom.v │ ├── decode.v │ ├── decode_sumtype.v │ ├── decoder2/ │ │ └── stub.v │ ├── decoder_deprecated.v │ ├── encode.v │ ├── encoder.v │ ├── json2.v │ ├── scanner.v │ ├── scanner_test.v │ ├── strict/ │ │ ├── strict.v │ │ ├── strict_test.v │ │ └── strict_test_todo.vv │ ├── tests/ │ │ ├── any_test.v │ │ ├── attributes_test.v │ │ ├── autofree_json_test.v │ │ ├── bench.v │ │ ├── checker_test.v │ │ ├── decode_and_encode_struct_any_test.v │ │ ├── decode_any_alias_test.v │ │ ├── decode_array_array_test.v │ │ ├── decode_array_test.v │ │ ├── decode_budget_number_test.v │ │ ├── decode_custom_test.v │ │ ├── decode_enum_test.v │ │ ├── decode_escaped_string_test.v │ │ ├── decode_fixed_array_test.v │ │ ├── decode_map_any_regression_test.v │ │ ├── decode_map_of_map_test.v │ │ ├── decode_map_test.v │ │ ├── decode_nested_array_test.v │ │ ├── decode_nested_object_same_kay_test.v │ │ ├── decode_number_and_boolean_test.v │ │ ├── decode_object_test.v │ │ ├── decode_option_field_test.v │ │ ├── decode_option_test.v │ │ ├── decode_string_test.v │ │ ├── decode_struct_test.v │ │ ├── decode_struct_todo_test.vv │ │ ├── decoder_test.v │ │ ├── encode_anon_struct_test.v │ │ ├── encode_embedded_structs_test.v │ │ ├── encode_option_test.v │ │ ├── encode_struct_skippable_fields_test.v │ │ ├── encode_struct_test.v │ │ ├── encode_struct_todo_test.vv │ │ ├── encode_test.v │ │ ├── encoder_test.v │ │ ├── integer_primitives_test.v │ │ ├── json2_test.v │ │ ├── json2_tests/ │ │ │ ├── decode_and_encode_struct_any_test.v │ │ │ ├── decode_map_test.v │ │ │ ├── decode_struct_test.v │ │ │ ├── decoder_test.v │ │ │ ├── encoder_test.v │ │ │ ├── json2_test.v │ │ │ └── json_module_compatibility_test/ │ │ │ ├── json_decode_todo_test.v │ │ │ └── json_test.v │ │ ├── json_module_compatibility_test/ │ │ │ ├── json_decode_todo_test.vv │ │ │ ├── json_decode_with_encode_arg_test.v │ │ │ ├── json_decode_with_generic_todo_test.vv │ │ │ ├── json_decode_with_option_arg_test.v │ │ │ ├── json_decode_with_sumtype_todo_test.vv │ │ │ ├── json_test.v │ │ │ └── json_todo_test.vv │ │ ├── json_optional_both_type_field_test.v │ │ ├── json_sumtype_test.v │ │ ├── json_sumtype_test_todo.vv │ │ └── old_json_compatibility/ │ │ └── json_decode_struct_default_test.v │ └── types.v ├── sessions/ │ ├── README.md │ ├── db_store.v │ ├── memory_store.v │ ├── sessions.v │ ├── store.v │ ├── tests/ │ │ ├── db_store_test.v │ │ ├── memory_store_test.v │ │ ├── session_app_test.v │ │ └── session_test.v │ └── vweb2_middleware/ │ └── vweb2_middleware.v ├── templating/ │ └── dtm/ │ ├── README.md │ ├── dynamic_template_manager.v │ ├── dynamic_template_manager_cache_system_test.v │ ├── dynamic_template_manager_test.v │ └── escape_html_strings_in_templates.v ├── ttf/ │ ├── README.md │ ├── common.v │ ├── render_bmp.v │ ├── render_sokol/ │ │ └── cpu.v │ ├── text_block.v │ ├── ttf.v │ └── ttf_test.v ├── vweb/ │ └── vweb.v ├── x.v └── x11/ ├── v.mod └── x11.v ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ root = true [*] charset = utf-8 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true [*.{v,js,css}] indent_style = tab [*.{bat,cmd}] # BAT/CMD ~ DOS/Win requires BAT/CMD files to have CRLF EOLNs end_of_line = crlf [*.{yml,yaml}] indent_style = space indent_size = 2 [*.md] trim_trailing_whitespace = false # lines that are too long will trigger an error in cmd/tools/vcheck-md.v # run v check-md [folder/file] to test markdown files # the longest normal line is specified with this constant: # `too_long_line_length_other = 100` max_line_length = 100 [*.{txt,out}] insert_final_newline = false [{Makefile,GNUmakefile}] indent_style = tab ================================================ FILE: .git/HEAD ================================================ ref: refs/heads/master ================================================ FILE: .git/config ================================================ [core] repositoryformatversion = 1 filemode = true bare = false logallrefupdates = true [remote "origin"] url = https://github.com/vlang/v tagOpt = --no-tags fetch = +refs/heads/master:refs/remotes/origin/master promisor = true partialclonefilter = blob:limit=1048576 [branch "master"] remote = origin merge = refs/heads/master ================================================ FILE: .git/description ================================================ Unnamed repository; edit this file 'description' to name the repository. ================================================ FILE: .git/hooks/applypatch-msg.sample ================================================ #!/bin/sh # # An example hook script to check the commit log message taken by # applypatch from an e-mail message. # # The hook should exit with non-zero status after issuing an # appropriate message if it wants to stop the commit. The hook is # allowed to edit the commit message file. # # To enable this hook, rename this file to "applypatch-msg". . git-sh-setup commitmsg="$(git rev-parse --git-path hooks/commit-msg)" test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} : ================================================ FILE: .git/hooks/commit-msg.sample ================================================ #!/bin/sh # # An example hook script to check the commit log message. # Called by "git commit" with one argument, the name of the file # that has the commit message. The hook should exit with non-zero # status after issuing an appropriate message if it wants to stop the # commit. The hook is allowed to edit the commit message file. # # To enable this hook, rename this file to "commit-msg". # Uncomment the below to add a Signed-off-by line to the message. # Doing this in a hook is a bad idea in general, but the prepare-commit-msg # hook is more suited to it. # # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" # This example catches duplicate Signed-off-by lines. test "" = "$(grep '^Signed-off-by: ' "$1" | sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { echo >&2 Duplicate Signed-off-by lines. exit 1 } ================================================ FILE: .git/hooks/fsmonitor-watchman.sample ================================================ #!/usr/bin/perl use strict; use warnings; use IPC::Open2; # An example hook script to integrate Watchman # (https://facebook.github.io/watchman/) with git to speed up detecting # new and modified files. # # The hook is passed a version (currently 2) and last update token # formatted as a string and outputs to stdout a new update token and # all files that have been modified since the update token. Paths must # be relative to the root of the working tree and separated by a single NUL. # # To enable this hook, rename this file to "query-watchman" and set # 'git config core.fsmonitor .git/hooks/query-watchman' # my ($version, $last_update_token) = @ARGV; # Uncomment for debugging # print STDERR "$0 $version $last_update_token\n"; # Check the hook interface version if ($version ne 2) { die "Unsupported query-fsmonitor hook version '$version'.\n" . "Falling back to scanning...\n"; } my $git_work_tree = get_working_dir(); my $retry = 1; my $json_pkg; eval { require JSON::XS; $json_pkg = "JSON::XS"; 1; } or do { require JSON::PP; $json_pkg = "JSON::PP"; }; launch_watchman(); sub launch_watchman { my $o = watchman_query(); if (is_work_tree_watched($o)) { output_result($o->{clock}, @{$o->{files}}); } } sub output_result { my ($clockid, @files) = @_; # Uncomment for debugging watchman output # open (my $fh, ">", ".git/watchman-output.out"); # binmode $fh, ":utf8"; # print $fh "$clockid\n@files\n"; # close $fh; binmode STDOUT, ":utf8"; print $clockid; print "\0"; local $, = "\0"; print @files; } sub watchman_clock { my $response = qx/watchman clock "$git_work_tree"/; die "Failed to get clock id on '$git_work_tree'.\n" . "Falling back to scanning...\n" if $? != 0; return $json_pkg->new->utf8->decode($response); } sub watchman_query { my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') or die "open2() failed: $!\n" . "Falling back to scanning...\n"; # In the query expression below we're asking for names of files that # changed since $last_update_token but not from the .git folder. # # To accomplish this, we're using the "since" generator to use the # recency index to select candidate nodes and "fields" to limit the # output to file names only. Then we're using the "expression" term to # further constrain the results. my $last_update_line = ""; if (substr($last_update_token, 0, 1) eq "c") { $last_update_token = "\"$last_update_token\""; $last_update_line = qq[\n"since": $last_update_token,]; } my $query = <<" END"; ["query", "$git_work_tree", {$last_update_line "fields": ["name"], "expression": ["not", ["dirname", ".git"]] }] END # Uncomment for debugging the watchman query # open (my $fh, ">", ".git/watchman-query.json"); # print $fh $query; # close $fh; print CHLD_IN $query; close CHLD_IN; my $response = do {local $/; }; # Uncomment for debugging the watch response # open ($fh, ">", ".git/watchman-response.json"); # print $fh $response; # close $fh; die "Watchman: command returned no output.\n" . "Falling back to scanning...\n" if $response eq ""; die "Watchman: command returned invalid output: $response\n" . "Falling back to scanning...\n" unless $response =~ /^\{/; return $json_pkg->new->utf8->decode($response); } sub is_work_tree_watched { my ($output) = @_; my $error = $output->{error}; if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { $retry--; my $response = qx/watchman watch "$git_work_tree"/; die "Failed to make watchman watch '$git_work_tree'.\n" . "Falling back to scanning...\n" if $? != 0; $output = $json_pkg->new->utf8->decode($response); $error = $output->{error}; die "Watchman: $error.\n" . "Falling back to scanning...\n" if $error; # Uncomment for debugging watchman output # open (my $fh, ">", ".git/watchman-output.out"); # close $fh; # Watchman will always return all files on the first query so # return the fast "everything is dirty" flag to git and do the # Watchman query just to get it over with now so we won't pay # the cost in git to look up each individual file. my $o = watchman_clock(); $error = $output->{error}; die "Watchman: $error.\n" . "Falling back to scanning...\n" if $error; output_result($o->{clock}, ("/")); $last_update_token = $o->{clock}; eval { launch_watchman() }; return 0; } die "Watchman: $error.\n" . "Falling back to scanning...\n" if $error; return 1; } sub get_working_dir { my $working_dir; if ($^O =~ 'msys' || $^O =~ 'cygwin') { $working_dir = Win32::GetCwd(); $working_dir =~ tr/\\/\//; } else { require Cwd; $working_dir = Cwd::cwd(); } return $working_dir; } ================================================ FILE: .git/hooks/post-update.sample ================================================ #!/bin/sh # # An example hook script to prepare a packed repository for use over # dumb transports. # # To enable this hook, rename this file to "post-update". exec git update-server-info ================================================ FILE: .git/hooks/pre-applypatch.sample ================================================ #!/bin/sh # # An example hook script to verify what is about to be committed # by applypatch from an e-mail message. # # The hook should exit with non-zero status after issuing an # appropriate message if it wants to stop the commit. # # To enable this hook, rename this file to "pre-applypatch". . git-sh-setup precommit="$(git rev-parse --git-path hooks/pre-commit)" test -x "$precommit" && exec "$precommit" ${1+"$@"} : ================================================ FILE: .git/hooks/pre-commit.sample ================================================ #!/bin/sh # # An example hook script to verify what is about to be committed. # Called by "git commit" with no arguments. The hook should # exit with non-zero status after issuing an appropriate message if # it wants to stop the commit. # # To enable this hook, rename this file to "pre-commit". if git rev-parse --verify HEAD >/dev/null 2>&1 then against=HEAD else # Initial commit: diff against an empty tree object against=$(git hash-object -t tree /dev/null) fi # If you want to allow non-ASCII filenames set this variable to true. allownonascii=$(git config --type=bool hooks.allownonascii) # Redirect output to stderr. exec 1>&2 # Cross platform projects tend to avoid non-ASCII filenames; prevent # them from being added to the repository. We exploit the fact that the # printable range starts at the space character and ends with tilde. if [ "$allownonascii" != "true" ] && # Note that the use of brackets around a tr range is ok here, (it's # even required, for portability to Solaris 10's /usr/bin/tr), since # the square bracket bytes happen to fall in the designated range. test $(git diff-index --cached --name-only --diff-filter=A -z $against | LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 then cat <<\EOF Error: Attempt to add a non-ASCII file name. This can cause problems if you want to work with people on other platforms. To be portable it is advisable to rename the file. If you know what you are doing you can disable this check using: git config hooks.allownonascii true EOF exit 1 fi # If there are whitespace errors, print the offending file names and fail. exec git diff-index --check --cached $against -- ================================================ FILE: .git/hooks/pre-merge-commit.sample ================================================ #!/bin/sh # # An example hook script to verify what is about to be committed. # Called by "git merge" with no arguments. The hook should # exit with non-zero status after issuing an appropriate message to # stderr if it wants to stop the merge commit. # # To enable this hook, rename this file to "pre-merge-commit". . git-sh-setup test -x "$GIT_DIR/hooks/pre-commit" && exec "$GIT_DIR/hooks/pre-commit" : ================================================ FILE: .git/hooks/pre-push.sample ================================================ #!/bin/sh # An example hook script to verify what is about to be pushed. Called by "git # push" after it has checked the remote status, but before anything has been # pushed. If this script exits with a non-zero status nothing will be pushed. # # This hook is called with the following parameters: # # $1 -- Name of the remote to which the push is being done # $2 -- URL to which the push is being done # # If pushing without using a named remote those arguments will be equal. # # Information about the commits which are being pushed is supplied as lines to # the standard input in the form: # # # # This sample shows how to prevent push of commits where the log message starts # with "WIP" (work in progress). remote="$1" url="$2" zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" exit 1 fi fi done exit 0 ================================================ FILE: .git/hooks/pre-rebase.sample ================================================ #!/bin/sh # # Copyright (c) 2006, 2008 Junio C Hamano # # The "pre-rebase" hook is run just before "git rebase" starts doing # its job, and can prevent the command from running by exiting with # non-zero status. # # The hook is called with the following parameters: # # $1 -- the upstream the series was forked from. # $2 -- the branch being rebased (or empty when rebasing the current branch). # # This sample shows how to prevent topic branches that are already # merged to 'next' branch from getting rebased, because allowing it # would result in rebasing already published history. publish=next basebranch="$1" if test "$#" = 2 then topic="refs/heads/$2" else topic=`git symbolic-ref HEAD` || exit 0 ;# we do not interrupt rebasing detached HEAD fi case "$topic" in refs/heads/??/*) ;; *) exit 0 ;# we do not interrupt others. ;; esac # Now we are dealing with a topic branch being rebased # on top of master. Is it OK to rebase it? # Does the topic really exist? git show-ref -q "$topic" || { echo >&2 "No such branch $topic" exit 1 } # Is topic fully merged to master? not_in_master=`git rev-list --pretty=oneline ^master "$topic"` if test -z "$not_in_master" then echo >&2 "$topic is fully merged to master; better remove it." exit 1 ;# we could allow it, but there is no point. fi # Is topic ever merged to next? If so you should not be rebasing it. only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` only_next_2=`git rev-list ^master ${publish} | sort` if test "$only_next_1" = "$only_next_2" then not_in_topic=`git rev-list "^$topic" master` if test -z "$not_in_topic" then echo >&2 "$topic is already up to date with master" exit 1 ;# we could allow it, but there is no point. else exit 0 fi else not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` /usr/bin/perl -e ' my $topic = $ARGV[0]; my $msg = "* $topic has commits already merged to public branch:\n"; my (%not_in_next) = map { /^([0-9a-f]+) /; ($1 => 1); } split(/\n/, $ARGV[1]); for my $elem (map { /^([0-9a-f]+) (.*)$/; [$1 => $2]; } split(/\n/, $ARGV[2])) { if (!exists $not_in_next{$elem->[0]}) { if ($msg) { print STDERR $msg; undef $msg; } print STDERR " $elem->[1]\n"; } } ' "$topic" "$not_in_next" "$not_in_master" exit 1 fi <<\DOC_END This sample hook safeguards topic branches that have been published from being rewound. The workflow assumed here is: * Once a topic branch forks from "master", "master" is never merged into it again (either directly or indirectly). * Once a topic branch is fully cooked and merged into "master", it is deleted. If you need to build on top of it to correct earlier mistakes, a new topic branch is created by forking at the tip of the "master". This is not strictly necessary, but it makes it easier to keep your history simple. * Whenever you need to test or publish your changes to topic branches, merge them into "next" branch. The script, being an example, hardcodes the publish branch name to be "next", but it is trivial to make it configurable via $GIT_DIR/config mechanism. With this workflow, you would want to know: (1) ... if a topic branch has ever been merged to "next". Young topic branches can have stupid mistakes you would rather clean up before publishing, and things that have not been merged into other branches can be easily rebased without affecting other people. But once it is published, you would not want to rewind it. (2) ... if a topic branch has been fully merged to "master". Then you can delete it. More importantly, you should not build on top of it -- other people may already want to change things related to the topic as patches against your "master", so if you need further changes, it is better to fork the topic (perhaps with the same name) afresh from the tip of "master". Let's look at this example: o---o---o---o---o---o---o---o---o---o "next" / / / / / a---a---b A / / / / / / / / c---c---c---c B / / / / \ / / / / b---b C \ / / / / / \ / ---o---o---o---o---o---o---o---o---o---o---o "master" A, B and C are topic branches. * A has one fix since it was merged up to "next". * B has finished. It has been fully merged up to "master" and "next", and is ready to be deleted. * C has not merged to "next" at all. We would want to allow C to be rebased, refuse A, and encourage B to be deleted. To compute (1): git rev-list ^master ^topic next git rev-list ^master next if these match, topic has not merged in next at all. To compute (2): git rev-list master..topic if this is empty, it is fully merged to "master". DOC_END ================================================ FILE: .git/hooks/pre-receive.sample ================================================ #!/bin/sh # # An example hook script to make use of push options. # The example simply echoes all push options that start with 'echoback=' # and rejects all pushes when the "reject" push option is used. # # To enable this hook, rename this file to "pre-receive". if test -n "$GIT_PUSH_OPTION_COUNT" then i=0 while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" do eval "value=\$GIT_PUSH_OPTION_$i" case "$value" in echoback=*) echo "echo from the pre-receive-hook: ${value#*=}" >&2 ;; reject) exit 1 esac i=$((i + 1)) done fi ================================================ FILE: .git/hooks/prepare-commit-msg.sample ================================================ #!/bin/sh # # An example hook script to prepare the commit log message. # Called by "git commit" with the name of the file that has the # commit message, followed by the description of the commit # message's source. The hook's purpose is to edit the commit # message file. If the hook fails with a non-zero status, # the commit is aborted. # # To enable this hook, rename this file to "prepare-commit-msg". # This hook includes three examples. The first one removes the # "# Please enter the commit message..." help message. # # The second includes the output of "git diff --name-status -r" # into the message, just before the "git status" output. It is # commented because it doesn't cope with --amend or with squashed # commits. # # The third example adds a Signed-off-by line to the message, that can # still be edited. This is rarely a good idea. COMMIT_MSG_FILE=$1 COMMIT_SOURCE=$2 SHA1=$3 /usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" # case "$COMMIT_SOURCE,$SHA1" in # ,|template,) # /usr/bin/perl -i.bak -pe ' # print "\n" . `git diff --cached --name-status -r` # if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; # *) ;; # esac # SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') # git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" # if test -z "$COMMIT_SOURCE" # then # /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" # fi ================================================ FILE: .git/hooks/push-to-checkout.sample ================================================ #!/bin/sh # An example hook script to update a checked-out tree on a git push. # # This hook is invoked by git-receive-pack(1) when it reacts to git # push and updates reference(s) in its repository, and when the push # tries to update the branch that is currently checked out and the # receive.denyCurrentBranch configuration variable is set to # updateInstead. # # By default, such a push is refused if the working tree and the index # of the remote repository has any difference from the currently # checked out commit; when both the working tree and the index match # the current commit, they are updated to match the newly pushed tip # of the branch. This hook is to be used to override the default # behaviour; however the code below reimplements the default behaviour # as a starting point for convenient modification. # # The hook receives the commit with which the tip of the current # branch is going to be updated: commit=$1 # It can exit with a non-zero status to refuse the push (when it does # so, it must not modify the index or the working tree). die () { echo >&2 "$*" exit 1 } # Or it can make any necessary changes to the working tree and to the # index to bring them to the desired state when the tip of the current # branch is updated to the new commit, and exit with a zero status. # # For example, the hook can simply run git read-tree -u -m HEAD "$1" # in order to emulate git fetch that is run in the reverse direction # with git push, as the two-tree form of git read-tree -u -m is # essentially the same as git switch or git checkout that switches # branches while keeping the local changes in the working tree that do # not interfere with the difference between the branches. # The below is a more-or-less exact translation to shell of the C code # for the default behaviour for git's push-to-checkout hook defined in # the push_to_deploy() function in builtin/receive-pack.c. # # Note that the hook will be executed from the repository directory, # not from the working tree, so if you want to perform operations on # the working tree, you will have to adapt your code accordingly, e.g. # by adding "cd .." or using relative paths. if ! git update-index -q --ignore-submodules --refresh then die "Up-to-date check failed" fi if ! git diff-files --quiet --ignore-submodules -- then die "Working directory has unstaged changes" fi # This is a rough translation of: # # head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX if git cat-file -e HEAD 2>/dev/null then head=HEAD else head=$(git hash-object -t tree --stdin &2 exit 1 } unset GIT_DIR GIT_WORK_TREE cd "$worktree" && if grep -q "^diff --git " "$1" then validate_patch "$1" else validate_cover_letter "$1" fi && if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" then git config --unset-all sendemail.validateWorktree && trap 'git worktree remove -ff "$worktree"' EXIT && validate_series fi ================================================ FILE: .git/hooks/update.sample ================================================ #!/bin/sh # # An example hook script to block unannotated tags from entering. # Called by "git receive-pack" with arguments: refname sha1-old sha1-new # # To enable this hook, rename this file to "update". # # Config # ------ # hooks.allowunannotated # This boolean sets whether unannotated tags will be allowed into the # repository. By default they won't be. # hooks.allowdeletetag # This boolean sets whether deleting tags will be allowed in the # repository. By default they won't be. # hooks.allowmodifytag # This boolean sets whether a tag may be modified after creation. By default # it won't be. # hooks.allowdeletebranch # This boolean sets whether deleting branches will be allowed in the # repository. By default they won't be. # hooks.denycreatebranch # This boolean sets whether remotely creating branches will be denied # in the repository. By default this is allowed. # # --- Command line refname="$1" oldrev="$2" newrev="$3" # --- Safety check if [ -z "$GIT_DIR" ]; then echo "Don't run this script from the command line." >&2 echo " (if you want, you could supply GIT_DIR then run" >&2 echo " $0 )" >&2 exit 1 fi if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then echo "usage: $0 " >&2 exit 1 fi # --- Config allowunannotated=$(git config --type=bool hooks.allowunannotated) allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) denycreatebranch=$(git config --type=bool hooks.denycreatebranch) allowdeletetag=$(git config --type=bool hooks.allowdeletetag) allowmodifytag=$(git config --type=bool hooks.allowmodifytag) # check for no description projectdesc=$(sed -e '1q' "$GIT_DIR/description") case "$projectdesc" in "Unnamed repository"* | "") echo "*** Project description file hasn't been set" >&2 exit 1 ;; esac # --- Check types # if $newrev is 0000...0000, it's a commit to delete a ref. zero=$(git hash-object --stdin &2 echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 exit 1 fi ;; refs/tags/*,delete) # delete tag if [ "$allowdeletetag" != "true" ]; then echo "*** Deleting a tag is not allowed in this repository" >&2 exit 1 fi ;; refs/tags/*,tag) # annotated tag if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 then echo "*** Tag '$refname' already exists." >&2 echo "*** Modifying a tag is not allowed in this repository." >&2 exit 1 fi ;; refs/heads/*,commit) # branch if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then echo "*** Creating a branch is not allowed in this repository" >&2 exit 1 fi ;; refs/heads/*,delete) # delete branch if [ "$allowdeletebranch" != "true" ]; then echo "*** Deleting a branch is not allowed in this repository" >&2 exit 1 fi ;; refs/remotes/*,commit) # tracking branch ;; refs/remotes/*,delete) # delete tracking branch if [ "$allowdeletebranch" != "true" ]; then echo "*** Deleting a tracking branch is not allowed in this repository" >&2 exit 1 fi ;; *) # Anything else (is there anything else?) echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 exit 1 ;; esac # --- Finished exit 0 ================================================ FILE: .git/info/exclude ================================================ # git ls-files --others --exclude-from=.git/info/exclude # Lines that start with '#' are comments. # For a project mostly in C, the following would be a good set of # exclude patterns (uncomment them if you want to use them): # *.[oa] # *~ ================================================ FILE: .git/logs/HEAD ================================================ 0000000000000000000000000000000000000000 cdfc0bba9081099a0a6a62fcbbe7f364ba38231b appuser 1773985664 +0000 clone: from https://github.com/vlang/v ================================================ FILE: .git/logs/refs/heads/master ================================================ 0000000000000000000000000000000000000000 cdfc0bba9081099a0a6a62fcbbe7f364ba38231b appuser 1773985664 +0000 clone: from https://github.com/vlang/v ================================================ FILE: .git/logs/refs/remotes/origin/HEAD ================================================ 0000000000000000000000000000000000000000 cdfc0bba9081099a0a6a62fcbbe7f364ba38231b appuser 1773985664 +0000 clone: from https://github.com/vlang/v ================================================ FILE: .git/objects/pack/pack-4c5eb4b01e8d20d1b77462674426e18b34b3eb8d.pack ================================================ [File too large to display: 12.1 MB] ================================================ FILE: .git/objects/pack/pack-4c5eb4b01e8d20d1b77462674426e18b34b3eb8d.promisor ================================================ cdfc0bba9081099a0a6a62fcbbe7f364ba38231b refs/heads/master ================================================ FILE: .git/objects/pack/pack-a119d32135c98d4d3e4374ad1ecd525e9b537c4c.promisor ================================================ ================================================ FILE: .git/packed-refs ================================================ # pack-refs with: peeled fully-peeled sorted cdfc0bba9081099a0a6a62fcbbe7f364ba38231b refs/remotes/origin/master ================================================ FILE: .git/refs/heads/master ================================================ cdfc0bba9081099a0a6a62fcbbe7f364ba38231b ================================================ FILE: .git/refs/remotes/origin/HEAD ================================================ ref: refs/remotes/origin/master ================================================ FILE: .git/shallow ================================================ cdfc0bba9081099a0a6a62fcbbe7f364ba38231b ================================================ FILE: .gitattributes ================================================ * text=auto eol=lf *.bat eol=crlf *.v linguist-language=V *.vv linguist-language=V *.vsh linguist-language=V v.mod linguist-language=V .vdocignore linguist-language=ignore Dockerfile.* linguist-language=Dockerfile ================================================ FILE: .github/.prettierrc ================================================ { "singleQuote": true } ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms open_collective: vlang patreon: vlang github: [medvednikov] ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: true contact_links: - name: 💬 General Questions and Answers about V url: https://github.com/vlang/v/discussions/categories/questions-and-answers about: You can ask and answer questions about V in the discussions forum. - name: 💬 Discord Server url: https://discord.gg/vlang about: You can join our Discord server for real time discussion and support ================================================ FILE: .github/ISSUE_TEMPLATE/documentation.yml ================================================ name: 📕 Documentation Issue description: Report an issue in the Reference documentation or Developer Guide labels: ['Unit: Documentation'] body: - type: textarea id: description attributes: label: Describe the issue description: A clear and concise description of the issue. validations: required: true - type: textarea id: links attributes: label: Links description: Include links to affected documentation page(s). validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/feature-request.yml ================================================ name: 🚀 Feature Request description: Suggest an idea for this project labels: [Feature Request] body: - type: textarea id: description attributes: label: Describe the feature description: A clear and concise description of the feature you are proposing. validations: required: true - type: textarea id: use-case attributes: label: Use Case description: | Why do you need this feature? For example: "I'm always frustrated when..." validations: required: true - type: textarea id: solution attributes: label: Proposed Solution description: Suggest how to implement the addition or change. Please include prototype/workaround/sketch/reference implementation. validations: required: false - type: textarea id: other attributes: label: Other Information description: Any alternative solutions or features you considered, a more detailed explanation, stack traces, related issues, links for context, etc. validations: required: false - type: checkboxes id: ack attributes: label: Acknowledgements options: - label: I may be able to implement this feature request required: false - label: This feature might incur a breaking change required: false - type: input id: version attributes: label: Version used description: Please provide the version of the repository or tool you are using. validations: required: true - type: textarea id: environment attributes: label: Environment details (OS name and version, etc.) description: You can use `v doctor` to fill up this section. validations: required: true ================================================ FILE: .github/PULL_REQUEST_TEMPLATE ================================================ ================================================ FILE: .github/actions/cache-apt-packages-action/action.yml ================================================ name: 'Cache Apt Packages' description: 'Cache all commonly used apt packages to speed up CI jobs' # imagemagick : convert, mogrify # xvfb : xvfb # openimageio-tools : idiff # libxcursor-dev libxi-dev : V gfx deps # libgl1-mesa-dri : For headless rendering on the CI / software DRI driver (LIBGL_ALWAYS_SOFTWARE=true) # freeglut3-dev : Fixes graphic apps compilation with tcc # sdl2 : needed for Puzzle Vibes & Chocolate Doom # libsodium-dev : needed for Gitly and C2V runs: using: 'composite' steps: - uses: awalsh128/cache-apt-pkgs-action@v1.5.3 with: version: 1.0 packages: expect binutils postgresql sqlite3 clang valgrind \ imagemagick openimageio-tools xvfb xsel xclip \ libsodium-dev libpq-dev libssl-dev libsqlite3-dev \ libfreetype6-dev libxi-dev libxcursor-dev \ libgl-dev libxrandr-dev libasound2-dev \ libx11-dev freeglut3-dev mesa-common-dev libgl1-mesa-dev libgl1-mesa-dri \ libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev libsdl2-net-dev \ libpng-dev libsamplerate0-dev \ xfonts-75dpi xfonts-base - name: Install common packages run: echo "done installing packages" shell: bash ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: 'github-actions' directory: '/' schedule: interval: 'daily' ================================================ FILE: .github/problem-matchers/register_all.vsh ================================================ // The task of this program, is to register all available .json files // in this folder with Github Actions, so that it can make annotations // for all found notices/warnings/errors produced by the V compiler // while running the CI jobs. // Those annotations provide a way to get a quick overview for failures, // without having to scroll into the detailed logs produced by each job. const github_job = getenv('GITHUB_JOB') if github_job == '' { exit(0) } dump(github_job) chdir(@VEXEROOT)! for f in walk_ext('.github/problem-matchers/', '.json').sorted() { println('::add-matcher::${real_path(f)}') println('registered matcher: `${f}`') } ================================================ FILE: .github/problem-matchers/v.json ================================================ { "__comment": "Based on https://github.com/python/cpython/blob/main/.github/problem-matchers/gcc.json", "problemMatcher": [ { "owner": "v-problem-matcher", "pattern": [ { "regexp": "^(.*):(\\d+):(\\d+):\\s+(?:fatal\\s+)?(warning|error|notice):\\s+(.*)$", "file": 1, "line": 2, "column": 3, "severity": 4, "message": 5 } ] } ] } ================================================ FILE: .github/workflows/Dockerfile.ci_alpine_local ================================================ ####################################################################################### ## The goal of this file, is to provide an easy and reproducible way to check *locally* ## the CI job `docker-alpine-musl-gcc` ## Building the docker image: ## docker build -t ci_alpine_local - < .github/workflows/Dockerfile.ci_alpine_local ## Running the docker image, after building it: ## docker run --rm -it -v .:/opt/vlang -w /opt/vlang ci_alpine_local ## Once it is running, inside the container you can: ## make && v -e 'println(2+2)' ## ... then do whatever you need to reproduce the CI test failure. ## Note: after you are finished, and exit the container, run `make` again, otherwise ## you will be using V (and potentially V tools) that were compiled with musl. ####################################################################################### FROM thevlang/vlang:alpine-build LABEL maintainer="spytheman " WORKDIR /opt/vlang ENV PATH /opt/vlang:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ## install development packages RUN apk --no-cache add \ musl-dev libc-dev libc6-compat gcompat \ libunwind-dev libunwind-static \ gc gc-dev \ binutils diffutils elfutils \ strace gdb \ pcre bash fzf fzf-vim tmux less file colordiff \ vim vim-editorconfig \ nano nano-syntax \ micro RUN git config --global --add safe.directory /opt/vlang &&\ git config --global --add safe.directory /opt/vlang/vc &&\ git config --global --add safe.directory /opt/vlang/thirdparty/tcc &&\ find /usr/share/nano/ -iname "*.nanorc" -exec echo include {} \; >> ~/.nanorc &&\ micro -plugin install detectindent &&\ micro -plugin install editorconfig &&\ micro -plugin install monokai-dark &&\ micro -plugin install quickfix &&\ micro -plugin install runit &&\ micro -plugin install cheat &&\ micro -plugin install jump &&\ true ## setup runtime environment for v and bash: ENV VTMP /tmp/v ENV VMODULES /tmp/vmodules ENV VFLAGS "-d dynamic_boehm" CMD ["bash"] ================================================ FILE: .github/workflows/add-voting-info.yml ================================================ name: Add voting info to new issue on: issues: types: - opened jobs: add-voting-info: runs-on: ubuntu-latest permissions: issues: write steps: - name: Append voting info to issue body uses: julien-deramond/update-issue-body@v1 with: issue-number: ${{ github.event.issue.number }} body: | > [!NOTE] > You can use the 👍 reaction to increase the issue's priority for developers. > > Please note that only the 👍 reaction to the issue itself counts as a vote. > Other reactions and those to comments will not be taken into account. edit-mode: append append-separator: newline ================================================ FILE: .github/workflows/alpine.build.sh ================================================ #!/bin/sh -l set -e pwd uname -a make -j4 ./v version du -s . echo "DONE" ================================================ FILE: .github/workflows/alpine.test.sh ================================================ #!/bin/sh -l set -e pwd uname -a du -s . ls -lat ##./v -silent test-all ## try running the known failing tests first to get faster feedback ./v vlib/builtin/string_test.v ./v vlib/strings/builder_test.v ./v -silent test-cleancode ./v -silent test-self ./v build-vbinaries echo "DONE" ================================================ FILE: .github/workflows/android_cross_compile.vsh ================================================ #!/usr/bin/env -S v module main import os import vab.vxt import vab.android.ndk fn main() { assert ndk.found() assert vxt.found() work_dir := os.join_path(os.vtmp_dir(), 'android_cross_compile_test') os.rm(work_dir) or {} os.mkdir_all(work_dir) or { panic(err) } vexe := vxt.vexe() examples_dir := os.join_path(vxt.home(), 'examples') v_example := os.join_path(examples_dir, 'toml.v') ndk_version := ndk.default_version() sysroot_path := ndk.sysroot_path(ndk_version) or { panic(err) } include_path := os.join_path(sysroot_path, 'usr', 'include') android_include_path := os.join_path(include_path, 'android') //'-I"${include_path}"' cflags := ['-I"${android_include_path}"', '-Wno-unused-value', '-Wno-implicit-function-declaration', '-Wno-int-conversion'] for arch in ndk.supported_archs { for level in ['min', 'max'] { compiler_api := match level { 'min' { ndk.compiler_min_api(.c, ndk_version, arch) or { panic(err) } } 'max' { ndk.compiler_max_api(.c, ndk_version, arch) or { panic(err) } } else { panic('invalid min/max level') } } os.setenv('VCROSS_COMPILER_NAME', compiler_api, true) c_file := os.join_path(work_dir, arch + '-' + level + '.c') o_file := os.join_path(work_dir, arch + '-' + level + '.o') // x.v -> x.c v_compile_cmd := '${vexe} -o ${c_file} -os android -gc none ${v_example}' vres := os.execute(v_compile_cmd) if vres.exit_code != 0 { panic('"${v_compile_cmd}" failed: ${vres.output}') } assert os.exists(c_file) // x.c -> x.o compile_cmd := '${compiler_api} ${cflags.join(' ')} -c ${c_file} -o ${o_file}' cres := os.execute(compile_cmd) if cres.exit_code != 0 { panic('"${compile_cmd}" failed: ${cres.output}') } assert os.exists(o_file) compiler_exe_name := os.file_name(compiler_api) println('Compiled examples/toml.v successfully for (${level}) ${arch} ${compiler_exe_name}') } } } ================================================ FILE: .github/workflows/benchmark_footprint_json_decode.yml ================================================ name: json decoder benchmark CI on: push: paths: - 'vlib/x/json2/**' # Trigger on changes in this folder jobs: json-encode-benchmark: runs-on: ubuntu-latest timeout-minutes: 5 steps: - name: Checkout repository uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: Run V benchmark and save output run: (echo '```txt'; v -prod crun vlib/x/json2/tests/bench.v; echo '```') > vlib/x/json2/tests/bench_out.md - name: Upload result file uses: actions/upload-artifact@v7 with: name: program-output path: vlib/x/json2/tests/bench_out.md ================================================ FILE: .github/workflows/benchmark_footprint_json_encode.yml ================================================ name: json encoder benchmark CI on: push: paths: - 'vlib/x/json2/**' # Trigger on changes in this folder - '!vlib/x/json2/strict/**' # Ignore - '!vlib/x/json2/tests/**' # Ignore jobs: json-encode-benchmark: runs-on: ubuntu-latest timeout-minutes: 5 steps: - name: Checkout repository uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: Run V benchmark and save output run: (echo '```sh'; v -prod crun vlib/v/tests/bench/bench_json_vs_json2.v; echo '```') > vlib/v/tests/bench/bench_json_vs_json2_out.md - name: Upload result file uses: actions/upload-artifact@v7 with: name: program-output path: vlib/v/tests/bench/bench_json_vs_json2_out.md ================================================ FILE: .github/workflows/bootstrapping_ci.yml ================================================ name: Bootstrapping CI on: workflow_dispatch: push: paths-ignore: - '**.yml' - '**.md' - '**.vv' - '**.out' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' - '!cmd/tools/vup.v' - '!**/bootstrapping_ci.yml' pull_request: paths-ignore: - '**.yml' - '**.md' - '**.vv' - '**.out' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' - '!cmd/tools/vup.v' - '!**/bootstrapping_ci.yml' concurrency: group: bootstrapping-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: bootstrap-v: strategy: matrix: os: [ubuntu-latest, macos-14] fail-fast: false runs-on: ${{ matrix.os }} timeout-minutes: 20 env: VFLAGS: -no-parallel B_LFLAGS: -lm -lpthread steps: - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Build V run: make -j4 - name: Test bootstrapping (v.c can be compiled and run with -os cross) run: | ls -la v vc/v.c ./v -os cross -o vc/v.c cmd/v # shellcheck disable=SC2086 cc -o v_from_vc vc/v.c $B_LFLAGS ls -lart v_from_vc ./v_from_vc version ./v_from_vc run examples/hello_world.v ./v_from_vc -o v_from_vc_produced_native_v cmd/v ./v_from_vc_produced_native_v run examples/hello_world.v ### the next make invocation will simulate building V from scratch make local=1 ls -la v vc/v.c v_from_vc v_from_vc_produced_native_v ./v_from_vc_produced_native_v -os cross -o vc/v.c cmd/v ### do it a second time, just in case: # shellcheck disable=SC2086 clang -o v_from_vc2 vc/v.c $B_LFLAGS ls -lart v_from_vc2 ./v_from_vc2 version ./v_from_vc2 run examples/hello_world.v ./v_from_vc2 -o v_from_vc_produced_native_v2 cmd/v ./v_from_vc_produced_native_v2 run examples/hello_world.v make local=1 ls -la v vc/v.c ls -la v_from_vc v_from_vc_produced_native_v ls -la v_from_vc2 v_from_vc_produced_native_v2 - name: Ensure V master is available if: github.ref_name != 'master' run: git branch master remotes/origin/master - name: Test `v up` run: | # Derive a commit sha from an older successful fast workflow on master that was able to build V. # The workflow used below is `Path Testing CI` (18477644). recent_good_commit=$(curl -L \ -H "Accept: application/vnd.github+json" \ -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ -H "X-GitHub-Api-Version: 2022-11-28" \ "https://api.github.com/repos/vlang/v/actions/workflows/18477644/runs?branch=master&status=success&event=push&per_page=5&page=2" \ | jq -r '.workflow_runs[4].head_sha') echo "recent_good_commit=$recent_good_commit" # Build oldv at recent_good_commit. ./v run cmd/tools/oldv.v -v "$recent_good_commit" cd "$HOME/.cache/oldv/v_at_$recent_good_commit" # Test updating ./v version && ./v -v up && ./v version ./v -o v2 cmd/v && ./v2 -o v3 cmd/v ================================================ FILE: .github/workflows/build_on_ubuntu_25_ci.yml ================================================ name: CI Ubuntu 25 GCC 14.2 on: workflow_dispatch: push: paths-ignore: - '**.md' - '**.yml' - '!**/build_on_ubuntu_25_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**/build_on_ubuntu_25_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' jobs: ubuntu-25-gcc-14-2-build: runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v6 - name: Build and test in Ubuntu 25.04 with GCC 14.2 run: | set -o xtrace echo "$PWD" whoami touch outside_docker.txt git log -n4 echo "running docker ..." docker run --rm \ --mount type=bind,source=/home/runner/work/v/v,destination=/src \ -w /src ubuntu:25.04 bash -c ' set -o xtrace echo "running inside docker" whoami cp -r /src ~/vproject; cd ~/vproject touch inside_docker.txt ls -la git log -n4 apt update -y -qq apt install -y -qq git build-essential make git config --global --add safe.directory /src/vc git config --global --add safe.directory /src/thirdparty/tcc make ./v symlink v run examples/hello_world.v v run examples/primes.v ' ================================================ FILE: .github/workflows/build_vinix_locally.sh ================================================ #!/usr/bin/env bash set -e V=$PWD/v if [[ -x "$V" ]] then echo "The v executable exists." else echo "This script should be run from the top level folder of a V repository" echo "i.e. the folder where your V executable is." exit 1 fi BUILD=$PWD/vinix_build echo "Creating $BUILD folder..." rm -rf $BUILD mkdir -p $BUILD cd $BUILD echo "Clone current Vinix" ./v retry -- git clone --depth=1 https://github.com/vlang/vinix.git cd $BUILD echo "Clone current mlibc" ./v retry -- git clone --depth=1 https://github.com/managarm/mlibc.git cd $BUILD echo "Patch mlibc for Vinix" cd mlibc patch -p3 < ../vinix/patches/mlibc/mlibc.patch cd $BUILD echo "Install mlibc headers" mkdir mlibc-build cd mlibc-build meson --cross-file ../vinix/cross_file.txt --prefix=/ -Dheaders_only=true ../mlibc ninja mkdir ../mlibc-headers DESTDIR=`realpath ../mlibc-headers` ninja install cd $BUILD echo "Attempt to build the Vinix kernel (debug)" cd vinix/kernel make PROD=false CFLAGS="-D__vinix__ -O2 -g -pipe -I../../mlibc-headers/include" make clean cd $BUILD echo "Attempt to build the Vinix kernel (prod)" cd vinix/kernel make PROD=true CFLAGS="-D__vinix__ -O2 -g -pipe -I../../mlibc-headers/include" make clean rm -rf $BUILD ================================================ FILE: .github/workflows/c2v_ci.yml ================================================ name: C2V apps on: push: paths-ignore: - '**.md' - '**.yml' - '!**/c2v_ci.yml' - 'doc/**' - 'examples/**' - 'tutorials/**' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**/c2v_ci.yml' - 'doc/**' - 'examples/**' - 'tutorials/**' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' concurrency: group: c2v-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: build-doom: runs-on: ubuntu-24.04 timeout-minutes: 30 steps: - uses: actions/checkout@v6 - name: Build V run: make && ./v symlink - name: Set 8.8.8.8 as dns server run: | sudo sed -i 's/#DNS=/DNS=8.8.8.8 8.8.4.4/g' /etc/systemd/resolved.conf sudo systemctl daemon-reload sudo systemctl restart systemd-networkd sudo systemctl restart systemd-resolved dig distro.ibiblio.org - name: Install C2V run: | v retry -- v install --git https://github.com/vlang/c2v v -g ~/.vmodules/c2v/ || true - name: Install dependencies run: | if [ "${{ runner.os }}" == "Linux" ]; then .github/workflows/disable_azure_mirror.sh v retry -- sudo apt update -y -qq v retry -- sudo apt install libsdl2-dev libsdl2-mixer-dev libsdl2-net-dev libpng-dev libsamplerate0-dev else v retry -- brew install sdl2 sdl2_mixer sdl2_net libpng libsamplerate fi - name: Build original Chocolate Doom run: | v retry -- git clone --quiet --depth 1 https://github.com/vlang/doom ~/code/doom cd ~/code/doom/chocolate-doom cmake -DCMAKE_BUILD_TYPE=Debug . make chocolate-doom - name: Translate the whole game in project/folder mode and compile it run: | touch ~/DOOM1.WAD WAD_FILE=~/DOOM1.WAD ~/code/doom/build_whole_project.sh test-regression: runs-on: ubuntu-24.04 timeout-minutes: 20 env: VFLAGS: -cc tcc DISPLAY: :99 LIBGL_ALWAYS_SOFTWARE: true VTMP: /tmp steps: - uses: actions/checkout@v6 - name: Build V run: make && ./v symlink - name: Set 8.8.8.8 as dns server run: | sudo sed -i 's/#DNS=/DNS=8.8.8.8 8.8.4.4/g' /etc/systemd/resolved.conf sudo systemctl daemon-reload sudo systemctl restart systemd-networkd sudo systemctl restart systemd-resolved dig distro.ibiblio.org - name: Install C2V run: | v retry -- v install --git https://github.com/vlang/c2v v -g ~/.vmodules/c2v/ || true - name: Install dependencies run: | .github/workflows/disable_azure_mirror.sh v retry -- sudo apt update -y -qq v retry -- sudo apt install libsdl2-dev libsdl2-mixer-dev libsdl2-net-dev libpng-dev libsamplerate0-dev # c2v / DOOM dependencies # vgret dependencies # imagemagick : convert, mogrify, import # xvfb : For starting X11 Virtual FrameBuffers # openimageio-tools : idiff # libgl1-mesa-dri : For headless rendering / software DRI driver (LIBGL_ALWAYS_SOFTWARE=true) # freeglut3-dev : Fixes graphic apps compilation with tcc v retry -- sudo apt install imagemagick openimageio-tools freeglut3-dev libgl1-mesa-dri xvfb xsel xclip - name: Setup test tools run: | # Fetch the free ~4MB DOOM1.WAD from the link at https://doomwiki.org/wiki/DOOM1.WAD v retry -- v download https://distro.ibiblio.org/slitaz/sources/packages/d/doom1.wad mv doom1.wad ~/doom1.wad # Get imgur upload script v retry -- v download https://raw.githubusercontent.com/tremby/imgur.sh/c98345d/imgur.sh chmod +x ./imgur.sh # Get regression images to test against v retry -- git clone https://github.com/Larpon/doom-regression-images - name: Build original Chocolate Doom run: | v retry -- git clone --quiet --depth 1 https://github.com/vlang/doom ~/code/doom cd ~/code/doom/chocolate-doom cmake -DCMAKE_BUILD_TYPE=Debug . make chocolate-doom - name: Translate the whole game in project/folder mode run: WAD_FILE=~/doom1.wad ~/code/doom/build_whole_project.sh - name: Sample and compare with vgret id: compare continue-on-error: true run: | Xvfb "$DISPLAY" -screen 0 800x600x24 -fbdir /var/tmp/ & sleep 2; while [ ! -f /var/tmp/Xvfb_screen0 ]; do sleep 0.5; done # give xvfb time to start, even on slow CI runs sleep 5; v gret -r ~/code/doom -t ./doom-regression-images/vgret.doom.toml -v ./doom-sample_images ./doom-regression-images - name: Upload regression to imgur if: steps.compare.outcome != 'success' run: | ./imgur.sh /tmp/fail.png ./imgur.sh /tmp/diff.png exit 1 ================================================ FILE: .github/workflows/compare_pr_to_master.v ================================================ import os import time const compare_prod = '-prod' in os.args const cleanup_tmp = '-no-cleanup' !in os.args const fetch_remote = '-no-fetch' !in os.args fn gbranch() string { return os.execute(r'git branch --list|grep ^\*').output.trim_left('* ').trim_space() } fn gcommit() string { return os.execute(r'git rev-parse --short=7 HEAD').output.trim_left('* ').trim_space() } fn r(cmd string) { res := os.system(cmd) if res != 0 { eprintln('> failed running: `${cmd}`') exit(1) } } fn xtime(cmd string) { $if linux { r('/usr/bin/time -f "CPU: %Us\tReal: %es\tElapsed: %E\tRAM: %MKB\t%C" ${cmd}') return } $if macos { r('/opt/homebrew/bin/gtime -f "CPU: %Us\tReal: %es\tElapsed: %E\tRAM: %MKB\t%C" ${cmd}') return } // Pure V fallback - no memory stats, but better than nothing ... before := time.now() r(cmd) after := time.now() delta_time := after - before println('> Elapsed time: ${delta_time.milliseconds()} ms, for cmd: ${cmd}') } fn show_size(fpath string) { println('>Size of ${fpath:20s}: ${os.file_size(fpath):10}') } fn compare_size(fpath1 string, fpath2 string) { size1 := os.file_size(fpath1) size2 := os.file_size(fpath2) diff_ := i64(size2) - i64(size1) println('>>>>>> size("${fpath2:17}") - size("${fpath1:17}") = ${size2:10} - ${size1:10} = ${diff_:10}') } fn vcompare(vold string, vnew string) { r("v repeat --nmaxs 7 -R 3 '${vold} -check-syntax examples/hello_world.v' '${vnew} -check-syntax examples/hello_world.v'") r("v repeat --nmaxs 7 -R 3 '${vold} -check examples/hello_world.v' '${vnew} -check examples/hello_world.v'") r("v repeat --nmaxs 7 -R 3 '${vold} -no-parallel -o ohw.c examples/hello_world.v' '${vnew} -no-parallel -o nhw.c examples/hello_world.v'") compare_size('ohw.c', 'nhw.c') r("v repeat --nmaxs 7 -R 3 '${vold} -no-parallel -o ohw.exe examples/hello_world.v' '${vnew} -no-parallel -o nhw.exe examples/hello_world.v'") compare_size('ohw.exe', 'nhw.exe') r("v repeat --nmaxs 7 -R 3 '${vold} -check-syntax cmd/v' '${vnew} -check-syntax cmd/v'") r("v repeat --nmaxs 7 -R 3 '${vold} -check cmd/v' '${vnew} -check cmd/v'") r("v repeat --nmaxs 7 -R 3 '${vold} -no-parallel -o ov.c cmd/v' '${vnew} -no-parallel -o nv.c cmd/v'") compare_size('ov.c', 'nv.c') r("v repeat --nmaxs 7 -R 3 '${vold} -no-parallel -o ov.exe cmd/v' '${vnew} -no-parallel -o nv.exe cmd/v'") compare_size('ov.exe', 'nv.exe') } fn hline(header_message string) { println('='.repeat(98)) println(header_message) } fn main() { // The starting point, when this program should be started, is just after `gh pr checkout NUMBER`. start := time.now() pr_branch := gbranch() pr_commit := gcommit() hline('Current git branch: ${pr_branch}, commit: ${pr_commit}') println(' Compiling new V executables from PR branch: ${pr_branch}, commit: ${pr_commit} ...') // *not* using v self here is deliberate, so that the `v` executable itself, is not changed after running this script xtime('./v -o vnew1 cmd/v') xtime('./vnew1 -o vnew2 cmd/v') xtime('./vnew2 -no-parallel -o vnew cmd/v') xtime('./vnew -no-parallel -o nhw_current.c examples/hello_world.v') xtime('./vnew -no-parallel -o nhw_current_gcc.c -cc gcc examples/hello_world.v') xtime('./vnew -no-parallel -o nv_current.c cmd/v') if compare_prod { xtime('./vnew -no-parallel -prod -o vnew_prod cmd/v') } show_size('nhw_current.c') show_size('nhw_current_gcc.c') show_size('nv_current.c') show_size('vnew') if compare_prod { show_size('vnew_prod') } r('rm -rf vnew1 vnew2') if fetch_remote { // make sure to always compare against the main V repo's master branch by default: os.execute('git -C . remote add V_REPO https://github.com/vlang/v.git') os.execute('git -C . fetch V_REPO') os.execute('git branch -D v_repo_master') os.execute('git branch -f --track v_repo_master V_REPO/master') } r('git checkout v_repo_master') master_branch := gbranch() hline(' Compiling old V executables from branch: ${master_branch}, commit: ${gcommit()} ...') xtime('./v -o vold1 cmd/v') xtime('./vold1 -o vold2 cmd/v') xtime('./vold2 -no-parallel -o vold cmd/v') xtime('./vold -no-parallel -o ohw_master.c examples/hello_world.v') xtime('./vold -no-parallel -o ohw_master_gcc.c -cc gcc examples/hello_world.v') xtime('./vold -no-parallel -o ov_master.c cmd/v') if compare_prod { xtime('./vold -no-parallel -prod -o vold_prod cmd/v') show_size('vold_prod') } show_size('ohw_master.c') show_size('ohw_master_gcc.c') show_size('ov_master.c') show_size('vold') if compare_prod { show_size('vold_prod') } r('rm -rf vold1 vold2') hline('File sizes so far ...') compare_size('ohw_master.c', 'nhw_current.c') compare_size('ohw_master_gcc.c', 'nhw_current_gcc.c') compare_size('ov_master.c', 'nv_current.c') compare_size('vold', 'vnew') r('git checkout ${pr_branch}') // we are on the PR branch again hline(' Measuring at PR branch: ${pr_branch}, commit: ${gcommit()} ...') if compare_prod { vcompare('./vold_prod', './vnew_prod') } else { vcompare('./vold', './vnew') } println('Done. Total time: ${(time.now() - start).seconds()} s.') hline('Final summary for file diff sizes on their own branches:') compare_size('ohw_master.c', 'nhw_current.c') compare_size('ohw_master_gcc.c', 'nhw_current_gcc.c') compare_size('ov_master.c', 'nv_current.c') compare_size('vold', 'vnew') if compare_prod { compare_size('vold_prod', 'vnew_prod') } hline('Final summary for file diff sizes for generated files on the *current* branch:') compare_size('ohw.c', 'nhw.c') compare_size('ov.c', 'nv.c') compare_size('ohw.exe', 'nhw.exe') compare_size('ov.exe', 'nv.exe') // After all the measurements are done, delete all the generated temporary files, // except the `vold` and `vnew` compilers, so that they can be used later in manual // experiments: if cleanup_tmp { r('rm -rf ohw* nhw* nv* ov*') } } ================================================ FILE: .github/workflows/compile_discordv.sh ================================================ #!/usr/bin/env bash set -e function show() { printf "\u001b[35m$1\u001b[0m\n" } rm -rf discord/ show "Clone https://github.com/vcv88/discord.v" v retry -- git clone --filter=blob:none --quiet https://github.com/vcv88/discord.v discord/ cd discord/ show "Checkout last known good commit" git checkout ce9ff457fce92d5bb15df2974440cd8292457ee0 show "Execute Tests" v test . cd .. rm -rf discord/ ================================================ FILE: .github/workflows/compile_herolib.sh ================================================ #!/usr/bin/env bash set -e function show() { printf "\u001b[35m$1\u001b[0m\n" } rm -rf herolib/ show "Clone https://github.com/freeflowuniverse/herolib" v retry -- git clone --filter=blob:none --quiet https://github.com/freeflowuniverse/herolib herolib cd herolib git checkout development mkdir -p ~/.vmodules/freeflowuniverse ln -s $(pwd)/lib ~/.vmodules/freeflowuniverse/herolib cd cli show "Checkout last known good commit" git checkout ca8799af39228a5678a7be81128c5b0c342c9efc v wipe-cache show "Build project no parallel (gcc)" v -cc gcc -cg -enable-globals -w -n hero.v show "Checking build" ls -l ./hero v wipe-cache show "Build project no parallel (clang)" v -cc clang -cg -enable-globals -w -n hero.v show "Checking build" ls -l ./hero v wipe-cache show "Build project with -parallel-cc (clang)" v -cc clang -cg -enable-globals -parallel-cc -w -n hero.v show "Checking gcc build" ls -l ./hero v wipe-cache show "Build project with -parallel-cc (gcc)" v -cc gcc -cg -enable-globals -parallel-cc -w -n hero.v show "Checking clang build" ls -l ./hero rm -rf ../../herolib ================================================ FILE: .github/workflows/compile_shaders_in_examples.sh ================================================ #!/usr/bin/env bash for f in examples/sokol/*/ ; do echo "compiling shaders for $f ..."; time ./v shader $f; echo "done"; done; ================================================ FILE: .github/workflows/compile_v_with_vtcc.sh ================================================ #!/usr/bin/env bash set -ex function show() { printf "\u001b[35m$1\u001b[0m\n" } show "Prepare" rm -rf vtcc/ show "Clone vtcc" .github/workflows/retry.sh git clone https://github.com/felipensp/vtcc --branch stable --quiet vtcc/ du -s vtcc/ ## TODO: just `./v vtcc`, later will cause V, to detect the compiler as tcc (which it is), and add `-fwrapv`, which causes the vtcc compiler to panic currently show "Compile vtcc" cd vtcc/ v run make.vsh cd .. ls -la vtcc/vtcc ./vtcc/vtcc --version show "Generate the C file, for the current V version" ./v -o vlang.c cmd/v ls -la vlang.c show "Compile the C file with vtcc" ./vtcc/vtcc -o v_compiled_with_vtcc vlang.c -lpthread ls -la v_compiled_with_vtcc show "Test the resulting V compiler" ./v_compiled_with_vtcc version show "Compile and run hello with vtcc" ./v_compiled_with_vtcc -cc vtcc/vtcc -showcc run examples/hello_world.v show "Remove the generated temporary files, so the script can be re-run cleanly" rm -rf v_compiled_with_vtcc vlang.c vtcc/ ================================================ FILE: .github/workflows/compile_vlang_gui_examples.sh ================================================ #!/usr/bin/env bash set -e function show() { printf "\u001b[35m$1\u001b[0m\n" } rm -rf ~/.vmodules/gui/ export VJOBS=1 show "Clone https://github.com/vlang/gui" v retry -- git clone --filter=blob:none --quiet https://github.com/vlang/gui ~/.vmodules/gui/ show "Checkout last known good commit" git -C ~/.vmodules/gui/ checkout b4e3716b042ee6352efedff64c5b92cbf0e81ded show "Check module for syntax and semantic errors" v -shared -check ~/.vmodules/gui show "Execute Tests" v test ~/.vmodules/gui/ show "Compile Examples" v should-compile-all -no-parallel ~/.vmodules/gui/examples/ rm -rf ~/.vmodules/gui/ ================================================ FILE: .github/workflows/cross_ci.yml ================================================ name: Cross CI on: push: paths-ignore: - '**.md' - '**.yml' - '!**/cross_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**/cross_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' concurrency: group: cross-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: cross-macos: runs-on: macos-latest timeout-minutes: 20 env: VFLAGS: -cc clang steps: - uses: actions/checkout@v6 with: fetch-depth: 10 - name: Build V run: make -j4 && ./v symlink - name: Install dependencies run: | ./v retry -- brew install mingw-w64 export LIBRARY_PATH="$LIBRARY_PATH:/usr/local/opt/openssl/lib/" - name: Test symlink run: ./v symlink - name: Cross-compilation to Linux run: | ./v -os linux cmd/v # TODO: fix this: ./v -os linux examples/2048/2048.v - name: Cross-compilation of veb app to Linux with -d use_openssl run: ./v -d use_openssl -os linux examples/veb/veb_example.v - name: Cross-compilation to Windows run: | ./v -os windows cmd/v ./v -os windows examples/2048/2048.v cross-linux: runs-on: ubuntu-24.04 timeout-minutes: 20 env: VFLAGS: -cc tcc -no-retry-compilation steps: - uses: actions/checkout@v6 with: fetch-depth: 10 - name: Build v run: make -j4 && ./v symlink - name: Install dependencies run: | .github/workflows/disable_azure_mirror.sh ./v retry -- sudo apt update -y -qq ./v retry -- sudo apt install --quiet -y mingw-w64 wine wine64 winetricks libssl-dev sqlite3 libsqlite3-dev - name: Show diagnostics for wine run: | which wine # shellcheck disable=SC2046 ls -la $(realpath $(which wine)) - name: v.c can be compiled and run with -os cross run: | ./v -os cross -o /tmp/v.c cmd/v gcc -g -std=gnu11 -w -o v_from_vc /tmp/v.c -lm -lpthread ls -lart v_from_vc ./v_from_vc version - name: v_win.c can be compiled and run with -os windows run: | ./v -cc msvc -os windows -o /tmp/v_win.c cmd/v x86_64-w64-mingw32-gcc /tmp/v_win.c -std=c99 -w -municode -o v_from_vc.exe -lws2_32 ls -lart v_from_vc.exe wine ./v_from_vc.exe version - name: hello_world.v can be cross compiled to hello_world.exe run: | ./v -os windows examples/hello_world.v ls -lart examples/hello_world.exe wine examples/hello_world.exe - name: 2048.v can be cross compiled to 2048.exe run: | ./v -os windows examples/2048/2048.v ls -lart examples/2048/2048.exe cross-windows: runs-on: windows-2025 timeout-minutes: 20 steps: - uses: actions/checkout@v6 - name: Build run: | echo %VFLAGS% echo $VFLAGS .\make.bat -msvc - name: TODO v_win.c can be compiled and run with -os windows run: | .\v.exe -os windows -cc msvc -showcc -o v2.exe cmd\v .\v.exe -os windows -cc msvc -o v_win.c cmd\v dir v2.exe dir v_win.c .\v2.exe version ================================================ FILE: .github/workflows/debug.yml ================================================ name: Debug CI on: [workflow_dispatch] jobs: debug-msvc: runs-on: windows-2025 timeout-minutes: 121 env: VFLAGS: -cc msvc steps: - uses: actions/checkout@v6 - name: Build run: | echo %VFLAGS% echo $VFLAGS .\make.bat -msvc .\v.exe -cflags /WX self - name: Install dependencies run: | .\v.exe setup-freetype .\.github\workflows\windows-install-sqlite.bat - name: v doctor run: ./v doctor - name: Verify `v test` works run: | ./v cmd/tools/test_if_v_test_system_works.v ./cmd/tools/test_if_v_test_system_works - name: All code is formatted run: ./v -silent test-cleancode - name: Self tests run: ./v -silent test-self - name: Test v->js run: ./v -o hi.js examples/js_hello_world.v && node hi.js - name: Test v binaries run: ./v build-vbinaries - name: Build examples run: ./v -silent build-examples - name: v2 self compilation run: .\v.exe -o v2.exe cmd/v && .\v2.exe -o v3.exe cmd/v ================================================ FILE: .github/workflows/disable_azure_mirror.sh ================================================ #!/bin/bash echo "APT MIRRORS BEFORE:"; cat /etc/apt/apt-mirrors.txt sudo sed -i 's@http://azure.archive.ubuntu.com@http://archive.ubuntu.com@gm' /etc/apt/apt-mirrors.txt echo "APT MIRRORS AFTER:"; cat /etc/apt/apt-mirrors.txt echo "ls -la /etc/apt/sources.list.d/"; ls -la /etc/apt/sources.list.d/ for f in /etc/apt/sources.list.d/*; do echo "####### $f ######"; cat $f; done echo "APT SOURCES BEFORE:"; echo "ls -la /etc/apt/sources.list"; ls -la /etc/apt/sources.list; cat /etc/apt/sources.list sudo sed -i 's@http://azure.archive.ubuntu.com@http://archive.ubuntu.com@gm' /etc/apt/sources.list echo "APT SOURCES AFTER:"; echo "ls -la /etc/apt/sources.list"; ls -la /etc/apt/sources.list; cat /etc/apt/sources.list ================================================ FILE: .github/workflows/docker_ci.yml ================================================ name: Docker CI on: push: paths-ignore: - '**.md' - '**.yml' - '!**/docker_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**/docker_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' concurrency: group: docker-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true env: V_CI_MUSL: 1 jobs: docker-alpine-musl-gcc: runs-on: ubuntu-24.04 timeout-minutes: 241 container: image: thevlang/vlang:alpine-build env: VFLAGS: -cc gcc volumes: - ${{github.workspace}}:/opt/vlang steps: - name: Checkout uses: actions/checkout@v6 - name: Show Environment run: | echo "PWD:" pwd echo "ENVIRONMENT:" env echo "C Compiler:" gcc --version - name: Add dependencies run: apk add libc6-compat gcompat gc gc-dev binutils diffutils elfutils - name: Build V run: CC=gcc make - name: All code is formatted run: ./v -silent test-cleancode - name: Run only essential tests run: VTEST_JUST_ESSENTIAL=1 ./v -silent test-self docker-alpine-musl-tcc: runs-on: ubuntu-24.04 timeout-minutes: 241 container: image: thevlang/vlang:alpine-build volumes: - ${{github.workspace}}:/opt/vlang steps: - name: Checkout uses: actions/checkout@v6 - name: Add dependencies run: apk add musl-dev libatomic_ops-dev libatomic openssl libc6-compat gcompat gc gc-dev binutils diffutils elfutils - name: Build V run: make - name: Check if vpm compiles with tcc run: ./v -show-c-output -showcc -no-retry-compilation -cc tcc cmd/tools/vpm - name: Run only builtin and math tests run: ./v test vlib/builtin docker-ubuntu-musl: runs-on: ubuntu-24.04 timeout-minutes: 121 container: image: thevlang/vlang:ubuntu-build env: V_CI_UBUNTU_MUSL: 1 VFLAGS: -cc musl-gcc -gc none volumes: - ${{github.workspace}}:/opt/vlang steps: - name: Checkout uses: actions/checkout@v6 - name: Build V run: echo "$VFLAGS" && make -j4 && ./v -cg -o v cmd/v - name: Verify `v test` works run: | echo "$VFLAGS" ./v cmd/tools/test_if_v_test_system_works.v ./cmd/tools/test_if_v_test_system_works - name: Add dependencies run: apt install libsqlite3-dev - name: All code is formatted run: ./v -silent test-cleancode - name: Test V fixed tests run: ./v -silent test-self vlib ================================================ FILE: .github/workflows/docs_ci.yml ================================================ name: Docs CI ### Run on *EVERY* .v or .md related commit. ### The documentation *SHOULD* stay valid, and the developers should receive ### early warning, if they break it. on: push: paths-ignore: - '**.yml' - '!**/docs_ci.yml' - 'cmd/tools/vrepl.v' pull_request: paths-ignore: - '**.yml' - '!**/docs_ci.yml' - 'cmd/tools/vrepl.v' concurrency: group: docs-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: check-markdown: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - uses: actions/checkout@v6 - name: Build V run: make - name: Install dependencies (some examples show how to use sqlite and the x11 clipboard) run: ./v retry -- sudo apt install --quiet -y libx11-dev libssl-dev sqlite3 libsqlite3-dev - name: Check markdown line length & code examples run: ./v check-md -hide-warnings . ## NB: -hide-warnings is used here, so that the output is less noisy, ## thus real errors are easier to spot. report-missing-fn-doc: runs-on: ubuntu-24.04 timeout-minutes: 5 env: MOPTIONS: --diff --deprecated --relative-paths --exclude /vlib/v/ --exclude /vlib/v2/ --exclude /builtin/linux_bare/ --exclude /testdata/ --exclude /tests/ --exclude /vlib/sokol/ --exclude /vlib/x/ steps: - uses: actions/checkout@v6 - name: Build V run: make - name: Checkout previous v uses: actions/checkout@v6 with: repository: vlang/v ref: master path: pv - name: Check against parent commit run: | # shellcheck disable=SC2086 ./v missdoc $MOPTIONS pv/vlib vlib report-missing-dots-in-doc-comments: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - uses: actions/checkout@v6 - name: Build V run: make - name: Check doc comment dots for some key modules run: ./v run cmd/tools/find_doc_comments_with_no_dots.v \ vlib/builtin/ vlib/arrays/ vlib/flag/ \ vlib/bitfield/ vlib/term/ vlib/strings/ \ vlib/rand/ vlib/compress/ vlib/clipboard/ \ vlib/time/ \ vlib/os report-wrong-examples-in-doc-comments: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - uses: actions/checkout@v6 - name: Build V run: make - name: Check examples in the doc comments for all vlib modules run: VJOBS=1 ./v doc -check-examples -f none vlib/ ================================================ FILE: .github/workflows/download_full_toml_test_suites.sh ================================================ #!/usr/bin/env bash set -ex rm -rf vlib/toml/tests/testdata/iarna vlib/toml/tests/testdata/toml_rs vlib/toml/tests/testdata/toml_lang vlib/toml/tests/testdata/large_toml_file_test.toml ./v retry -- ./v download -o vlib/toml/tests/testdata/large_toml_file_test.toml https://gist.githubusercontent.com/Larpon/89b0e3d94c6903851ff15559e5df7a05/raw/62a1f87a4e37bf157f2e0bfb32d85d840c98e422/large_toml_file_test.toml ./v retry -- git clone -n https://github.com/iarna/toml-spec-tests.git vlib/toml/tests/testdata/iarna git -C vlib/toml/tests/testdata/iarna checkout 1880b1a ./v retry -- git clone -n https://github.com/toml-lang/toml-test.git vlib/toml/tests/testdata/toml_lang git -C vlib/toml/tests/testdata/toml_lang checkout 229ce2e # A few history notes of toml-rs (previously alexcrichton): # commit 7f5472c the test-suite dir moves to the crates/ sub-directory # commit 8461f7c *a lot* of test files are removed in *hope* that they are covered by the compliance test suite (assumed to be BurntSushi/toml-test, later toml-lang/toml-test) # commit 9bd454c the last known good commit we can test against ./v retry -- git clone -n https://github.com/toml-rs/toml.git vlib/toml/tests/testdata/toml_rs git -C vlib/toml/tests/testdata/toml_rs reset --hard 9bd454c ================================================ FILE: .github/workflows/find_openssl.bat ================================================ @echo off setlocal EnableDelayedExpansion REM Find every openssl.exe reachable through PATH: for /f "delims=" %%F in ('where openssl 2^>nul') do ( set "OPENSSL_DIR=%%~dpF" echo OpenSSL lives in: "!OPENSSL_DIR!" goto :end ) echo OpenSSL not found in: "!PATH!" :end ================================================ FILE: .github/workflows/freebsd_ci.yml ================================================ name: CI FreeBSD on: workflow_dispatch: push: paths-ignore: - '**.md' - '**.yml' - 'cmd/tools/**' - '!**/freebsd_ci.yml' - '!ci/freebsd_ci.vsh' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - 'cmd/tools/**' - '!**/freebsd_ci.yml' - '!ci/freebsd_ci.vsh' - '!cmd/tools/builders/**.v' ### See https://github.com/cross-platform-actions/action ### for a description of the used fields here jobs: tcc-freebsd: runs-on: ubuntu-latest timeout-minutes: 20 steps: - uses: actions/checkout@v6 - name: Tests on FreeBSD with tcc id: tests-freebsd-tcc uses: cross-platform-actions/action@v0.32.0 with: operating_system: freebsd version: '15.0' memory: 4G shell: sh sync_files: runner-to-vm run: | sudo pkg install -y git sqlite3 gmake boehm-gc-threaded libiconv # Install DB packages needed to build examples sudo pkg install -y mariadb118-client postgresql18-client # Install packages needed by Sokol to build examples sudo pkg install -y alsa-lib libglvnd libXi libXcursor # Mandatory: hostname not set in VM => some tests fail sudo hostname -s freebsd-ci echo "### OS infos" uname -a git config --global --add safe.directory . echo "### Build V" gmake sudo ./v symlink export VTEST_SHOW_LONGEST_BY_RUNTIME=3 export VTEST_SHOW_LONGEST_BY_COMPTIME=3 export VTEST_SHOW_LONGEST_BY_TOTALTIME=3 export VFLAGS='-cc tcc -no-retry-compilation' ./v run ci/freebsd_ci.vsh all clang-freebsd: runs-on: ubuntu-latest timeout-minutes: 20 steps: - uses: actions/checkout@v6 - name: Tests on FreeBSD with clang id: tests-freebsd-clang uses: cross-platform-actions/action@v0.32.0 with: operating_system: freebsd version: '15.0' memory: 4G shell: sh sync_files: runner-to-vm run: | sudo pkg install -y git sqlite3 gmake boehm-gc-threaded libiconv # Install DB packages needed to build examples sudo pkg install -y mariadb118-client postgresql18-client # Install packages needed by Sokol to build examples sudo pkg install -y alsa-lib libglvnd libXi libXcursor # Mandatory: hostname not set in VM => some tests fail sudo hostname -s freebsd-ci echo "### OS infos" uname -a git config --global --add safe.directory . echo "### Build V" gmake sudo ./v symlink export VTEST_SHOW_LONGEST_BY_RUNTIME=3 export VTEST_SHOW_LONGEST_BY_COMPTIME=3 export VTEST_SHOW_LONGEST_BY_TOTALTIME=3 export VFLAGS='-cc clang' ./v run ci/freebsd_ci.vsh all gcc-freebsd: runs-on: ubuntu-latest timeout-minutes: 20 steps: - uses: actions/checkout@v6 - name: Tests on FreeBSD with gcc id: tests-freebsd-gcc uses: cross-platform-actions/action@v0.32.0 with: operating_system: freebsd version: '15.0' memory: 4G shell: sh sync_files: runner-to-vm run: | sudo pkg install -y git sqlite3 gmake boehm-gc-threaded libiconv gcc # Install DB packages needed to build examples sudo pkg install -y mariadb118-client postgresql18-client # Install packages needed by Sokol to build examples sudo pkg install -y alsa-lib libglvnd libXi libXcursor # Mandatory: hostname not set in VM => some tests fail sudo hostname -s freebsd-ci echo "### OS infos" uname -a git config --global --add safe.directory . echo "### Build V" gmake sudo ./v symlink export VTEST_SHOW_LONGEST_BY_RUNTIME=3 export VTEST_SHOW_LONGEST_BY_COMPTIME=3 export VTEST_SHOW_LONGEST_BY_TOTALTIME=3 export VFLAGS='-cc gcc' ./v run ci/freebsd_ci.vsh all ================================================ FILE: .github/workflows/gen_vc_ci.yml ================================================ name: VC gen on: workflow_dispatch: pull_request: paths-ignore: - '**.vv' - '**.out' - '**.md' - '**.yml' - '!**/gen_vc_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' push: paths-ignore: - '**.vv' - '**.out' - '**.md' - '**.yml' - '!**/gen_vc_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. concurrency: group: gen_vc-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ !contains(github.ref, 'master')}} jobs: build-vc: runs-on: ubuntu-latest timeout-minutes: 20 steps: - uses: actions/checkout@v6 - name: Build V run: make -j4 - name: Regenerate v.c and v_win.c run: | git config --global user.email "vlang-bot@users.noreply.github.com" git config --global user.name "vlang-bot" COMMIT_HASH="$(git rev-parse HEAD)" COMMIT_MSG="$(git log -1 --oneline --pretty='%s' HEAD)" rm -rf vc ./v retry -- git clone --depth=1 "https://vlang-bot:${{ secrets.VLANG_BOT_SECRET }}@github.com/vlang/vc.git" rm -rf vc/v.c vc/v_win.c ./v -o vc/v.c -cross cmd/v ./v -o vc/v_win.c -os windows -cc msvc cmd/v sed -i "1s/^/#define V_COMMIT_HASH \"$COMMIT_HASH\"\n/" vc/v.c sed -i "1s/^/#define V_COMMIT_HASH \"$COMMIT_HASH\"\n/" vc/v_win.c # do some sanity checks for the generated v.c file: grep 'Turned ON custom defines: no_backtrace,cross' vc/v.c grep '#define CUSTOM_DEFINE_cross' vc/v.c # ensure the generated C files for the compiler, are over 5000 lines long, as a safety measure [ "$(wc -l < vc/v.c)" -gt 5000 ] [ "$(wc -l < vc/v_win.c)" -gt 5000 ] git -C vc add v.c v_win.c git -C vc commit -m "[v:master] $COMMIT_HASH - $COMMIT_MSG" # in case there are recent commits: ./v retry -- git -C vc pull --rebase origin master git -C vc log -3 - name: Deploy if: github.event_name == 'push' && github.repository == 'vlang/v' && github.ref == 'refs/heads/master' run: git -C vc push || true ================================================ FILE: .github/workflows/gg_regressions_ci.yml ================================================ name: Graphics CI on: push: paths: - 'vlib/**' - 'thirdparty/**' - 'cmd/tools/builders/**.v' - '**/gg_regressions_ci.yml' - '!**.md' pull_request: paths: - 'vlib/**' - 'thirdparty/**' - 'cmd/tools/builders/**.v' - '**/gg_regressions_ci.yml' - '!**.md' concurrency: group: gg-regressions-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: gg-regressions: runs-on: ubuntu-24.04 timeout-minutes: 20 env: VFLAGS: -cc tcc DISPLAY: :99 LIBGL_ALWAYS_SOFTWARE: true VTMP: /tmp steps: - name: Checkout V uses: actions/checkout@v6 - name: Build local v run: make -j4 && ./v symlink - name: Clear module cache run: ./v wipe-cache - name: Setup dependencies run: | # imagemagick : convert, mogrify # xvfb : xvfb # openimageio-tools : idiff # libxcursor-dev libxi-dev : V gfx deps # libgl1-mesa-dri : For headless rendering / software DRI driver (LIBGL_ALWAYS_SOFTWARE=true) # freeglut3-dev : Fixes graphic apps compilation with tcc # libx11-dev : X11 headers for clipboard and sokol (default backend on Linux) .github/workflows/disable_azure_mirror.sh ./v retry -- sudo apt update ./v retry -- sudo apt install imagemagick openimageio-tools libgl1-mesa-dri xvfb libxcursor-dev libxi-dev libxrandr-dev freeglut3-dev xsel xclip libx11-dev libegl-dev ./v retry -- ./v download https://raw.githubusercontent.com/tremby/imgur.sh/c98345d/imgur.sh ./v retry -- git clone https://github.com/Larpon/gg-regression-images gg-regression-images chmod +x ./imgur.sh - name: Sample and compare id: compare continue-on-error: true run: | Xvfb "$DISPLAY" -screen 0 1280x1024x24 -fbdir /var/tmp/ & sleep 2; while [ ! -f /var/tmp/Xvfb_screen0 ]; do sleep 0.5; done # give xvfb time to start, even on slow CI runs sleep 5; ./v gret -t ./gg-regression-images/vgret.v_examples.toml -v ./gg-sample_images ./gg-regression-images - name: Upload regression to imgur if: steps.compare.outcome != 'success' run: | ./imgur.sh /tmp/fail.png ./imgur.sh /tmp/diff.png exit 1 ================================================ FILE: .github/workflows/gh_restart_failed.v ================================================ import os import json import term import time const c = term.colorize const tg = term.green const tm = term.magenta const tb = term.bold struct Check { name string bucket string state string link string workflow string } fn (c Check) is_failed() bool { return c.bucket == 'fail' || c.state in ['FAILURE', 'TIMED_OUT'] } fn (c Check) is_cancelled() bool { return c.bucket == 'cancel' || c.state == 'CANCELLED' } struct GhCheckRun { name string status string conclusion string html_url string @[json: html_url] } struct GhCheckRunsResponse { check_runs []GhCheckRun @[json: check_runs] } fn main() { unbuffer_stdout() arg := os.args[1] or { println('Usage: v run gh_restart_failed.v ') return } is_pr := arg.len < 6 && arg.bytes().all(it.is_digit()) checks := if is_pr { get_checks_for_pr(arg.int()) } else { get_checks_for_commit(arg) } mut failed := []Check{} mut cancelled := []Check{} mut succeeded := 0 mut in_progress := 0 for check in checks { if check.is_failed() { failed << check } else if check.is_cancelled() { cancelled << check } else if check.bucket == 'pass' || check.state == 'SUCCESS' { succeeded++ } else { in_progress++ } } mut to_restart := []Check{} to_restart << failed to_restart << cancelled mut restarted_count := 0 if to_restart.len > 0 { println('Found ${to_restart.len} failed or cancelled jobs:') for job in to_restart { println('- ${job.workflow} / ${job.name} (${job.state})') } println('\n' + c(tg, 'Do you want to restart these ${to_restart.len} jobs? [y/N]: ')) if os.input('').to_lower().trim_space() == 'y' { println('') for job in to_restart { run_id, job_id := parse_ids(job.link) if run_id == '' || job_id == '' { println('Could not parse IDs from link: ${job.link} (Skipping)') continue } print('Restarting ${job.name} (Run: ${run_id}, Job: ${job_id})... ') res := execute_with_progress('gh run rerun ${run_id} --job ${job_id}') if res.exit_code == 0 { restarted_count++ } else { println(' Error: ${res.output.trim_space()}') } } } else { println('Aborted restart.') } } else { println('No failed or cancelled jobs found.') } println('\n' + c(tg, 'Summary:')) println('Total jobs: ${m(checks.len)}') println('Failed: ${m(failed.len)}') println('Cancelled: ${m(cancelled.len)}') println('Succeeded: ${m(succeeded)}') println('In Progress: ${m(in_progress)}') println('Restarted: ${m(restarted_count)}') } fn m(n int) string { return c(tb, n.str()) } fn parse_ids(link string) (string, string) { parts := link.split('/') runs_idx := parts.index('runs') job_idx := parts.index('job') mut run_id := '' mut job_id := '' if runs_idx != -1 && runs_idx + 1 < parts.len { run_id = parts[runs_idx + 1] } if job_idx != -1 && job_idx + 1 < parts.len { job_id = parts[job_idx + 1] } return run_id, job_id } fn get_checks_for_pr(pr_number int) []Check { println(c(tg, 'Fetching checks for PR ${m(pr_number)}...')) res := execute_with_progress('gh pr checks ${pr_number} --json name,bucket,state,link,workflow') if res.exit_code != 0 { println('Error: ${res.output}') exit(1) } return json.decode([]Check, res.output) or { exit(1) } } fn get_checks_for_commit(commit string) []Check { println(c(tg, 'Fetching checks for ref ${c(tb, commit)}...')) res := execute_with_progress('gh api repos/:owner/:repo/commits/${commit}/check-runs?per_page=100') if res.exit_code != 0 { println('Error: ${res.output}') exit(1) } resp := json.decode(GhCheckRunsResponse, res.output) or { exit(1) } mut checks := []Check{} for cr in resp.check_runs { checks << Check{ name: cr.name bucket: if cr.conclusion == 'failure' { 'fail' } else if cr.conclusion == 'cancelled' { 'cancel' } else if cr.conclusion == 'success' { 'pass' } else { 'pending' } state: if cr.conclusion != '' { cr.conclusion.to_upper() } else { cr.status.to_upper() } link: cr.html_url workflow: 'Actions' } } return checks } fn execute_with_progress(cmd string) os.Result { start := time.now() mut stop := false spawn fn (cmd string, start time.Time, mut stop &bool) { start_str := start.hhmmss() for !*stop { elapsed := time.since(start).seconds() print('\rRunning ${c(tm, cmd)} [${start_str}] ... ${elapsed:.1f}s') os.flush() time.sleep(100 * time.millisecond) } }(cmd, start, mut &stop) res := os.execute(cmd) elapsed := time.since(start).seconds() stop = true time.sleep(100 * time.millisecond) status := if res.exit_code == 0 { 'OK' } else { 'Failed' } print('\r') println('Command ${c(tm, cmd)} done in ${elapsed:.1f}s. ${status}') return res } ================================================ FILE: .github/workflows/hub_docker_ci.yml ================================================ name: hub_docker_ci ### NB: avoid caching things here, since the action is rare (once per week), ### and the potential benefits are less than the complexity of debugging ### cache invalidation issues... ## Trigger on both new release tags, and on weekly tags. ## Allow for manual override too: on: workflow_dispatch: push: tags: - '[0-9].[0-9]+.[0-9]+' - 'weekly.*' concurrency: group: 'hub_docker_ci-${{ github.ref }}' cancel-in-progress: true jobs: publish-new-docker-images: strategy: matrix: os: [debian, alpine] runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 with: repository: 'vlang/docker' - name: Set up QEMU uses: docker/setup-qemu-action@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 - name: Login to hub.docker.com uses: docker/login-action@v4 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Create & bootstrap persistent builder run: | docker buildx create --name gh-builder --driver docker-container --use docker buildx inspect --bootstrap - name: generate tags conditionally id: gen_tags run: | if [[ "${{ matrix.os }}" == 'debian' ]]; then echo 'TAGS=thevlang/vlang:latest,thevlang/vlang:${{ matrix.os }}' >> "$GITHUB_OUTPUT" else echo 'TAGS=thevlang/vlang:${{ matrix.os }}' >> "$GITHUB_OUTPUT" fi - uses: docker/build-push-action@v7 name: Build and deploy v image with: builder: gh-builder context: . platforms: linux/amd64,linux/arm64 tags: ${{ steps.gen_tags.outputs.TAGS }} file: docker/vlang/Dockerfile.${{ matrix.os }} push: true build-args: 'USER=thevlang' ## cache-from: type=registry,ref=thevlang/vlang:${{ matrix.os }}-buildcache ## cache-to: type=registry,ref=thevlang/vlang:${{ matrix.os }}-buildcache,mode=max - uses: docker/build-push-action@v7 name: Build and deploy developer build with: builder: gh-builder context: . platforms: linux/amd64,linux/arm64 tags: thevlang/vlang:${{ matrix.os }}-dev file: docker/vlang/Dockerfile.${{ matrix.os }}.dev-full push: true build-args: 'USER=thevlang' ## cache-from: type=registry,ref=thevlang/vlang:${{ matrix.os }}-dev-buildcache ## cache-to: type=registry,ref=thevlang/vlang:${{ matrix.os }}-dev-buildcache,mode=max ================================================ FILE: .github/workflows/linux_ci.yml ================================================ name: CI Linux on: workflow_dispatch: push: paths-ignore: - '**.md' - '**.yml' - '!**/linux_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**/linux_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' concurrency: group: linux-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: tcc-linux: runs-on: ubuntu-24.04 timeout-minutes: 121 env: VFLAGS: -cc tcc -no-retry-compilation VTEST_SHOW_LONGEST_BY_RUNTIME: 3 VTEST_SHOW_LONGEST_BY_COMPTIME: 3 VTEST_SHOW_LONGEST_BY_TOTALTIME: 3 steps: - uses: actions/checkout@v6 - name: Build v run: make -j4 && ./v symlink - name: Build v with -prealloc run: v run ci/linux_ci.vsh build_v_with_prealloc - name: All code is formatted run: v run ci/linux_ci.vsh all_code_is_formatted_tcc - name: Install dependencies for examples and tools run: v run ci/linux_ci.vsh install_dependencies_for_examples_and_tools_tcc - name: Test v->c run: v run ci/linux_ci.vsh test_v_to_c_tcc - name: v self compilation run: v run ci/linux_ci.vsh v_self_compilation_tcc - name: v doctor run: v run ci/linux_ci.vsh v_doctor_tcc - name: Verify `v test` works run: v run ci/linux_ci.vsh verify_v_test_works_tcc - name: Test pure V math module run: v run ci/linux_ci.vsh test_pure_v_math_module_tcc - name: Test inline assembly on linux run: v run ci/linux_ci.vsh test_inline_assembly - name: Self tests run: v run ci/linux_ci.vsh self_tests_tcc - name: Build examples run: v run ci/linux_ci.vsh build_examples_tcc - name: Run the submodule example, using a relative path run: v run ci/linux_ci.vsh run_submodule_example_tcc - name: Build v tools run: v run ci/linux_ci.vsh build_tools_tcc - name: Build v binaries run: v run ci/linux_ci.vsh build_vbinaries_tcc - name: Build benches run: v run ci/linux_ci.vsh build_benches_tcc - name: Run a VSH script run: v run ci/linux_ci.vsh run_vsh_script_tcc - name: Test v tutorials run: v run ci/linux_ci.vsh test_v_tutorials_tcc - name: Build cmd/tools/fast run: v run ci/linux_ci.vsh build_fast_tcc - name: V self compilation with -usecache run: v run ci/linux_ci.vsh v_self_compilation_usecache_tcc - name: Test password input run: v run ci/linux_ci.vsh test_password_input_tcc - name: Test readline run: v run ci/linux_ci.vsh test_readline_tcc - name: Test leak detector run: v run ci/linux_ci.vsh test_leak_detector_tcc - name: Test leak detector not being active for normal compile run: v run ci/linux_ci.vsh test_leak_detector_not_active_tcc - name: native cross compilation to macos run: v run ci/linux_ci.vsh native_cross_compilation_to_macos gcc-linux: runs-on: ubuntu-24.04 timeout-minutes: 121 env: VTEST_SHOW_LONGEST_BY_RUNTIME: 3 VTEST_SHOW_LONGEST_BY_COMPTIME: 3 VTEST_SHOW_LONGEST_BY_TOTALTIME: 3 steps: - uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: All code is formatted run: v run ci/linux_ci.vsh all_code_is_formatted_gcc - name: Install dependencies for examples and tools run: v run ci/linux_ci.vsh install_dependencies_for_examples_and_tools_gcc - name: Recompile V with -cstrict and gcc run: v run ci/linux_ci.vsh recompile_v_with_cstrict_gcc - name: Valgrind v.c run: v run ci/linux_ci.vsh valgrind_v_c_gcc - name: Run sanitizers run: v run ci/linux_ci.vsh run_sanitizers_gcc - name: v self compilation run: v run ci/linux_ci.vsh v_self_compilation_gcc - name: v self compilation with -usecache run: v run ci/linux_ci.vsh v_self_compilation_usecache_gcc - name: Verify `v test` works run: v run ci/linux_ci.vsh verify_v_test_works_gcc - name: Test pure V math module run: v run ci/linux_ci.vsh test_pure_v_math_module_gcc - name: Self tests run: v run ci/linux_ci.vsh self_tests_gcc - name: Self tests (-prod) run: v run ci/linux_ci.vsh self_tests_prod_gcc - name: Self tests (-cstrict) run: v run ci/linux_ci.vsh self_tests_cstrict_gcc - name: Build examples run: v run ci/linux_ci.vsh build_examples_gcc - name: Build tetris with -autofree run: v run ci/linux_ci.vsh build_tetris_autofree_gcc - name: Build blog tutorial with -autofree run: v run ci/linux_ci.vsh build_blog_autofree_gcc - name: Build option_test.c.v with -autofree run: v run ci/linux_ci.vsh build_option_test_autofree_gcc - name: V self compilation with -parallel-cc run: v run ci/linux_ci.vsh v_self_compilation_parallel_cc_gcc - name: Build modules run: v run ci/linux_ci.vsh build_modules_gcc - name: native machine code generation run: v run ci/linux_ci.vsh native_machine_code_generation_gcc - name: native cross compilation to macos run: v run ci/linux_ci.vsh native_cross_compilation_to_macos - name: compile vdoctor.v with -prod run: v run ci/linux_ci.vsh compile_vdoctor_prod_gcc - name: compile vup.v with -prod run: v run ci/linux_ci.vsh compile_vup_prod_gcc clang-linux: runs-on: ubuntu-24.04 timeout-minutes: 121 env: VFLAGS: -cc clang VTEST_SHOW_LONGEST_BY_RUNTIME: 3 VTEST_SHOW_LONGEST_BY_COMPTIME: 3 VTEST_SHOW_LONGEST_BY_TOTALTIME: 3 steps: - uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: All code is formatted run: v run ci/linux_ci.vsh all_code_is_formatted_clang - name: Install dependencies for examples and tools run: v run ci/linux_ci.vsh install_dependencies_for_examples_and_tools_clang - name: Recompile V with -cstrict and clang run: v run ci/linux_ci.vsh recompile_v_with_cstrict_clang - name: Valgrind run: v run ci/linux_ci.vsh valgrind_clang - name: Run sanitizers run: v run ci/linux_ci.vsh run_sanitizers_clang - name: v self compilation run: v run ci/linux_ci.vsh v_self_compilation_clang - name: v self compilation with -usecache run: v run ci/linux_ci.vsh v_self_compilation_usecache_clang - name: Verify `v test` works run: v run ci/linux_ci.vsh verify_v_test_works_clang - name: Test pure V math module run: v run ci/linux_ci.vsh test_pure_v_math_module_clang - name: Self tests run: v run ci/linux_ci.vsh self_tests_clang - name: Self tests (vprod) run: v run ci/linux_ci.vsh self_tests_vprod_clang - name: Self tests (-cstrict) run: v run ci/linux_ci.vsh self_tests_cstrict_clang - name: Build examples run: v run ci/linux_ci.vsh build_examples_clang - name: Build examples with -autofree run: v run ci/linux_ci.vsh build_examples_autofree_clang - name: Build modules run: v run ci/linux_ci.vsh build_modules_clang - name: native machine code generation run: v run ci/linux_ci.vsh native_machine_code_generation_clang - name: native cross compilation to macos run: v run ci/linux_ci.vsh native_cross_compilation_to_macos ================================================ FILE: .github/workflows/macos_ci.yml ================================================ name: CI macOS on: push: paths-ignore: - '**.md' - '**.yml' - '!**/macos_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**/macos_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' concurrency: group: macos-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: clang-macos: strategy: matrix: os: [macos-14] fail-fast: false runs-on: ${{ matrix.os }} timeout-minutes: 151 env: VFLAGS: -cc clang VTEST_SHOW_LONGEST_BY_RUNTIME: 3 VTEST_SHOW_LONGEST_BY_COMPTIME: 3 VTEST_SHOW_LONGEST_BY_TOTALTIME: 3 steps: - uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: Test symlink run: v run ci/macos_ci.vsh test_symlink - name: v doctor run: v run ci/macos_ci.vsh v_doctor - name: Build v with -prealloc run: v run ci/macos_ci.vsh build_v_with_prealloc - name: Test cross compilation to Linux run: v run ci/macos_ci.vsh test_cross_compilation - name: Test inline assembly on macos run: v run ci/macos_ci.vsh test_inline_assembly - name: Build V with -cstrict run: v run ci/macos_ci.vsh build_with_cstrict - name: All code is formatted run: v run ci/macos_ci.vsh all_code_is_formatted - name: Run sanitizers run: v run ci/macos_ci.vsh run_sanitizers - name: Build V using V run: v run ci/macos_ci.vsh build_using_v - name: Verify `v test` works run: v run ci/macos_ci.vsh verify_v_test_works - name: Install iconv for encoding.iconv run: v run ci/macos_ci.vsh install_iconv - name: Test pure V math module run: v run ci/macos_ci.vsh test_pure_v_math_module - name: Self tests run: v run ci/macos_ci.vsh self_tests - name: Build examples run: v run ci/macos_ci.vsh build_examples - name: Build tetris with -autofree run: v run ci/macos_ci.vsh build_tetris_autofree - name: Build blog tutorial with -autofree run: v run ci/macos_ci.vsh build_blog_autofree - name: Build examples with -prod run: v run ci/macos_ci.vsh build_examples_prod - name: Build examples with V build with tcc run: v run ci/macos_ci.vsh build_examples_v_compiled_with_tcc ## - name: V self compilation with -usecache ## run: v run ci/macos_ci.vsh v_self_compilation_usecache - name: V self compilation with -parallel-cc run: v run ci/macos_ci.vsh v_self_compilation_parallel_cc - name: Test password input run: v run ci/macos_ci.vsh test_password_input - name: Test readline run: v run ci/macos_ci.vsh test_readline ================================================ FILE: .github/workflows/make_sure_ci_run_with_32bit_compiler_test.v ================================================ fn test_ci_run_with_32bit_compiler() { $if x64 && tinyc { // TODO: uncomment that next assert when tcc32 vs tcc64 detection on windows works reliably // assert false assert true } } ================================================ FILE: .github/workflows/make_sure_ci_run_with_64bit_compiler_test.v ================================================ fn test_ci_run_with_64bit_compiler() { $if x32 { assert false } } ================================================ FILE: .github/workflows/module_docs_ci.yml ================================================ name: vlib modules CI on: pull_request: paths: - 'vlib/**.v' - 'vlib/**.md' - 'cmd/tools/vdoc/**.v' - 'cmd/tools/vdoc/theme/**.js' - 'cmd/tools/vdoc/theme/**.css' - 'cmd/tools/vdoc/theme/**.svg' - 'cmd/tools/vdoc/theme/**.html' - '**/module_docs_ci.yml' push: paths: - 'vlib/**.v' - 'vlib/**.md' - 'cmd/tools/vdoc/**.v' - 'cmd/tools/vdoc/theme/**.js' - 'cmd/tools/vdoc/theme/**.css' - 'cmd/tools/vdoc/theme/**.svg' - 'cmd/tools/vdoc/theme/**.html' - '**/module_docs_ci.yml' # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. concurrency: group: module_docs-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ !contains(github.ref, 'master')}} jobs: build-module-docs: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: Update packages, before running apt install run: .github/workflows/disable_azure_mirror.sh && v retry -- sudo apt update -y -qq - name: Install dependencies (some modules wrap C libs) run: v retry -- sudo apt install --quiet -y libpq-dev libsodium-dev libasound2-dev libssl-dev \ sqlite3 libsqlite3-dev libfreetype6-dev \ libx11-dev libxi-dev freeglut3-dev \ libgl1-mesa-dri libxcursor-dev libgl-dev libxrandr-dev libegl-dev - name: Install markdown from vpm run: v retry -- v install markdown - name: Test v doc run: VJOBS=1 ./v test cmd/tools/vdoc/ - name: Build module documentation and check the examples in the comments run: VJOBS=1 ./v doc -m -f html -unsafe-run-examples -time vlib/ - name: Deploy docs to vercel if: github.event_name == 'push' && github.repository == 'vlang/v' && github.ref == 'refs/heads/master' run: npx vercel --confirm --prod --name vmodules --token ${{ secrets.VERCEL_TOKEN }} vlib/_docs/ || true ================================================ FILE: .github/workflows/module_docs_lint.yml ================================================ name: Code CI vlib modules on: push: paths: - '**/cmd/tools/vdoc/theme/**' pull_request: paths: - '**/cmd/tools/vdoc/theme/**' jobs: lint-module-docs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Check Formatting uses: creyD/prettier_action@v4.6 with: prettier_options: --check cmd/tools/vdoc/theme ================================================ FILE: .github/workflows/more_extensive_but_slower_tests_ci.yml ================================================ name: More extensive but slower tests on: push: paths-ignore: - '**.md' - '**.yml' - '!**/more_extensive_but_slower_tests_ci.yml' - 'examples/**' - 'cmd/tools/**' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**/more_extensive_but_slower_tests_ci.yml' - 'examples/**' - 'cmd/tools/**' concurrency: group: slower_tests-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: more-tests: strategy: matrix: os: [ubuntu-latest, macos-14, windows-latest] runs-on: ${{ matrix.os }} timeout-minutes: 20 steps: - uses: actions/checkout@v6 - name: Build V if: runner.os != 'Windows' run: make -j4 && ./v symlink - name: Build V (Windows) if: runner.os == 'Windows' run: ./make.bat && ./v symlink - name: Run additional crypto tests run: | v retry -- git clone --depth 1 https://github.com/vlang/slower_tests v test slower_tests/ ================================================ FILE: .github/workflows/native_backend_ci.yml ================================================ name: native backend CI on: push: paths: - '!**' - '!**.md' - 'vlib/v/gen/native/' - 'cmd/tools/builders/**.v' - 'vlib/builtin/**.v' - 'vlib/v/ast/**.v' - 'vlib/v/scanner/**.v' - 'vlib/v/parser/**.v' - 'vlib/v/checker/**.v' - 'vlib/v/gen/c/**.v' - 'vlib/v/builder/**.v' - 'vlib/v/cflag/**.v' - 'vlib/v/live/**.v' - 'vlib/v/util/**.v' - 'vlib/v/markused/**.v' - 'vlib/v/preludes/**.v' - 'vlib/v/gen/native/**.v' - 'vlib/v/gen/native/tests/**.v' - '.github/workflows/native_backend_ci.yml' pull_request: paths: - '!**' - '!**.md' - 'vlib/v/gen/native/' - 'cmd/tools/builders/**.v' - 'vlib/builtin/**.v' - 'vlib/v/ast/**.v' - 'vlib/v/scanner/**.v' - 'vlib/v/parser/**.v' - 'vlib/v/checker/**.v' - 'vlib/v/gen/c/**.v' - 'vlib/v/builder/**.v' - 'vlib/v/cflag/**.v' - 'vlib/v/live/**.v' - 'vlib/v/util/**.v' - 'vlib/v/markused/**.v' - 'vlib/v/preludes/**.v' - 'vlib/v/gen/native/**.v' - 'vlib/v/gen/native/tests/**.v' - '.github/workflows/native_backend_ci.yml' concurrency: group: native_backend-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: native-backend-ubuntu: runs-on: ubuntu-24.04 env: VJOBS: 1 steps: - uses: actions/checkout@v6 - name: Build V run: make && ./v symlink - name: Install linker run: v retry -- sudo apt -qq install binutils - name: Rebuild V with -g, for better stacktraces on compiler panics run: v -g self - name: Run the native backend tests serially with more details run: v test vlib/v/gen/native/ native-backend-windows: runs-on: windows-2022 env: VJOBS: 1 steps: - uses: actions/checkout@v6 - name: Build V (Windows) run: ./make.bat && ./v symlink - name: Rebuild V with -g, for better stacktraces on compiler panics run: v -g self - name: Run the native backend tests serially with more details run: v test vlib/v/gen/native/ ================================================ FILE: .github/workflows/openbsd_ci.yml ================================================ name: CI OpenBSD on: workflow_dispatch: push: paths-ignore: - '**.md' - '**.yml' - 'cmd/tools/**' - '!**/openbsd_ci.yml' - '!ci/openbsd_ci.vsh' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - 'cmd/tools/**' - '!**/openbsd_ci.yml' - '!ci/openbsd_ci.vsh' - '!cmd/tools/builders/**.v' ### See https://github.com/cross-platform-actions/action ### for a description of the used fields here jobs: tcc-openbsd: runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v6 - name: Tests on OpenBSD with tcc id: tests-openbsd-tcc uses: cross-platform-actions/action@v0.32.0 with: operating_system: openbsd version: '7.8' memory: 4G shell: sh sync_files: runner-to-vm run: | sudo pkg_add git sqlite3 gmake boehm-gc libiconv # Install packages needed to build examples sudo pkg_add mariadb-client postgresql-client # Mandatory: hostname not set in VM => some tests fail sudo hostname -s openbsd-ci echo "### OS infos" uname -a git config --global --add safe.directory . echo "### Build V" gmake sudo ./v symlink export VTEST_SHOW_LONGEST_BY_RUNTIME=3 export VTEST_SHOW_LONGEST_BY_COMPTIME=3 export VTEST_SHOW_LONGEST_BY_TOTALTIME=3 export VFLAGS='-cc tcc -no-retry-compilation' ./v run ci/openbsd_ci.vsh all clang-openbsd: runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v6 - name: Tests on OpenBSD with clang id: tests-openbsd-clang uses: cross-platform-actions/action@v0.32.0 with: operating_system: openbsd version: '7.8' memory: 4G shell: sh sync_files: runner-to-vm run: | sudo pkg_add git sqlite3 gmake boehm-gc libiconv # Install packages needed to build examples sudo pkg_add mariadb-client postgresql-client # Mandatory: hostname not set in VM => some tests fail sudo hostname -s openbsd-ci echo "### OS infos" uname -a git config --global --add safe.directory . echo "### Build V" gmake sudo ./v symlink export VTEST_SHOW_LONGEST_BY_RUNTIME=3 export VTEST_SHOW_LONGEST_BY_COMPTIME=3 export VTEST_SHOW_LONGEST_BY_TOTALTIME=3 export VFLAGS='-cc clang' ./v run ci/openbsd_ci.vsh all ================================================ FILE: .github/workflows/other_ci.yml ================================================ name: Other CI on: workflow_dispatch: push: paths-ignore: - '**.md' - '**.yml' - '!**/other_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**/other_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' concurrency: group: other-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: performance-compare-with-master: runs-on: ubuntu-24.04 timeout-minutes: 30 steps: - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Environment info run: echo "$VFLAGS $GITHUB_SHA $GITHUB_REF" - name: Name the local git branch run: git checkout -b the_v_pr_branch - name: Build local v run: make && ./v symlink - name: V version run: ./v version - name: Build the repeat tool run: ./v cmd/tools/vrepeat.v - name: Run compare_pr_to_master.v run: VREPEAT_SILENT=1 ./v run .github/workflows/compare_pr_to_master.v prevent-gpl-licenses: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - name: Checkout V ${{ github.head_ref }} uses: actions/checkout@v6 with: path: v - name: Checkout V master uses: actions/checkout@v6 with: repository: vlang/v path: vmaster - name: Detect potentially added GPL licensed code run: | gpl_search_cmd="grep 'GPL' -r --exclude-dir=.git --exclude=*.yml --exclude=*.md --exclude=*.vv --exclude=*_test.v ." cd vmaster eval "$gpl_search_cmd" > ../gpl_res_vmaster cd ../v eval "$gpl_search_cmd" > ../gpl_res_vnew cd .. diff -d -a -U 2 --color=always gpl_res_vmaster gpl_res_vnew code-formatting: runs-on: ubuntu-24.04 timeout-minutes: 20 env: VFLAGS: -cc gcc steps: - uses: actions/checkout@v6 - name: Environment info run: echo "$VFLAGS $GITHUB_SHA $GITHUB_REF" - name: Build local v run: make -j4 && ./v symlink - name: v test-cleancode run: ./v -silent test-cleancode - name: v test-fmt run: ./v -silent test-fmt performance-regressions: runs-on: ubuntu-24.04 timeout-minutes: 20 env: VFLAGS: -cc gcc steps: - uses: actions/checkout@v6 - name: Environment info run: echo "$VFLAGS $GITHUB_SHA $GITHUB_REF" - name: Build local v run: make -j4 && ./v symlink - name: Clone & Build previous vmaster/v run: | ./v retry -- git clone --depth=1 https://github.com/vlang/v vmaster/ (cd vmaster; make -j4) - name: V versions run: ./v version && ./vmaster/v version - name: Build the repeat tool run: ./v cmd/tools/vrepeat.v - name: Repeat -o hw.c examples/hello_world.v run: ./v repeat --max_time 251 --series 3 --runs 20 --nmins 2 --nmaxs 5 --warmup 3 --fail_percent 10 -t 'cd {T} ; ./v -o hw.c examples/hello_world.v' . ./vmaster - name: Repeat -o v.c cmd/v run: ./v repeat --max_time 1731 --series 3 --runs 20 --nmins 2 --nmaxs 5 --warmup 3 --fail_percent 10 -t 'cd {T} ; ./v -o v.c cmd/v' . ./vmaster misc-tooling: runs-on: ubuntu-24.04 timeout-minutes: 20 env: VFLAGS: -cc tcc -no-retry-compilation steps: - uses: actions/checkout@v6 with: fetch-depth: 10 - name: Build v run: make -j4 && ./v symlink - name: Install dependencies run: | .github/workflows/disable_azure_mirror.sh ./v retry -- sudo apt update ./v retry -- sudo apt install --quiet -y libsodium-dev libssl-dev sqlite3 libsqlite3-dev postgresql libpq-dev valgrind ./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev xfonts-75dpi xfonts-base libegl-dev ./v retry -- sudo apt install --quiet -y g++-9 g++-10 - name: g++-9 version run: g++-9 --version - name: V self compilation with g++ and -std=c++11 run: ./v -cc g++-9 -no-std -cflags -std=c++11 -o v2 cmd/v && ./v2 -cc g++-9 -no-std -cflags -std=c++11 -o v3 cmd/v - name: g++-10 version run: g++-10 --version - name: V self compilation with g++ and -std=c++20 run: ./v -cc g++-10 -no-std -cflags -std=c++20 -o v2 cmd/v && ./v2 -cc g++-10 -no-std -cflags -std=c++20 -o v3 cmd/v # NB: this does not mean it runs, but at least keeps it from regressing - name: Ensure V can be compiled with -autofree run: ./v -autofree cmd/v - name: Ensure V can be compiled with -no-closures run: ./v -no-closures cmd/v - name: Shader examples can be built run: | .github/workflows/compile_shaders_in_examples.sh ./v should-compile-all examples/sokol/*.v examples/sokol/0?*/*.v parser-silent: runs-on: ubuntu-24.04 timeout-minutes: 30 steps: - uses: actions/checkout@v6 - name: Build local v run: | make -j4 && ./v symlink ./v -g -d trace_parse_stmt cmd/tools/vtest-parser.v - name: Install zzuf run: ./v retry -- sudo apt install -qq zzuf - name: Run test-parser run: | ./v test-parser --show_source --linear examples/hello_world.v ./v test-parser --show_source --linear examples/hanoi.v ./v test-parser --show_source --linear examples/fibonacci.v ./v test-parser --show_source --linear examples/cli.v ./v test-parser --show_source --linear examples/json.v ./v test-parser --show_source --linear examples/vmod.v ./v test-parser --show_source --linear examples/regex/regex_example.v ./v test-parser --show_source --linear examples/2048/2048.v - name: Run test-parser over fuzzed files run: | zzuf -R '\x00-\x20\x7f-\xff' -r0.01 < examples/hello_world.v > examples/hello_world_fuzz.v zzuf -R '\x00-\x20\x7f-\xff' -r0.01 < examples/hanoi.v > examples/hanoi_fuzz.v zzuf -R '\x00-\x20\x7f-\xff' -r0.01 < examples/fibonacci.v > examples/fibonacci_fuzz.v zzuf -R '\x00-\x20\x7f-\xff' -r0.01 < examples/cli.v > examples/cli_fuzz.v zzuf -R '\x00-\x20\x7f-\xff' -r0.01 < examples/json.v > examples/json_fuzz.v zzuf -R '\x00-\x20\x7f-\xff' -r0.01 < examples/vmod.v > examples/vmod_fuzz.v zzuf -R '\x00-\x20\x7f-\xff' -r0.01 < examples/regex/regex_example.v > examples/regex_example_fuzz.v zzuf -R '\x00-\x20\x7f-\xff' -r0.01 < examples/2048/2048.v > examples/2048/2048_fuzz.v ./v test-parser --show_source --linear examples/hello_world_fuzz.v ./v test-parser --show_source --linear examples/fibonacci_fuzz.v ./v test-parser --show_source --linear examples/hanoi_fuzz.v ./v test-parser --show_source --linear examples/cli_fuzz.v ./v test-parser --show_source --linear examples/json_fuzz.v ./v test-parser --show_source --linear examples/vmod_fuzz.v ./v test-parser --show_source --linear examples/regex_example_fuzz.v ./v test-parser --show_source --linear examples/2048/2048_fuzz.v ================================================ FILE: .github/workflows/paths_ci.yml ================================================ name: Path Testing CI on: workflow_dispatch: push: paths-ignore: - '**.md' - '**.yml' - '!**/paths_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**/paths_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' concurrency: group: paths-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: space-paths-linux: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - uses: actions/checkout@v6 with: persist-credentials: false path: '你好 my $path, @с интервали' - name: Build V run: | # shellcheck disable=SC2016 echo '你好 my $path, @с интервали' ls -la # shellcheck disable=SC2016 cd '你好 my $path, @с интервали' ls -la make - name: v doctor run: | # shellcheck disable=SC2016 cd '你好 my $path, @с интервали' ./v doctor - name: v tests run: | # shellcheck disable=SC2016 cd '你好 my $path, @с интервали' ./v test vlib/builtin vlib/os space-paths-macos: runs-on: macos-14 timeout-minutes: 30 steps: - uses: actions/checkout@v6 with: path: '你好 my $path, @с интервали' persist-credentials: false - name: Build V run: | # shellcheck disable=SC2016 echo '你好 my $path, @с интервали' ls -la # shellcheck disable=SC2016 cd '你好 my $path, @с интервали' ls -la make ## prebuild cmd/tools/builders/js_builder, to minimise the ## chances of a sporadic "Killed" when running the tests later ./v -b js run examples/hello_world.v - name: v doctor run: | # shellcheck disable=SC2016 cd '你好 my $path, @с интервали' ./v doctor - name: v tests run: | # shellcheck disable=SC2016 cd '你好 my $path, @с интервали' ./v test vlib/builtin vlib/os space-paths-windows: runs-on: windows-2022 timeout-minutes: 30 ## NB: the following paths do not work for now: ##### MY_V_PATH: '你好 my $path, @с интервали' ##### MY_V_PATH: 'path with some $punctuation, and some spaces ' ## tcc has a problem interpreting paths with non latin letters in them, ## by default, but that can be solved with passing -Bthirdparty/tcc ## but after that V fails self building with: ####### builder error: cannot write to folder ####### D:\a\v\v\你好 my $path, @с интервали: No such file or directory ## and that happens even for gcc builds, not just tcc ones steps: - uses: actions/checkout@v6 with: path: 'path with some $punctuation, and some spaces' persist-credentials: false - name: Build V run: | echo 'path with some $punctuation, and some spaces' dir cd 'path with some $punctuation, and some spaces' dir .\make.bat -tcc - name: v doctor run: | cd 'path with some $punctuation, and some spaces' ./v doctor - name: v tests run: | cd 'path with some $punctuation, and some spaces' ./v test vlib/builtin vlib/os ================================================ FILE: .github/workflows/periodic_ci.yml ================================================ name: Periodic CI on: schedule: - cron: '0 */6 * * *' push: paths: - '**/periodic_ci.yml' pull_request: paths: - '**/periodic_ci.yml' jobs: periodic-network: strategy: matrix: include: - os: ubuntu-latest cc: tcc - os: windows-latest cc: msvc - os: macos-latest cc: clang fail-fast: false runs-on: ${{ matrix.os }} if: github.event_name != 'schedule' || (github.ref == 'refs/heads/master' && github.repository == 'vlang/v') timeout-minutes: 30 env: VFLAGS: -cc ${{ matrix.cc }} V_CI_PERIODIC: 1 steps: - uses: actions/checkout@v6 - name: Build if: runner.os != 'Windows' run: make -j4 && ./v -showcc -o v cmd/v && ./v doctor - name: Build V (Windows) if: runner.os == 'Windows' run: ./make.bat -msvc && ./v -o v2.exe cmd/v && ./v2 -showcc -o v.exe cmd/v && ./v doctor - name: Test run: ./v -d network -silent test-self vlib/net ================================================ FILE: .github/workflows/prebuilt.yml ================================================ name: Test prebuilt binaries on: workflow_dispatch: release: types: [edited, published] jobs: prebuilt-linux: runs-on: ubuntu-24.04 timeout-minutes: 5 steps: - name: Download V run: | .github/workflows/retry.sh wget https://github.com/vlang/v/releases/latest/download/v_linux.zip unzip v_linux.zip cd v ./v -version - name: Test V run: | cd v ./v run examples/hello_world.v ./v -showcc -gc none -cc tcc -no-retry-compilation run examples/hello_world.v prebuilt-macos-arm64: ## macos-14 is a m1 runner runs-on: macos-14 timeout-minutes: 5 steps: - name: Download V run: | .github/workflows/retry.sh wget https://github.com/vlang/v/releases/latest/download/v_macos_arm64.zip unzip v_macos_arm64.zip cd v ./v -version - name: Test V run: | cd v ./v run examples/hello_world.v ./v -showcc -gc none -cc tcc -no-retry-compilation run examples/hello_world.v prebuilt-macos-x86_64: runs-on: macos-latest timeout-minutes: 5 steps: - name: Download V run: | .github/workflows/retry.sh wget https://github.com/vlang/v/releases/latest/download/v_macos_x86_64.zip unzip v_macos_x86_64.zip cd v ./v -version - name: Test V run: | cd v ./v run examples/hello_world.v prebuilt-windows: runs-on: windows-latest timeout-minutes: 5 steps: - name: Download V run: | curl -L https://github.com/vlang/v/releases/latest/download/v_windows.zip -o v_windows.zip unzip .\v_windows.zip cd v .\v.exe -version - name: Test V run: | cd v .\v.exe run .\examples\hello_world.v .\v.exe -showcc -gc none -cc tcc -no-retry-compilation run .\examples/hello_world.v ================================================ FILE: .github/workflows/puzzle_vibes_ci.yml ================================================ name: Shy and PV CI on: workflow_dispatch: push: paths: - 'vlib/v/checker/**.v' - 'vlib/v/gen/c/**.v' - 'thirdparty/**' - 'cmd/tools/builders/**.v' - 'cmd/tools/vshader.v' - '**/puzzle_vibes_ci.yml' - '!**_test.v' - '!**.md' pull_request: paths: - 'vlib/v/checker/**' - 'vlib/v/gen/c/**' - 'thirdparty/**' - 'cmd/tools/builders/**.v' - 'cmd/tools/vshader.v' - '**/puzzle_vibes_ci.yml' - '!**_test.v' - '!**.md' concurrency: group: puzzle_vibes-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: v-compiles-puzzle-vibes: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - uses: actions/checkout@v6 - uses: ./.github/actions/cache-apt-packages-action - name: Build V run: make && ./v symlink - name: Install & Setup SDL run: v retry -- v install sdl && v ~/.vmodules/sdl/setup.vsh - name: Install Shy run: v retry -- v install https://github.com/larpon/shy - name: Clone Puzzle Vibes run: v retry -- git clone https://github.com/larpon/puzzle_vibes/ - name: Check PV compiles with -g run: cd puzzle_vibes && v -g . - name: Check PV compiles run: cd puzzle_vibes && v . - name: Check PV compiles with -prod run: cd puzzle_vibes && v -prod -no-prod-options . - name: Check PV compiles with -prod and -g run: cd puzzle_vibes && v -prod -g -no-prod-options . ================================================ FILE: .github/workflows/release_ci.yml ================================================ name: Release CI on: workflow_dispatch: pull_request: paths: - '.github/workflows/release_ci.yml' push: paths: - '.github/workflows/release_ci.yml' tags: - weekly.** - 0.** concurrency: group: release-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.ref_type != 'tag' }} permissions: contents: write jobs: release-build: runs-on: ${{ matrix.os }} strategy: matrix: os: [ ubuntu-22.04, ubuntu-22.04-arm, macos-15-intel, macos-15, windows-latest, ] include: - os: ubuntu-22.04 cc: gcc target: linux artifact: v_linux.zip - os: ubuntu-22.04-arm cc: gcc target: linux_arm64 artifact: v_linux_arm64.zip - os: macos-15-intel cc: clang target: macos_x86_64 artifact: v_macos_x86_64.zip - os: macos-15 cc: clang target: macos_arm64 artifact: v_macos_arm64.zip - os: windows-latest cc: msvc target: windows artifact: v_windows.zip fail-fast: false steps: - uses: actions/checkout@v6 - name: Compile release binaries if: runner.os != 'Windows' run: | make ./v -cc ${{ matrix.cc }} ${{ matrix.cflags }} -prod -o v cmd/v ./v -cc ${{ matrix.cc }} ${{ matrix.cflags }} -prod cmd/tools/vup.v ./v -cc ${{ matrix.cc }} ${{ matrix.cflags }} -prod cmd/tools/vdoctor.v - name: Compile release binaries (Windows) if: runner.os == 'Windows' run: | ./make.bat -msvc ./v -prod -cc msvc -o cmd/vprod.exe cmd/v ./v -prod -cc msvc cmd/tools/vup.v ./v -prod -cc msvc cmd/tools/vdoctor.v del ./*.exe del ./*.tmp.obj move cmd/vprod.exe v.exe - name: Prepare artifact shell: bash run: | if [[ ${{ matrix.os }} == 'macos-14' ]]; then rm -rf thirdparty/tcc git clone --branch thirdparty-macos-arm64 --depth=1 https://github.com/vlang/tccbin thirdparty/tcc fi # Remove excluded if [[ $RUNNER_OS == 'Windows' ]]; then find . -type f \( -name "*.ilk" -o -name "*.pdb" \) -exec rm -rf {} + rm -rf v_old.exe fi find . -type d -name ".git" -exec rm -rf {} + rm -rf vc/ rm -rf v_old rm -rf vlib/v/tests/bench/gcboehm/*.svg.xz - name: Create ZIP archive shell: bash run: | cd .. if [[ $RUNNER_OS == 'Windows' ]]; then 7z a -tzip ${{ matrix.artifact }} v/ else zip -r9 --symlinks ${{ matrix.artifact }} v/ fi zipinfo ${{ matrix.artifact }} mv ${{ matrix.artifact }} v/ cd v/ - name: Create artifact uses: actions/upload-artifact@v7 with: name: ${{ matrix.target }} path: ${{ matrix.artifact }} release-publish: if: github.ref_type == 'tag' needs: release-build runs-on: ubuntu-latest steps: - uses: actions/download-artifact@v8 - name: Create release uses: ncipollo/release-action@v1 with: artifacts: | ~/work/v/v/windows/v_windows.zip ~/work/v/v/linux/v_linux.zip ~/work/v/v/linux_arm64/v_linux_arm64.zip ~/work/v/v/macos_arm64/v_macos_arm64.zip ~/work/v/v/macos_x86_64/v_macos_x86_64.zip tag: ${{ github.ref_name }} name: ${{ github.ref_name }} draft: false prerelease: false ================================================ FILE: .github/workflows/retry.sh ================================================ #!/usr/bin/env bash cmd=$@ function elog() { message=$1 printf "%(%Y/%m/%d %H:%M:%S)T | retry.sh $1\n" } declare -i iteration=0 declare -i max_iterations=9 for((iteration=1;iteration<=max_iterations;iteration++)); do elog "iteration: $iteration/$max_iterations, cmd: $cmd" if $cmd; then exit 0 fi elog "command failed, retrying ..."; sleep 1; done; elog "failed doing $max_iterations iterations of command: $cmd" exit 1 ================================================ FILE: .github/workflows/riscv64_linux_ci.yml ================================================ name: riscv64 CI on: workflow_dispatch: push: paths-ignore: - '**.md' - '**.yml' - '!**/riscv64_linux_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**/riscv64_linux_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' jobs: riscv64_linux: # The host should always be Linux runs-on: ubuntu-24.04 timeout-minutes: 30 name: Build on ubuntu-24.04 riscv64 steps: - uses: actions/checkout@v6 - uses: uraimo/run-on-arch-action@v3 name: Run commands id: runcmd with: arch: riscv64 distro: ubuntu24.04 base_image: --platform=linux/riscv64 riscv64/ubuntu:24.04 # The token tag here is not required, but speeds up builds, # by allowing caching of the installed dependencies, which is ~2.5min: githubToken: ${{ github.token }} shell: /bin/bash install: | apt-get update -q -y apt-get install -q -y make gcc git file coreutils binutils run: | uname -a make --version gcc --version ls -la export LDFLAGS="-latomic" export VFLAGS="-gc none -no-retry-compilation -cc cc" make file ./v ls -la ./v ./v test vlib/builtin vlib/os vlib/encoding/binary ./v test vlib/v/slow_tests/assembly VTEST_ONLY=closure ./v test vlib/v/tests ================================================ FILE: .github/workflows/run_sanitizers.sh ================================================ #!/usr/bin/env bash export PS4='\033[0;33m+ >>>>> (${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }\033[0m' set -xe echo " Setup environment ..." export DEBUG_OPTS=${DEBUG_OPTS:-"-keepc -cg -cflags -fno-omit-frame-pointer"} export VFLAGS=${VFLAGS:-"-cc clang"} v version v -show-c-output -cflags --version -e ';' || true echo " Compile and run sanitizers ..." v ${VFLAGS} ${DEBUG_OPTS} -o v2 cmd/v -cflags -fsanitize=memory UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1" ./v2 -o v.c cmd/v v ${VFLAGS} ${DEBUG_OPTS} -o v3 cmd/v -cflags -fsanitize=thread TSAN_OPTIONS="suppressions=.github/workflows/run_sanitizers_thread.suppressions" UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1" ./v3 -o v.c cmd/v v ${VFLAGS} ${DEBUG_OPTS} -o v4 cmd/v -cflags -fsanitize=undefined UBSAN_OPTIONS="suppressions=.github/workflows/run_sanitizers_undefined.suppressions:print_stacktrace=1:halt_on_error=1" ./v4 -o v.c cmd/v v ${VFLAGS} ${DEBUG_OPTS} -o v5 cmd/v -cflags -fsanitize=address,pointer-compare,pointer-subtract ASAN_OPTIONS="detect_leaks=0" UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1" ./v5 -o v.c cmd/v ================================================ FILE: .github/workflows/run_sanitizers_leak.suppressions ================================================ # websocket tests leak:mbedtls_ssl_setup # sqlite tests leak:*sqlite* # v leak:v__* leak:os__* leak:string__plus leak:malloc_uncollectable leak:new_array_from_c_array leak:_vinit ================================================ FILE: .github/workflows/run_sanitizers_thread.suppressions ================================================ ## See https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions ## and https://clang.llvm.org/docs/ThreadSanitizer.html ## The sync__stdatomic__add_i64 and sync__stdatomic__sub_i64 suppressions below, are needed for clang-10 to clang-12; clang-18 is fine without them race:sync__stdatomic__add_i64 race:sync__stdatomic__sub_i64 ================================================ FILE: .github/workflows/run_sanitizers_undefined.suppressions ================================================ ## See https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html ## Most of the supressed functions here use asserts, that in turn use an indirection through an interface. TODO: if that is solved, most of these can be removed. ## Usually they contain a __test_ in their name, but not always (see the x.ttf ones like vlib/x/ttf/ttf_test.v ). ## TODO: extract the common part of the assertions to a VDO_ function (1 for pass and 1 for failure), so that they can be whitelisted here just once. function:map_exists function:map_get function:IError_str shift-exponent:math__bits__rotate_left_64 shift-exponent:math__bits__div_64 function:math__big__Integer_general_radix_str function:math__big__Integer_div_mod_internal function:math__bits__test_bits function:math__bits__test_div_64_edge_cases function:math__test_nan alignment:rand__read_64 function:rand__internal_ulid_at_millisecond function:rand__internal_string_from_set function:rand__internal_uuid_v4 function:rand__deinit function:rand__read_internal function:rand__read_64 function:rand__PRNG_f64 function:rand__cuid2__test_cuid2 function:sync__pool__process_in_thread function:sync__Once_do_slow_with_param function:v__type_resolver__TypeResolver_resolve_fn_generic_args function:v__type_resolver__TypeResolver_unwrap_generic_expr function:v__type_resolver__TypeResolver_get_type ## these have asserts in them, and trigger due to the used indirection; TODO: remove them, when a more general solution is found for all interfaces function:x__ttf__TTF_File_get_glyph_offset function:x__ttf__TTF_File_get_horizontal_metrics function:x__ttf__TTF_File_glyph_count function:x__ttf__TTF_File_read_glyph function:x__ttf__TTF_File_read_simple_glyph function:x__ttf__TTF_File_read_kern_table function:x__ttf__TTF_File_read_hhea_table function:x__ttf__TTF_File_read_cmap_table function:x__ttf__TTF_File_read_name_table function:x__ttf__TTF_File_read_head_table function:x__ttf__TTF_File_read_offset_tables function:net__unix__select_deadline function:net__select_deadline function:net__socks__test_parse_ipv4 function:net__http__download_file_with_progress function:net__http__download_progres_cb function:net__http__check_headers function:net__http__test_str function:net__http__test_int function:net__http__test_is_valid function:net__http__test_is_error function:net__http__test_is_success function:net__http__test_parse_response_with_weird_cookie function:net__http__test_parse_response_with_cookies function:net__http__test_parse_response function:net__http__test_response_bytestr_1 function:net__http__test_response_bytestr_2 function:net__http__test_parse_large_body function:net__http__test_multipart_form_body function:net__http__test_parse_multipart_form2 function:net__http__test_parse_request_no_headers function:net__http__test_parse_multipart_form function:net__http__test_parse_form function:net__http__test_parse_request_line function:net__http__test_parse_request_body function:net__http__test_parse_request_two_header_values function:net__http__test_parse_request_no_headers function:net__http__test_parse_request_two_headers function:net__http__test_proxy_fields function:net__http__test_proxy_headers function:net__http__test_set_cookie function:net__http__test_parse_headers function:net__http__parse_headers_test function:net__http__test_header_join function:net__http__test_header_from_map function:net__http__test_custom_header_from_map function:net__http__test_render_coerce_canonicalize function:net__http__test_render_canonicalize function:net__http__test_render_version function:net__http__test_coerce_canonicalize_custom function:net__http__test_coerce_custom function:net__http__test_coerce_canonicalize function:net__http__test_coerce function:net__http__test_custom_values function:net__http__test_starting_with function:net__http__test_get_custom function:net__http__test_contains_custom function:net__http__test_custom_header function:net__http__test_delete_header function:net__http__test_header_delete_not_existing function:net__http__test_header_delete function:net__http__test_header_set function:net__http__test_header_get function:net__http__test_header_adds_multiple function:net__http__test_header_new function:net__test_ip6_str function:net__test_ip_str function:net__test_sizes_unix function:net__test_sizes_ipv4 function:net__test_sizes_ipv6 function:net__test_offsets_unix function:net__test_offsets_ipv4 function:net__test_offsets_ipv6 function:net__test_sizes_unix_sun_path function:net__test_diagnostics function:net__test_ip_port function:net__websocket__delete_client_cb function:net__websocket__Server_listen function:net__websocket__Server_serve_client function:net__websocket__Server_parse_client_handshake function:net__websocket__Client_listen function:net__websocket__Client_send_message_event function:net__websocket__Client_send_close_event function:net__websocket__Client_debug_log function:net__websocket__Client_connect function:io__BufferedReader_fill_buffer function:io__read_all function:log__info function:log__debug function:log__warn function:log__error function:log__set_level function:log__Log_log_stream function:log__free_logger function:picoev__Picoev_poll_once function:picoev__Picoev_set_timeout function:picoev__Picoev_update_events function:picoev__test_if_all_file_descriptors_are_properly_initialized function:vweb__tests__vweb_test_server__App_index function:vweb__tests__vweb_test_server__start_in_background function:vweb__RoutePair_test_param function:veb__RoutePair_test_param function:veb__test_load_files_translations ## needed for tests; TODO: move the test specific setup code into its own separate VDO_tests function, so only it can be added here function:main function:crypto__sha3__test_0_length_hash function:crypto__sha3__test_0_length_xof function:crypto__sha3__test_200_length_hash function:crypto__sha3__test_200_length_xof function:crypto__sha3__test_2_x_24_rounds_on_zero function:crypto__sha3__test_stepping_functions_on_zero function:crypto__sha3__test_zero_state function:crypto__sha3__test_rho_offsets function:crypto__sha3__test_to_from_bytes function:crypto__sha3__test_round_constants function:crypto__pem__test_decode_rfc1421 function:crypto__pem__test_decode function:crypto__pem__test_encode_rfc1421 function:crypto__pem__test_encode function:crypto__hmac__test_hmac_equal function:crypto__hmac__test_hmac_sha3_224 function:crypto__hmac__test_hmac_sha3_256 function:crypto__hmac__test_hmac_sha3_384 function:crypto__hmac__test_hmac_sha3_512 function:crypto__hmac__test_hmac_blake3_256 function:crypto__hmac__test_hmac_blake2b_160 function:crypto__hmac__test_hmac_blake2b_256 function:crypto__hmac__test_hmac_blake2b_384 function:crypto__hmac__test_hmac_blake2b_512 function:crypto__hmac__test_hmac_blake2s_128 function:crypto__hmac__test_hmac_blake2s_160 function:crypto__hmac__test_hmac_blake2s_224 function:crypto__hmac__test_hmac_blake2s_256 function:crypto__hmac__test_hmac_sha512 function:crypto__hmac__test_hmac_sha384 function:crypto__hmac__test_hmac_sha256 function:crypto__hmac__test_hmac_sha224 function:crypto__hmac__test_hmac_sha1 function:crypto__hmac__test_hmac_md5 function:crypto__ed25519__internal__edwards25519__sc_reduce function:crypto__ed25519__internal__edwards25519__sc_reduce ================================================ FILE: .github/workflows/s390x_linux_ci.yml ================================================ name: s390 CI on: workflow_dispatch: push: paths-ignore: - '**.md' - '**.yml' - '!**/s390x_linux_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**/s390x_linux_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' jobs: s390x_linux: # The host should always be Linux runs-on: ubuntu-22.04 timeout-minutes: 30 name: Build on ubuntu-22.04 s390x steps: - uses: actions/checkout@v6 - uses: uraimo/run-on-arch-action@v3 name: Run commands id: runcmd with: arch: s390x distro: ubuntu22.04 base_image: --platform=linux/s390x s390x/ubuntu:22.04 # The token tag here is not required, but speeds up builds, # by allowing caching of the installed dependencies, which is ~2.5min: githubToken: ${{ github.token }} shell: /bin/bash install: | apt-get update -q -y apt-get install -q -y make gcc git file coreutils binutils run: | uname -a make --version gcc --version ls -la make file ./v ls -la ./v ./v test vlib/builtin vlib/os vlib/encoding/binary ./v test vlib/v/tests/fns/closure_test.v ================================================ FILE: .github/workflows/sanitized_ci.yml ================================================ name: Sanitized CI ## Running these jobs is slow (over ~1 hour, sometimes even 2) ## so we run them only when there is a chance that the generated ## C code could have changed, or for some critical vlib modules, ## like `builtin`, `os`, `sync`, where they have demonstrated ## their usefulness by catching actual very hard to find bugs. ## The cost of this selective running is delayed feedback when ## there are bugs in other V modules. ## The positive is *much faster CI runs* for most V contributors, ## that make PRs that are not concerning V itself, or the critical ## V modules. on: workflow_dispatch: push: paths: - '!**' - '!**.md' - '!**.yml' - 'vlib/builtin/**.v' - 'vlib/strconv/**.v' - 'vlib/strings/**.v' - 'vlib/math/**.v' - 'vlib/math/big/**.v' - 'vlib/arrays/**.v' - 'vlib/crypto/ecdsa/**.v' - 'vlib/datatypes/**.v' - 'vlib/os/**.v' - 'vlib/sync/**.v' - 'vlib/v/tests/**.v' - 'vlib/v/ast/**.v' - 'vlib/v/scanner/**.v' - 'vlib/v/parser/**.v' - 'vlib/v/checker/**.v' - 'vlib/v/gen/c/**.v' - 'vlib/v/builder/**.v' - 'vlib/v/cflag/**.v' - 'vlib/v/live/**.v' - 'vlib/v/util/**.v' - 'vlib/v/markused/**.v' - 'vlib/v/preludes/**.v' - 'vlib/v/embed_file/**.v' - 'vlib/x/json2/**.v' - '**/sanitized_ci.yml' pull_request: paths: - '!**' - 'vlib/builtin/**.v' - 'vlib/strconv/**.v' - 'vlib/strings/**.v' - 'vlib/math/**.v' - 'vlib/math/big/**.v' - 'vlib/arrays/**.v' - 'vlib/crypto/ecdsa/**.v' - 'vlib/datatypes/**.v' - 'vlib/os/**.v' - 'vlib/sync/**.v' - 'vlib/v/tests/**.v' - 'vlib/v/ast/**.v' - 'vlib/v/scanner/**.v' - 'vlib/v/parser/**.v' - 'vlib/v/checker/**.v' - 'vlib/v/gen/c/**.v' - 'vlib/v/builder/**.v' - 'vlib/v/cflag/**.v' - 'vlib/v/live/**.v' - 'vlib/v/util/**.v' - 'vlib/v/markused/**.v' - 'vlib/v/preludes/**.v' - 'vlib/v/embed_file/**.v' - 'vlib/x/json2/**.v' - '**/sanitized_ci.yml' concurrency: group: sanitized-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: sanitize-undefined-clang: runs-on: ubuntu-22.04 timeout-minutes: 120 env: VFLAGS: -cc clang -cflags -fno-omit-frame-pointer VJOBS: 1 UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1:print_suppressions=0:suppressions=/home/runner/work/v/v/.github/workflows/run_sanitizers_undefined.suppressions VNATIVE_SKIP_LIBC_VV: 1 VTEST_SHOW_LONGEST_BY_RUNTIME: 3 VTEST_SHOW_LONGEST_BY_COMPTIME: 3 VTEST_SHOW_LONGEST_BY_TOTALTIME: 3 steps: - uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: V doctor run: ./v doctor - name: Ensure code is well formatted run: ./v -silent test-cleancode - name: Install dependencies run: | .github/workflows/disable_azure_mirror.sh ./v retry -- sudo apt update ./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind ./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev ./v retry -- sudo apt install clang - name: Recompile V with -cstrict run: ./v -cg -cstrict -o v cmd/v - name: Self tests (-fsanitize=undefined) run: | ./v -cflags -fsanitize=undefined -o v2 cmd/v ./v2 -cflags -fsanitize=undefined -silent test-self vlib - name: Build examples (V compiled with -fsanitize=undefined) run: ./v2 -silent build-examples sanitize-undefined-gcc: runs-on: ubuntu-22.04 timeout-minutes: 120 env: VFLAGS: -cc gcc -cflags -fno-omit-frame-pointer VJOBS: 1 UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1:print_suppressions=0:suppressions=/home/runner/work/v/v/.github/workflows/run_sanitizers_undefined.suppressions VNATIVE_SKIP_LIBC_VV: 1 VTEST_SHOW_LONGEST_BY_RUNTIME: 3 VTEST_SHOW_LONGEST_BY_COMPTIME: 3 VTEST_SHOW_LONGEST_BY_TOTALTIME: 3 steps: - uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: V doctor run: ./v doctor - name: Ensure code is well formatted run: ./v -silent test-cleancode - name: Install dependencies run: | .github/workflows/disable_azure_mirror.sh ./v retry -- sudo apt update ./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind ./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev - name: Recompile V with -cstrict run: ./v -cg -cstrict -o v cmd/v - name: Self tests (-fsanitize=undefined) run: | ./v -cflags -fsanitize=undefined -o v2 cmd/v ./v2 -cflags -fsanitize=undefined -silent test-self vlib - name: Build examples (V compiled with -fsanitize=undefined) run: ./v2 -silent build-examples sanitize-address-clang: runs-on: ubuntu-22.04 timeout-minutes: 300 env: VFLAGS: -cc clang -cflags -fno-omit-frame-pointer VJOBS: 1 ASAN_OPTIONS: detect_leaks=1 LSAN_OPTIONS: max_leaks=1:print_suppressions=0:suppressions=/home/runner/work/v/v/.github/workflows/run_sanitizers_leak.suppressions VNATIVE_SKIP_LIBC_VV: 1 VTEST_SHOW_LONGEST_BY_RUNTIME: 3 VTEST_SHOW_LONGEST_BY_COMPTIME: 3 VTEST_SHOW_LONGEST_BY_TOTALTIME: 3 steps: - uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: V doctor run: ./v doctor - name: Ensure code is well formatted run: ./v -silent test-cleancode - name: Install dependencies run: | .github/workflows/disable_azure_mirror.sh ./v retry -- sudo apt update ./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind ./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev ./v retry -- sudo apt install clang - name: Recompile V with -cstrict run: ./v -cg -cstrict -o v cmd/v - name: Self tests (-fsanitize=address) run: ./v -cflags -fsanitize=address,pointer-compare,pointer-subtract -silent test-self vlib - name: Test vlib/v/tests/ (V compiled with -fsanitize=address) run: | ./v -cflags -fsanitize=address -o v cmd/v ./v -cc tcc -silent test-self -asan-compiler vlib/v/tests/ - name: Build examples (V compiled with -fsanitize=address) run: ./v -silent build-examples sanitize-address-msvc: runs-on: windows-2025 timeout-minutes: 30 env: VFLAGS: -cc msvc VJOBS: 1 VNATIVE_SKIP_LIBC_VV: 1 VTEST_SHOW_LONGEST_BY_RUNTIME: 3 VTEST_SHOW_LONGEST_BY_COMPTIME: 3 VTEST_SHOW_LONGEST_BY_TOTALTIME: 3 steps: - uses: actions/checkout@v6 - name: Build run: | echo %VFLAGS% echo $VFLAGS .\make.bat -msvc .\v.exe self - name: V doctor run: .\v.exe doctor - name: Ensure code is well formatted run: .\v.exe -silent test-cleancode # - name: Install dependencies # run: | # .\v.exe setup-freetype # .\.github\workflows\windows-install-sqlite.bat # - name: Self tests (/fsanitize=address) # TODO: # run: .\v.exe -cflags "/fsanitize=address" -silent test-self vlib sanitize-address-gcc: runs-on: ubuntu-22.04 timeout-minutes: 300 env: VFLAGS: -cc gcc -cflags -fno-omit-frame-pointer VJOBS: 1 ASAN_OPTIONS: detect_leaks=1 LSAN_OPTIONS: max_leaks=1:print_suppressions=0:suppressions=/home/runner/work/v/v/.github/workflows/run_sanitizers_leak.suppressions VNATIVE_SKIP_LIBC_VV: 1 VTEST_SHOW_LONGEST_BY_RUNTIME: 3 VTEST_SHOW_LONGEST_BY_COMPTIME: 3 VTEST_SHOW_LONGEST_BY_TOTALTIME: 3 steps: - uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: V doctor run: ./v doctor - name: Ensure code is well formatted run: ./v -silent test-cleancode - name: Install dependencies run: | .github/workflows/disable_azure_mirror.sh ./v retry -- sudo apt update ./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind ./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev ./v retry -- sudo apt install clang - name: Recompile V with -cstrict run: ./v -cg -cstrict -o v cmd/v - name: Self tests (-fsanitize=address) run: ./v -cflags -fsanitize=address -silent test-self vlib - name: Test vlib/v/tests/ (V compiled with -fsanitize=address) run: | ./v -cflags -fsanitize=address,pointer-compare,pointer-subtract -o v cmd/v ./v -cc tcc -silent test-self -asan-compiler vlib/v/tests/ - name: Build examples (V compiled with -fsanitize=address) run: ./v -silent build-examples sanitize-memory-clang: runs-on: ubuntu-22.04 timeout-minutes: 240 env: VFLAGS: -cc clang -gc none -cflags -fno-omit-frame-pointer VJOBS: 1 VNATIVE_SKIP_LIBC_VV: 1 VTEST_SHOW_LONGEST_BY_RUNTIME: 3 VTEST_SHOW_LONGEST_BY_COMPTIME: 3 VTEST_SHOW_LONGEST_BY_TOTALTIME: 3 steps: - uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: V doctor run: ./v doctor - name: Ensure code is well formatted run: ./v -silent test-cleancode - name: Install dependencies run: | .github/workflows/disable_azure_mirror.sh ./v retry -- sudo apt update ./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind ./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev ./v retry -- sudo apt install clang - name: Recompile V with clang and -cstrict run: ./v -cc clang -cg -cstrict -o v cmd/v - name: Self tests (-fsanitize=memory) run: ./v -cflags -fsanitize=memory -silent test-self -msan-compiler vlib - name: Test vlib/v/tests/ (V compiled with -fsanitize=memory) run: | ./v -cflags -fsanitize=memory -o v cmd/v ./v -cc tcc -silent test-self -msan-compiler vlib/v/tests/ - name: Build examples (V compiled with -fsanitize=memory) run: ./v -silent build-examples sanitize-address-clang-without-gc: runs-on: ubuntu-22.04 timeout-minutes: 300 env: VFLAGS: -cc clang -gc none -cflags -fno-omit-frame-pointer VJOBS: 1 LSAN_OPTIONS: detect_leaks=0 VNATIVE_SKIP_LIBC_VV: 1 VTEST_SHOW_LONGEST_BY_RUNTIME: 3 VTEST_SHOW_LONGEST_BY_COMPTIME: 3 VTEST_SHOW_LONGEST_BY_TOTALTIME: 3 steps: - uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: V doctor run: ./v doctor - name: Ensure code is well formatted run: ./v -silent test-cleancode - name: Install dependencies run: | .github/workflows/disable_azure_mirror.sh ./v retry -- sudo apt update ./v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind ./v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev ./v retry -- sudo apt install clang - name: Recompile V with -cstrict run: ./v -cg -cstrict -o v cmd/v - name: Self tests (-fsanitize=address) run: ./v -cflags -fsanitize=address -silent test-self vlib ================================================ FILE: .github/workflows/sdl_ci.yml ================================================ name: sdl CI on: workflow_dispatch: push: paths: - 'vlib/**' - 'thirdparty/**' - 'cmd/tools/builders/**.v' - 'cmd/tools/vshader.v' - '**/sdl_ci.yml' - '!**.md' pull_request: paths: - 'vlib/**' - 'thirdparty/**' - 'cmd/tools/builders/**.v' - 'cmd/tools/vshader.v' - '**/sdl_ci.yml' - '!**.md' concurrency: group: sdl-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: v-compiles-sdl-examples: runs-on: ubuntu-24.04 timeout-minutes: 20 env: VFLAGS: -cc tcc steps: - uses: actions/checkout@v6 - name: Build V run: make && sudo ./v symlink - name: Install dependencies run: | .github/workflows/disable_azure_mirror.sh v retry 'sudo apt update' v retry 'sudo apt install -y libsdl2-dev libsdl2-ttf-dev' v retry 'sudo apt install -y libsdl2-mixer-dev libsdl2-image-dev' - name: Clone sdl into .vmodules run: | v retry 'git clone --filter=blob:none https://github.com/vlang/sdl' cd sdl mkdir -p ~/.vmodules ln -s "$(pwd)" ~/.vmodules/sdl - name: Ensure SDL setup works run: ./v ~/.vmodules/sdl/setup.vsh - name: Run tests run: ./v test sdl - name: Build sdl shared run: ./v -shared -g sdl - name: Build sdl examples run: | v shader sdl/examples/sdl_opengl_and_sokol v should-compile-all sdl/examples/ ~/.vmodules/sdl/examples/versions/main - name: Check SDL works, when installed through vpm run: | rm -rf sdl/ rm -rf ~/.vmodules/sdl v retry 'v install sdl' ls -la ~/.vmodules/sdl/ v ~/.vmodules/sdl/setup.vsh v run ~/.vmodules/sdl/examples/versions ================================================ FILE: .github/workflows/show_manual_release_cmd.vsh ================================================ import os import time import term now := time.now() year := now.year week := now.strftime('%V') mut remote_name := 'origin' mut release_tag := 'weekly.${year:04}.${week:02}' if os.args.len > 1 { remote_name = os.args[1] } if os.args.len > 2 { release_tag = os.args[2] } println('## Usage: show_manual_release_cmd.vsh [REMOTE] [TAGNAME]') println('## current remote_name: ${remote_name}') println('## current release_tag: ${release_tag}') println('## ▼▼▼ ${term.ecolorize(term.yellow, 'run the following, to make a new github release')} ▼▼▼ ') git_cmd := 'git tag -s -m "releases: ${release_tag}" ${release_tag} && git push --atomic ${remote_name} ${release_tag}' println(git_cmd) ================================================ FILE: .github/workflows/ssa_backends_ci.yml.disabled ================================================ name: SSA backends CI on: push: paths: - 'vlib/v2/**' - 'cmd/tinyv/**' - '.github/workflows/ssa_backends_ci.yml' pull_request: paths: - 'vlib/v2/**' - 'cmd/tinyv/**' - '.github/workflows/ssa_backends_ci.yml' concurrency: group: ssa_backends-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: ssa-backends-linux: runs-on: ubuntu-24.04 env: VJOBS: 1 steps: - uses: actions/checkout@v6 - name: Build V run: make && ./v symlink - name: Test native x64 backend run: v run cmd/tinyv/test_ssa_backends.v - name: Test cleanc backend run: v run cmd/tinyv/test_ssa_backends.v cleanc - name: Test c-ssa backend run: v run cmd/tinyv/test_ssa_backends.v c ssa-backends-macos: runs-on: macos-14 env: VJOBS: 1 steps: - uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: Test native arm64 backend run: v run cmd/tinyv/test_ssa_backends.v - name: Test cleanc backend run: v run cmd/tinyv/test_ssa_backends.v cleanc - name: Test c-ssa backend run: v run cmd/tinyv/test_ssa_backends.v c ================================================ FILE: .github/workflows/symlink_ci.yml ================================================ name: Symlink CI on: workflow_dispatch: push: paths: - 'cmd/tools/vsymlink/**.v' - '.github/workflows/symlink_ci.yml' pull_request: paths: - 'cmd/tools/vsymlink/**.v' - '.github/workflows/symlink_ci.yml' concurrency: group: symlink-${{ github.workflow }}-${{ github.ref_name == 'master' && github.sha || github.ref_name }} cancel-in-progress: true jobs: symlink-unix: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, macos-latest] fail-fast: false steps: - uses: actions/checkout@v6 - name: Build V run: make -j4 - name: Symlink run: | ./v symlink cd /tmp/ && v version cd ~ && v version echo 'println(123)' > hi.v v run hi.v - name: Unlink run: | rm "$(which v)" v --version && exit 1 || exit 0 - name: Symlink (sudo) run: | sudo ./v symlink cd /tmp/ && v version cd ~ && v version echo 'println(123)' > hi.v v run hi.v - name: Unlink run: | rm "$(which v)" v --version && exit 1 || exit 0 - name: Symlink (-githubci) run: ./v symlink -githubci - name: Test after symlink with -githubci (in a separate script) run: | cd /tmp/ && v version cd ~ && v version echo 'println(123)' > hi.v v run hi.v symlink-windows: runs-on: windows-2025 strategy: matrix: flags: ['', '-githubci'] fail-fast: false steps: - uses: actions/checkout@v6 - name: Build V run: ./make.bat - name: Symlink run: ./v symlink ${{ matrix.flags }} - name: Check if V is usable run: | cd $RUNNER_TEMP && pwd && v version cd ~ && pwd && v version echo 'println(123)' > hi.v v run hi.v ================================================ FILE: .github/workflows/termux_ci.yml ================================================ name: CI Termux on: workflow_dispatch: push: paths-ignore: - '**.md' - '**.yml' - '!**/termux_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**/termux_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' jobs: termux-build: runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v6 - name: Build and test in Termux run: | set -o xtrace echo "$PWD" whoami touch outside_docker.txt git log -n4 echo "running docker ..." docker run --rm --mount type=bind,source=/home/runner/work/v/v,destination=/src -w /src termux/termux-docker:latest bash -c ' set -o xtrace echo "running inside docker" whoami cp -r /src ~/vproject; cd ~/vproject touch inside_docker.txt ls -la echo "previous TERMUX_VERSION: $TERMUX_VERSION" export TERMUX_VERSION=0.118.3 echo "explicit TERMUX_VERSION: $TERMUX_VERSION" .github/workflows/retry.sh pkg update -y .github/workflows/retry.sh pkg install -y clang libexecinfo libgc libgc-static make git git log -n4 VFLAGS="-cc cc" make ./v symlink v run examples/hello_world.v v run examples/primes.v v -e "import os; dump( os.user_os() )" ' ================================================ FILE: .github/workflows/time_ci.yml ================================================ name: Time CI on: push: paths: - 'vlib/**' - 'cmd/tools/builders/**.v' - '**/time_ci.yml' - '!**.md' pull_request: paths: - 'vlib/**' - 'cmd/tools/builders/**.v' - '**/time_ci.yml' - '!**.md' concurrency: group: time-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: time-linux: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Build V run: make - name: Test time functions in a timezone UTC-12 run: TZ=Etc/GMT+12 ./v test vlib/time/ - name: Test time functions in a timezone UTC-3 run: TZ=Etc/GMT+3 ./v test vlib/time/ - name: Test time functions in a timezone UTC+3 run: TZ=Etc/GMT-3 ./v test vlib/time/ - name: Test time functions in a timezone UTC+12 run: TZ=Etc/GMT-12 ./v test vlib/time/ - name: Test in a timezone using daylight saving (Europe/Paris) run: TZ=Europe/Paris ./v test vlib/time/ time-macos: runs-on: macos-14 steps: - uses: actions/checkout@v6 - name: Build V run: make - name: Test time functions in a timezone UTC-12 run: TZ=Etc/GMT+12 ./v test vlib/time/ - name: Test time functions in a timezone UTC-3 run: TZ=Etc/GMT+3 ./v test vlib/time/ - name: Test time functions in a timezone UTC+3 run: TZ=Etc/GMT-3 ./v test vlib/time/ - name: Test time functions in a timezone UTC+12 run: TZ=Etc/GMT-12 ./v test vlib/time/ - name: Test in a timezone using daylight saving (Europe/Paris) run: TZ=Europe/Paris ./v test vlib/time/ time-windows: runs-on: windows-2025 steps: - uses: actions/checkout@v6 - name: Build V run: .\make.bat - name: Test time functions in a timezone UTC-12 run: tzutil /s "Dateline Standard Time" && ./v test vlib/time/ - name: Test time functions in a timezone UTC-3 run: tzutil /s "Greenland Standard Time" && ./v test vlib/time/ - name: Test time functions in a timezone UTC+3 run: tzutil /s "Russian Standard Time" && ./v test vlib/time/ - name: Test time functions in a timezone UTC+12 run: tzutil /s "New Zealand Standard Time" && ./v test vlib/time/ - name: Test in a timezone using daylight saving (Europe/Paris) run: tzutil /s "W. Europe Standard Time" && ./v test vlib/time/ ================================================ FILE: .github/workflows/toml_ci.yml ================================================ name: toml CI on: push: paths: - 'vlib/**' - '**/toml_ci.yml' - '!**.md' pull_request: paths: - 'vlib/**' - '**/toml_ci.yml' - '!**.md' concurrency: group: toml-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: toml-module-pass-external-test-suites: runs-on: ubuntu-latest timeout-minutes: 20 steps: - uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: Install dependencies run: | v retry -- v download https://github.com/jqlang/jq/releases/download/jq-1.6/jq-linux64 sudo chmod 755 jq-linux64 sudo mv jq-linux64 /usr/bin/jq - name: Show JQ Version run: jq --version - name: Download more TOML testsuits run: .github/workflows/download_full_toml_test_suites.sh - name: Run TOML tests run: VTEST_TOML_DO_YAML_CONVERSION=1 VTEST_TOML_DO_LARGE_FILES=1 ./v test vlib/toml ================================================ FILE: .github/workflows/tools_ci.yml ================================================ name: Tools CI on: push: paths: - 'cmd/**' - '!cmd/tools/vpm/**' - 'vlib/**' - 'thirdparty/**' - '!**.md' - '**/tools_ci.yml' pull_request: paths: - 'cmd/**' - '!cmd/tools/vpm/**' - 'vlib/**' - 'thirdparty/**' - '!**.md' - '**/tools_ci.yml' concurrency: group: tools-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: tools-linux: runs-on: ubuntu-22.04 timeout-minutes: 20 strategy: matrix: cc: [tcc, gcc, clang] fail-fast: false env: VFLAGS: -cc ${{ matrix.cc }} steps: - uses: actions/checkout@v6 - name: Build V run: make && ./v -showcc -o v cmd/v && ./v symlink && ./v doctor - name: Code in cmd/ is formatted run: ./v fmt -verify cmd/ - name: Check build-tools run: ./v -silent -N -W -check build-tools - name: Test tools run: ./v -silent test-self cmd - name: Test tools (-cstrict) if: ${{ matrix.cc != 'tcc' }} run: ./v -silent -W -cstrict test-self cmd - name: Test sanitized if: ${{ matrix.cc != 'tcc' }} run: | export VNATIVE_SKIP_LIBC_VV=1 if [[ ${{ matrix.cc }} == "clang" ]]; then cmd="./v -silent -cc clang -cflags -fsanitize=undefined test-self -ubsan-compiler cmd" echo "$cmd" && $cmd cmd="./v -silent -cc clang -cflags -fsanitize=memory test-self -msan-compiler cmd" echo "$cmd" && $cmd else cmd="./v -silent -cc gcc -cflags -fsanitize=thread test-self cmd" echo "$cmd" && $cmd cmd="./v -silent -cc gcc -cflags -fsanitize=address,leak,undefined,shift,shift-exponent,shift-base,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,bounds-strict,alignment,object-size,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr test-self -asan-compiler cmd/tools" echo "$cmd" && $cmd ## cmd="./v -silent -cc gcc -cflags -fsanitize=kernel-address test-self -asan-compiler cmd" ## echo "$cmd" && $cmd fi tools-macos: runs-on: macos-14 timeout-minutes: 20 strategy: matrix: cc: [clang] fail-fast: false env: VFLAGS: -cc ${{ matrix.cc }} steps: - uses: actions/checkout@v6 - name: Build V run: make && ./v -showcc -o v cmd/v && ./v symlink && ./v doctor - name: Check build-tools run: ./v -silent -N -W -check build-tools - name: Test tools run: ./v -silent test-self cmd - name: Test tools (-cstrict) run: ./v -silent -W -cstrict test-self cmd tools-windows: runs-on: windows-2025 timeout-minutes: 20 strategy: matrix: cc: [tcc, gcc, msvc] fail-fast: false env: VFLAGS: -cc ${{ matrix.cc }} steps: - uses: actions/checkout@v6 - name: Build V run: ./make.bat -${{ matrix.cc }} && ./v -o v2.exe cmd/v && ./v2 -showcc -o v.exe cmd/v && ./v symlink && ./v doctor - name: Check build tools run: ./v build-tools - name: Test tools run: ./v -silent test-self cmd - name: Test tools (-cstrict) if: ${{ matrix.cc == 'msvc' }} run: ./v -silent -W -cstrict test-self cmd tools-docker-ubuntu-musl: runs-on: ubuntu-24.04 timeout-minutes: 20 container: image: thevlang/vlang:ubuntu-build env: V_CI_MUSL: 1 V_CI_UBUNTU_MUSL: 1 VFLAGS: -cc musl-gcc -gc none volumes: - ${{github.workspace}}:/opt/vlang steps: - name: Checkout uses: actions/checkout@v6 - name: Build V run: make && ./v -cg -o v cmd/v && ./v symlink - name: Ensure git commands can be used with no prompts on modern Git versions run: git config --global --add safe.directory /__w/v/v - name: Verify `v test` works run: | ./v cmd/tools/test_if_v_test_system_works.v ./cmd/tools/test_if_v_test_system_works - name: Check build tools run: ./v -silent -N -W -check build-tools - name: Test tools run: ./v -silent test-self cmd - name: Test tools (-cstrict) run: ./v -silent -W -cstrict test-self cmd tools-freebsd: runs-on: ubuntu-latest timeout-minutes: 20 strategy: matrix: cc: [tcc, gcc, clang] fail-fast: false env: VFLAGS: -cc ${{ matrix.cc }} steps: - uses: actions/checkout@v6 - name: Tests tools on FreeBSD with ${{ matrix.cc }} uses: cross-platform-actions/action@v0.32.0 with: operating_system: freebsd version: '15.0' memory: 4G shell: sh sync_files: runner-to-vm environment_variables: VFLAGS run: | sudo pkg install -y git sqlite3 gmake boehm-gc-threaded libiconv if [ "$VFLAGS" = "-cc gcc" ]; then sudo pkg install -y gcc fi # Mandatory: hostname not set in VM => some tests fail sudo hostname -s freebsd-ci echo "### OS infos" uname -a git config --global --add safe.directory . # Build V echo "### Build V" printf "VFLAGS = %s\n" "$VFLAGS" gmake && ./v -showcc -o v cmd/v && sudo ./v symlink && ./v doctor # Code in cmd/ is formatted echo "### Check code in cmd/ is formatted" ./v fmt -verify cmd/ # Check build-tools echo "### Check build tools" ./v -silent -N -W -check build-tools # Test tools echo "### Test tools" ./v -silent test-self cmd # Test tools (-cstrict) if [ "$VFLAGS" != "-cc tcc" ]; then echo "### Test tools (-cstrict)" ./v -silent -W -cstrict test-self cmd fi tools-openbsd: runs-on: ubuntu-latest timeout-minutes: 20 strategy: matrix: cc: [tcc, clang] fail-fast: false env: VFLAGS: -cc ${{ matrix.cc }} steps: - uses: actions/checkout@v6 - name: Tests tools on OpenBSD with ${{ matrix.cc }} uses: cross-platform-actions/action@v0.32.0 with: operating_system: openbsd version: '7.8' memory: 4G shell: sh sync_files: runner-to-vm environment_variables: VFLAGS run: | sudo pkg_add git sqlite3 gmake boehm-gc libiconv # Mandatory: hostname not set in VM => some tests fail sudo hostname -s openbsd-ci echo "### OS infos" uname -a git config --global --add safe.directory . # Build V echo "### Build V" printf "VFLAGS = %s\n" "$VFLAGS" gmake && ./v -showcc -o v cmd/v && sudo ./v symlink && ./v doctor # Code in cmd/ is formatted echo "### Check code in cmd/ is formatted" ./v fmt -verify cmd/ # Check build-tools echo "### Check build tools" ./v -silent -N -W -check build-tools # Test tools echo "### Test tools" ./v -silent test-self cmd # Test tools (-cstrict) if [ "$VFLAGS" != "-cc tcc" ]; then echo "### Test tools (-cstrict)" ./v -silent -W -cstrict test-self cmd fi ================================================ FILE: .github/workflows/v_apps_and_modules_compile_ci.yml ================================================ name: V Apps and Modules on: push: paths-ignore: - '**.md' - '**.yml' - '!**/v_apps_and_modules_compile_ci.yml' - 'examples/**' - 'cmd/tools/vrepl.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**/v_apps_and_modules_compile_ci.yml' - 'examples/**' - 'cmd/tools/vrepl.v' concurrency: group: v_apps-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: v-apps-compile: strategy: matrix: os: [ubuntu-latest, macos-14] fail-fast: false runs-on: ${{ matrix.os }} timeout-minutes: 60 steps: - uses: actions/checkout@v6 - name: Build V id: build run: make && sudo ./v symlink - name: Install dependencies run: | if [ "$RUNNER_OS" == 'Linux' ]; then .github/workflows/disable_azure_mirror.sh v retry -- sudo apt -qq update v retry -- sudo apt -qq install libgc-dev libsodium-dev libssl-dev sqlite3 libsqlite3-dev v retry -- sudo apt -qq install libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev xfonts-75dpi xfonts-base libegl-dev v retry -- sudo apt -qq install sassc libgit2-dev # needed by gitly else v retry brew install sassc libgit2 fi - name: Build docs generator run: | v retry -- v install markdown v retry -- git clone https://github.com/vlang/docs --branch generator --depth 1 cd docs v . - name: Test vtcc if: runner.os == 'Linux' run: .github/workflows/compile_v_with_vtcc.sh - name: Test vsql compilation and examples if: ${{ false && !cancelled() && steps.build.outcome == 'success' }} run: | echo "Install vsql" v retry -- v install elliotchance.vsql cd ~/.vmodules/elliotchance/vsql echo "Compile vsql" make bin/vsql echo "Run examples" make examples echo "Run vsql/connection_test.v" v vsql/connection_test.v - name: Test vlang/gui if: ${{ !cancelled() && steps.build.outcome == 'success' }} run: .github/workflows/compile_vlang_gui_examples.sh - name: Test discord.v if: ${{ !cancelled() && steps.build.outcome == 'success' }} run: .github/workflows/compile_discordv.sh - name: Build herolib if: ${{ false && !cancelled() && steps.build.outcome == 'success' }} run: .github/workflows/compile_herolib.sh - name: Build vlang/vab if: ${{ !cancelled() && steps.build.outcome == 'success' }} run: | echo "Install VAB" v retry -- v install vab echo "Build vab" v ~/.vmodules/vab echo "Build vab with -g" v -g ~/.vmodules/vab - name: Build vlang/ved if: ${{ !cancelled() && steps.build.outcome == 'success' }} run: | v retry -- git clone --depth 1 https://github.com/vlang/ved cd ved && v -o ved . echo "Build" v . echo "Build with -autofree ..." v -autofree . echo "Build with -prod ..." v -prod . cd .. - name: Build vlang/pdf if: ${{ !cancelled() && steps.build.outcome == 'success' }} run: | v retry -- v install pdf echo "PDF examples should compile" v should-compile-all ~/.vmodules/pdf/examples - name: Build vlang/libsodium if: ${{ !cancelled() && steps.build.outcome == 'success' }} run: | echo "Install the libsodium wrapper" v retry -- v install libsodium echo "Test libsodium" VJOBS=1 v test ~/.vmodules/libsodium - name: Build vlang/coreutils if: ${{ !cancelled() && steps.build.outcome == 'success' }} run: | echo "Clone Coreutils" v retry -- git clone --depth 1 https://github.com/vlang/coreutils /tmp/coreutils echo "Build Coreutils" cd /tmp/coreutils; make - name: Build vlang/gitly if: ${{ !cancelled() && steps.build.outcome == 'success' }} run: | echo "Install markdown" v retry -- v install markdown echo "Install pcre" v retry -- v install pcre echo "Clone Gitly" v retry -- git clone https://github.com/vlang/gitly /tmp/gitly echo "Build Gitly" v -cc gcc /tmp/gitly ## echo "Build Gitly with -autofree" ## v -cc gcc -autofree /tmp/gitly echo "Compile gitly.css from gitly.scss" sassc /tmp/gitly/src/static/css/gitly.scss > /tmp/gitly/src/static/css/gitly.css # echo "Run first_run.v" # v -cc gcc run /tmp/gitly/tests/first_run.v # # /tmp/gitly/gitly -ci_run - name: Build V UI examples if: ${{ !cancelled() && steps.build.outcome == 'success' }} run: | v retry -- v install ui v -no-parallel ~/.vmodules/ui/examples/rectangles.v v -no-parallel ~/.vmodules/ui/examples/users.v # v run ~/.vmodules/ui/examples/build_examples.vsh - name: Build vlang/v-analyzer if: ${{ !cancelled() && steps.build.outcome == 'success' }} run: | echo "Clone v-analyzer" v retry -- git clone --depth=1 --filter=blob:none --recursive --shallow-submodules https://github.com/vlang/v-analyzer /tmp/v-analyzer cd /tmp/v-analyzer echo "Installing dependencies" v install echo "Build v-analyzer debug" v build.vsh debug echo "Build v-analyzer release" v build.vsh release - name: Format vlang/v-analyzer if: ${{ !cancelled() && steps.build.outcome == 'success' }} run: | cd /tmp/v-analyzer set +e v fmt -c . exit_code=$? if [[ $exit_code -ne 0 && $exit_code -ne 5 ]]; then # Don't fail if there are only internal errors (exit code 5). v fmt -diff . exit 1 fi - name: Build vlang/go2v if: ${{ !cancelled() && steps.build.outcome == 'success' && matrix.os != 'macos-14' }} run: | echo "Clone Go2V" v retry -- git clone --depth=1 https://github.com/vlang/go2v /tmp/go2v/ echo "Build Go2V" v /tmp/go2v/ echo "Run Go2V tests" VJOBS=1 v test /tmp/go2v/ - name: Install UI through VPM and make sure its examples compile if: ${{ !cancelled() && steps.build.outcome == 'success' }} run: | echo "Official VPM modules should be installable" v retry -- v install ui echo "Examples of UI should compile" v ~/.vmodules/ui/examples/build_examples.vsh - name: Build vlang/adventofcode if: ${{ !cancelled() && steps.build.outcome == 'success' }} run: | echo "Clone the AdventOfCode repo" v retry -- git clone --depth 1 https://github.com/vlang/adventofcode /tmp/adventofcode echo "Install dependencies" v retry -- v install pcre echo "Execute Tests" cd /tmp/adventofcode && v run verify.v - name: Build vlang/msgpack if: ${{ !cancelled() && steps.build.outcome == 'success' }} run: | echo "Install msgpack" v retry -- v install msgpack echo "Build msgpack" v -shared ~/.vmodules/msgpack/ echo "Run msgpack tests" v test ~/.vmodules/msgpack/ echo "MessagePack examples should compile" v should-compile-all ~/.vmodules/msgpack/examples # - name: Build VEX # if: ${{ !cancelled() }} && steps.build.outcome == 'success' # run: | # echo "Install Vex" # v retry -- v install nedpals.vex # echo "Compile all of the Vex examples" # v should-compile-all ~/.vmodules/nedpals/vex/examples # echo "Compile the simple Vex example" # v ~/.vmodules/nedpals/vex/examples/simple_example.v # echo "Run Vex Tests" # v test ~/.vmodules/nedpals/vex vpm-site-compile: strategy: matrix: os: [ubuntu-24.04, macos-14] fail-fast: false runs-on: ${{ matrix.os }} timeout-minutes: 20 steps: - uses: actions/checkout@v6 - name: Build V run: make && ./v symlink - name: Build vpm run: | v retry -- v install markdown v retry -- git clone --depth 1 https://github.com/vlang/vpm cd vpm && v . ================================================ FILE: .github/workflows/vab_ci.yml ================================================ name: vab CI on: workflow_call: push: paths: - 'vlib/**' - 'thirdparty/**' - 'cmd/tools/builders/**.v' - '**/vab_ci.yml' - '!**.md' pull_request: paths: - 'vlib/**' - 'thirdparty/**' - 'cmd/tools/builders/**.v' - '**/vab_ci.yml' - '!**.md' concurrency: group: vab-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: vab-compiles-v-examples: runs-on: ubuntu-24.04 timeout-minutes: 20 env: VAB_FLAGS: --api 30 --build-tools 29.0.0 -v 3 steps: - uses: actions/setup-java@v5 with: distribution: 'temurin' java-version: 11 - uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: Install vab run: | v retry -- v install vab v -g ~/.vmodules/vab sudo ln -s ~/.vmodules/vab/vab /usr/local/bin/vab - name: Run tests run: v -g test ~/.vmodules/vab - name: Run vab --help run: vab --help - name: Run vab doctor run: | vab doctor which d8 || true which dx || true - name: Build graphical V examples as APK run: | declare -a v_examples=('flappylearning' '2048' 'fireworks' 'tetris' 'sokol/particles' 'sokol/drawing.v' 'sokol/freetype_raven.v' 'gg/polygons.v' 'gg/raven_text_rendering.v' 'gg/rectangles.v' 'gg/stars.v' 'gg/worker_thread.v') mkdir apks for example in "${v_examples[@]}"; do safe_name=$(echo "$example" | sed 's%/%-%' | sed 's%\.%-%' ) vab "examples/$example" -o "apks/$safe_name.apk" done v-compiles-os-android: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: Install vab run: | v retry -- v install vab v -g ~/.vmodules/vab sudo ln -s ~/.vmodules/vab/vab /usr/local/bin/vab - name: Run vab --help run: vab --help - name: Run vab doctor run: vab doctor - name: Check `v -os android` *without* -apk flag run: .github/workflows/android_cross_compile.vsh ================================================ FILE: .github/workflows/vinix_ci.yml ================================================ name: Build Vinix on: workflow_call: pull_request: paths-ignore: - '**.md' - '**.yml' - '!**/vinix_ci.yml' - 'cmd/tools/vrepl.v' push: branches: - master paths-ignore: - '**.md' - '**.yml' - '!**/vinix_ci.yml' - 'cmd/tools/vrepl.v' concurrency: group: vinix-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: vinix-build: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - uses: actions/checkout@v6 - name: Build V run: make -j4 && ./v symlink - name: Install dependencies run: | .github/workflows/disable_azure_mirror.sh v retry -- sudo apt update v retry -- sudo apt install build-essential -y - name: Clone current Vinix run: v retry -- git clone --depth=1 https://github.com/vlang/vinix.git - name: Download Vinix kernel dependencies run: cd vinix/kernel && v retry -- ./get-deps - name: Attempt to build the Vinix kernel (debug) run: | set -e cd vinix/kernel make PROD=false \ CFLAGS="-Ulinux -U__linux -U__linux__ -U__gnu_linux__ -D__vinix__ -O2 -g -pipe" \ V="$(realpath ../../v)" make clean - name: Attempt to build the Vinix kernel (prod) run: | set -e cd vinix/kernel make PROD=true \ CFLAGS="-Ulinux -U__linux -U__linux__ -U__gnu_linux__ -D__vinix__ -O2 -g -pipe" \ V="$(realpath ../../v)" make clean - name: Attempt to build the util-vinix (debug) run: | set -e cd vinix/util-vinix make PROD=false \ VFLAGS="-os vinix -gc none" \ CFLAGS="-Ulinux -U__linux -U__linux__ -U__gnu_linux__ -D__vinix__ -O2 -g -pipe" \ V="$(realpath ../../v)" make clean - name: Attempt to build the util-vinix (prod) run: | set -e cd vinix/util-vinix make PROD=true \ VFLAGS="-os vinix -gc none" \ CFLAGS="-Ulinux -U__linux -U__linux__ -U__gnu_linux__ -D__vinix__ -O2 -g -pipe" \ V="$(realpath ../../v)" make clean ================================================ FILE: .github/workflows/vpm_ci.yml ================================================ name: VPM CI on: push: paths: - '**/vpm_ci.yml' - '**/cmd/tools/vpm/**' pull_request: paths: - '**/vpm_ci.yml' - '**/cmd/tools/vpm/**' concurrency: group: vpm-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: setup-vpm: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] fail-fast: false runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v6 with: path: vlang - name: Show git version run: git version - name: Build V if: runner.os != 'Windows' run: cd vlang && make -j4 && ./v doctor - name: Build V (Windows) if: runner.os == 'Windows' run: cd vlang && ./make.bat && ./v doctor - name: Cache V uses: actions/cache/save@v5 with: path: vlang key: ${{ runner.os }}-${{ github.sha }} test-vpm: needs: setup-vpm strategy: matrix: include: - os: ubuntu-latest cc: tcc - os: ubuntu-latest cc: gcc - os: ubuntu-latest cc: clang - os: macos-latest cc: clang - os: windows-latest cc: tcc - os: windows-latest cc: gcc - os: windows-latest cc: msvc fail-fast: false runs-on: ${{ matrix.os }} steps: - name: Restore V cache uses: actions/cache/restore@v5 with: path: vlang key: ${{ runner.os }}-${{ github.sha }} - name: Show git version run: git version - name: Build and test VPM run: | cd vlang ./v -W -N cmd/tools/vpm ./v -cc ${{ matrix.cc }} -d network test cmd/tools/vpm ================================================ FILE: .github/workflows/vsl_and_vtl_compile_ci.yml ================================================ name: VSL and VTL on: push: paths-ignore: - '**.md' - '**.yml' - '!**/vsl_and_vtl_compile_ci.yml' - 'examples/**' - 'cmd/tools/vrepl.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**/vsl_and_vtl_compile_ci.yml' - 'examples/**' - 'cmd/tools/vrepl.v' concurrency: group: vsl-vtl-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: vsl-compiles: strategy: matrix: os: [ubuntu-24.04, macos-14] fail-fast: false runs-on: ${{ matrix.os }} timeout-minutes: 25 env: VFLAGS: -no-parallel steps: - uses: actions/checkout@v6 - name: Build V id: build run: make && sudo ./v symlink - name: Install dependencies run: | if [ "$RUNNER_OS" == 'Linux' ]; then .github/workflows/disable_azure_mirror.sh v retry -- sudo apt -qq update v retry -- sudo apt -qq install \ libgc-dev libgl1-mesa-dev mesa-common-dev liblapacke-dev libopenblas-dev libopenmpi-dev \ opencl-headers libxcursor-dev libxi-dev libxrandr-dev libhdf5-cpp-103-1t64 libhdf5-dev libhdf5-mpi-dev hdf5-tools else v retry brew install coreutils hdf5 open-mpi openblas lapack opencl-headers fi - name: Install vsl run: v retry -- v install vsl - name: Test with Pure V Backend run: ~/.vmodules/vsl/bin/test - name: Test with Pure V Backend and Pure V Math run: ~/.vmodules/vsl/bin/test --use-cblas vtl-compiles: strategy: matrix: os: [ubuntu-24.04, macos-14] fail-fast: false runs-on: ${{ matrix.os }} timeout-minutes: 25 env: VFLAGS: -no-parallel # Fixes complaints about $TERM not being set when running the vtl test script # (a warning on Linux, but an error on macOS). TERM: xterm steps: - uses: actions/checkout@v6 - name: Build V id: build run: make && sudo ./v symlink - name: Install dependencies run: | if [ "$RUNNER_OS" == 'Linux' ]; then .github/workflows/disable_azure_mirror.sh v retry -- sudo apt -qq update v retry -- sudo apt -qq install \ libgc-dev libgl1-mesa-dev mesa-common-dev liblapacke-dev libopenblas-dev libopenmpi-dev else v retry brew install coreutils hdf5 open-mpi openblas lapack opencl-headers fi v retry v install vsl - name: Install vtl run: v retry v install vtl - name: Test with Pure V Backend run: ~/.vmodules/vtl/bin/test - name: Test with Pure V Backend and Pure V Math run: ~/.vmodules/vtl/bin/test --use-cblas ================================================ FILE: .github/workflows/vup_works.yml ================================================ name: Upgrading from a previous release with v up works on: push: paths-ignore: - '**.md' - '**.yml' - '**.vv' - '**.out' - '!**/vup_works.yml' - '!cmd/tools/vup.v' - 'cmd/tools/vrepl.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '**.vv' - '**.out' - '!**/vup_works.yml' - '!cmd/tools/vup.v' - 'cmd/tools/vrepl.v' concurrency: group: vup-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: v-up-works-nix: strategy: fail-fast: false matrix: include: - os: ubuntu-latest zip: v_linux.zip - os: macos-15-intel zip: v_macos_x86_64.zip - os: macos-latest zip: v_macos_arm64.zip runs-on: ${{ matrix.os }} timeout-minutes: 20 env: VDIR: /tmp/v_from_release_zip steps: - uses: actions/checkout@v6 - name: Build v run: make && ./v symlink && ./v version - name: Download latest release ZIP run: ./v retry -- ./v download --sha256 https://github.com/vlang/v/releases/latest/download/${{ matrix.zip }} - name: Extract ZIP 1, no changes run: | rm -rf "$VDIR" && unzip -q -d v_from_release/ ${{ matrix.zip }} && mv v_from_release "$VDIR" cd "$VDIR/v" ./v version ./v up echo "Updated ./v version: $(./v version) | Current v version: $(v version)" - name: Extract ZIP 2, with local changes run: | rm -rf "$VDIR" && unzip -q -d v_from_release/ ${{ matrix.zip }} && mv v_from_release "$VDIR" touch "$VDIR/v/vlib/v/pref/local_file_not_present_in_master.c.v" && rm "$VDIR/v/examples/hello_world.v" cd "$VDIR/v" ./v version ./v up echo "Updated ./v version: $(./v version) | Current v version: $(v version)" - name: Extract ZIP 3, with current vup.v in the extract run: | rm -rf "$VDIR" && unzip -q -d v_from_release/ ${{ matrix.zip }} && mv v_from_release "$VDIR" rm -rf "$VDIR/v/cmd/tools/vup" && cp cmd/tools/vup.v "$VDIR/v/cmd/tools/vup.v" cd "$VDIR/v" ./v version ./v up echo "Updated ./v version: $(./v version) | Current v version: $(v version)" - name: Extract ZIP 4, with local changes, and with current vup.v run: | rm -rf "$VDIR" && unzip -q -d v_from_release/ ${{ matrix.zip }} && mv v_from_release "$VDIR" rm -rf "$VDIR/v/cmd/tools/vup" && cp cmd/tools/vup.v "$VDIR/v/cmd/tools/vup.v" touch "$VDIR/v/vlib/v/pref/local_file_not_present_in_master.c.v" && rm "$VDIR/v/examples/hello_world.v" cd "$VDIR/v" ./v version ./v up echo "Updated ./v version: $(./v version) | Current v version: $(v version)" ================================================ FILE: .github/workflows/wasm_backend_ci.yml ================================================ name: wasm backend CI on: push: paths: - 'cmd/tools/builders/**.v' - 'vlib/builtin/**.v' - 'vlib/v/ast/**.v' - 'vlib/v/scanner/**.v' - 'vlib/v/parser/**.v' - 'vlib/v/checker/**.v' - 'vlib/v/gen/c/**.v' - 'vlib/v/builder/**.v' - 'vlib/v/cflag/**.v' - 'vlib/v/live/**.v' - 'vlib/v/util/**.v' - 'vlib/v/markused/**.v' - 'vlib/v/preludes/**.v' - 'vlib/v/gen/wasm/**.v' - 'vlib/v/gen/wasm/tests/**.v' - 'vlib/v/gen/wasm/tests/**.vv' - 'vlib/v/gen/wasm/tests_decompile/**.v' - 'vlib/v/gen/wasm/tests_decompile/**.vv' - '**/wasm_backend_ci.yml' pull_request: paths: - 'cmd/tools/builders/**.v' - 'vlib/builtin/**.v' - 'vlib/v/ast/**.v' - 'vlib/v/scanner/**.v' - 'vlib/v/parser/**.v' - 'vlib/v/checker/**.v' - 'vlib/v/gen/c/**.v' - 'vlib/v/builder/**.v' - 'vlib/v/cflag/**.v' - 'vlib/v/live/**.v' - 'vlib/v/util/**.v' - 'vlib/v/markused/**.v' - 'vlib/v/preludes/**.v' - 'vlib/v/gen/wasm/**.v' - 'vlib/v/gen/wasm/tests/**.v' - 'vlib/v/gen/wasm/tests/**.vv' - 'vlib/v/gen/wasm/tests_decompile/**.v' - 'vlib/v/gen/wasm/tests_decompile/**.vv' - '**/wasm_backend_ci.yml' concurrency: group: wasm-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: wasm-backend: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-22.04, windows-2022] fail-fast: false timeout-minutes: 20 env: VTEST_ONLY: wasm steps: - uses: actions/checkout@v6 - name: Build V if: runner.os != 'Windows' run: make -j4 - name: Build V (Windows) if: runner.os == 'Windows' run: ./make.bat - name: Install WABT to get wasm-decompile if: runner.os != 'Windows' run: ./v retry -- sudo apt install wabt - name: Setup Wasmer uses: wasmerio/setup-wasmer@v3.1 - name: Prebuild the WASM backend run: ./v cmd/tools/builders/wasm_builder.v - name: Test the WASM backend run: ./v test vlib/v/gen/wasm/ - name: Build examples run: ./v build-examples ================================================ FILE: .github/workflows/websockets_ci.yml ================================================ name: Websockets CI on: push: paths-ignore: - '**.md' - '**.yml' - '!**/websockets_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**/websockets_ci.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' concurrency: group: websockets-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: websocket_tests: runs-on: ubuntu-24.04 timeout-minutes: 121 env: VFLAGS: -cc tcc -no-retry-compilation steps: - uses: actions/checkout@v6 - name: Build v run: | echo "$VFLAGS" sudo ln -s "$PWD/thirdparty/tcc/tcc.exe" /usr/local/bin/tcc ## TODO: remove make -j4 && ./v symlink ./v -g -o v cmd/v - name: Install dependencies run: v retry -- sudo apt install --quiet -y libssl-dev - name: v doctor run: ./v doctor - name: Run websockets tests run: ./v -g test vlib/net/websocket/ ## Autobahn integrations tests - name: Run autobahn services run: docker compose -f ${{github.workspace}}/vlib/net/websocket/tests/autobahn/docker-compose.yml up -d - name: Wait for the service to start run: sleep 10s - name: Build client test run: docker exec autobahn_client "/src/v" "/src/vlib/net/websocket/tests/autobahn/autobahn_client.v" - name: Run client test run: docker exec autobahn_client "/src/vlib/net/websocket/tests/autobahn/autobahn_client" - name: Build client wss test run: docker exec autobahn_client "/src/v" "/src/vlib/net/websocket/tests/autobahn/autobahn_client_wss.v" - name: Run client wss test run: docker exec autobahn_client "/src/vlib/net/websocket/tests/autobahn/autobahn_client_wss" - name: Run server test run: docker exec autobahn_server "wstest" "-m" "fuzzingclient" "-s" "/config/fuzzingclient.json" - name: Copy reports run: docker cp autobahn_server:/reports ${{github.workspace}}/reports - name: Copy reports wss run: docker cp autobahn_server_wss:/reports ${{github.workspace}}/reports_wss - name: Test success run: docker exec autobahn_server "python" "/check_results.py" - name: Test success WSS run: docker exec autobahn_server_wss "python" "/check_results.py" - name: Publish all reports uses: actions/upload-artifact@v7 with: name: full report path: ${{github.workspace}}/reports - name: Publish report client uses: actions/upload-artifact@v7 with: name: client path: ${{github.workspace}}/reports/clients/index.html - name: Publish report server uses: actions/upload-artifact@v7 with: name: server path: ${{github.workspace}}/reports/servers/index.html - name: Publish all reports WSS uses: actions/upload-artifact@v7 with: name: full report wss path: ${{github.workspace}}/reports_wss - name: Publish report client wss uses: actions/upload-artifact@v7 with: name: client wss path: ${{github.workspace}}/reports_wss/clients/index.html ================================================ FILE: .github/workflows/windows-install-sdl.bat ================================================ @echo off curl -L https://www.libsdl.org/release/SDL2-devel-2.0.10-VC.zip -o SDL2.zip curl -L https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-devel-2.0.15-VC.zip -o SDL2_ttf.zip curl -L https://www.libsdl.org/projects/SDL_image/release/SDL2_image-devel-2.0.5-VC.zip -o SDL2_image.zip curl -L https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-devel-2.0.4-VC.zip -o SDL2_mixer.zip unzip SDL2.zip -d thirdparty/ unzip SDL2_ttf.zip -d thirdparty/ unzip SDL2_image.zip -d thirdparty/ unzip SDL2_mixer.zip -d thirdparty/ move /y thirdparty/SDL2-2.0.10 thirdparty/SDL2 move /y thirdparty/SDL2_ttf-2.0.15 thirdparty/SDL2_ttf move /y thirdparty/SDL2_image-2.0.5 thirdparty/SDL2_image move /y thirdparty/SDL2_mixer-2.0.4 thirdparty/SDL2_mixer ================================================ FILE: .github/workflows/windows-install-sqlite.bat ================================================ REM This file should be run from the top folder of the V compiler itself. v vlib/db/sqlite/install_thirdparty_sqlite.vsh ================================================ FILE: .github/workflows/windows_ci_gcc.yml ================================================ name: CI Windows GCC on: push: paths-ignore: - '**.md' - '**.yml' - '!**.bat' - '!**/windows_ci_gcc.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**.bat' - '!**/windows_ci_gcc.yml' - '!**/windows-install-sqlite.bat' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' concurrency: group: windows-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: gcc-windows: runs-on: windows-2025 timeout-minutes: 110 env: VFLAGS: -cc gcc VTEST_SHOW_LONGEST_BY_RUNTIME: 3 VTEST_SHOW_LONGEST_BY_COMPTIME: 3 VTEST_SHOW_LONGEST_BY_TOTALTIME: 3 steps: - uses: actions/checkout@v6 - name: Show tool versions run: | gcc --version pkg-config --version openssl version echo "Flags for openssl:" pkg-config openssl --cflags echo "Flags for openssl libs:" pkg-config openssl --libs .github/workflows/find_openssl.bat echo "OpenSSL files:" where.exe /R "C:\Program Files\OpenSSL" *.* echo "Include files for openssl:" dir "c:/Program Files/OpenSSL/include" echo "Lib Include files for openssl:" dir "c:/Program Files/OpenSSL/lib/VC/x64/" - name: Build run: | .\make.bat -gcc .\v.exe symlink .\v.exe -stats vlib/crypto/ecdsa/ecdsa_test.v - name: Test v binaries run: v build-vbinaries - name: All code is formatted run: v -silent test-cleancode - name: Test new v.c run: | v -o v.c cmd/v gcc -Werror -municode -w v.c -lws2_32 -std=c99 - name: Install dependencies run: | v retry -- v setup-freetype .\.github\workflows\windows-install-sqlite.bat - name: v doctor run: | v doctor - name: Verify `v test` works run: | echo $VFLAGS v cmd/tools/test_if_v_test_system_works.v ./cmd/tools/test_if_v_test_system_works - name: Test pure V math module run: v -silent -exclude @vlib/math/*.c.v test vlib/math/ - name: Self tests run: v -silent test-self vlib - name: Build option_test.c.v with -autofree run: v -autofree vlib/v/tests/options/option_test.c.v - name: Test v->js run: v -o hi.js examples/js_hello_world.v && node hi.js - name: Build examples run: v build-examples - name: v2 self compilation run: v -o v2.exe cmd/v && .\v2.exe -o v3.exe cmd/v - name: compile vdoctor.v with -prod run: v -showcc -prod cmd/tools/vdoctor.v - name: compile vup.v with -prod run: v -showcc -prod cmd/tools/vup.v ================================================ FILE: .github/workflows/windows_ci_msvc.yml ================================================ name: CI Windows MSVC on: push: paths-ignore: - '**.md' - '**.yml' - '!**.bat' - '!**/windows_ci_msvc.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**.bat' - '!**/windows_ci_msvc.yml' - '!**/windows-install-sqlite.bat' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' concurrency: group: windows-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: msvc-windows: runs-on: windows-2022 timeout-minutes: 70 env: VFLAGS: -cc msvc VTEST_SHOW_LONGEST_BY_RUNTIME: 3 VTEST_SHOW_LONGEST_BY_COMPTIME: 3 VTEST_SHOW_LONGEST_BY_TOTALTIME: 3 steps: - uses: actions/checkout@v6 - name: Build run: | echo %VFLAGS% echo $VFLAGS .\make.bat -msvc .\v.exe symlink - name: Build V with WX run: v -cflags /WX self - name: All code is formatted run: v -silent test-cleancode - name: Test -cc msvc works run: v -no-retry-compilation run examples/hello_world.v - name: Install dependencies run: | v retry -- v setup-freetype .\.github\workflows\windows-install-sqlite.bat - name: v doctor run: | v doctor - name: Verify `v test` works run: | echo $VFLAGS v cmd/tools/test_if_v_test_system_works.v ./cmd/tools/test_if_v_test_system_works - name: Test pure V math module run: v -silent -exclude @vlib/math/*.c.v test vlib/math/ - name: Self tests run: v -silent test-self vlib - name: Test v->js run: v -o hi.js examples/js_hello_world.v && node hi.js - name: Test v binaries run: v build-vbinaries - name: Build examples run: v build-examples - name: v2 self compilation run: v -o v2.exe cmd/v && .\v2.exe -o v3.exe cmd/v ================================================ FILE: .github/workflows/windows_ci_tcc.yml ================================================ name: CI Windows TCC on: push: paths-ignore: - '**.md' - '**.yml' - '!**.bat' - '!**/windows_ci_tcc.yml' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' pull_request: paths-ignore: - '**.md' - '**.yml' - '!**.bat' - '!**/windows_ci_tcc.yml' - '!**/windows-install-sqlite.bat' - 'cmd/tools/**' - '!cmd/tools/builders/**.v' concurrency: group: windows-${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.sha || github.ref }} cancel-in-progress: true jobs: tcc-windows: runs-on: windows-2022 timeout-minutes: 60 env: VFLAGS: -cc tcc -no-retry-compilation VTEST_SHOW_LONGEST_BY_RUNTIME: 3 VTEST_SHOW_LONGEST_BY_COMPTIME: 3 VTEST_SHOW_LONGEST_BY_TOTALTIME: 3 steps: - uses: actions/checkout@v6 - name: Build with make.bat -tcc run: | .\make.bat -tcc .\v.exe symlink - name: All code is formatted run: v -silent test-cleancode - name: Test new v.c run: | v -o v.c cmd/v .\thirdparty\tcc\tcc.exe -Werror -w -ladvapi32 -lws2_32 -bt10 v.c - name: Install dependencies run: | v retry -- v setup-freetype .\.github\workflows\windows-install-sqlite.bat - name: v -g self run: v -g self - name: v doctor run: | v doctor - name: Verify `v test` works run: | v cmd/tools/test_if_v_test_system_works.v .\cmd\tools\test_if_v_test_system_works.exe - name: Verify `v vlib/v/gen/c/coutput_test.v` works run: v vlib/v/gen/c/coutput_test.v - name: Make sure running TCC64 instead of TCC32 run: v test .github\workflows\make_sure_ci_run_with_64bit_compiler_test.v - name: Test ./v doc -v clipboard *BEFORE building tools* run: v doc -v clipboard - name: Test v build-tools run: v -silent -W build-tools - name: Test pure V math module run: v -silent -exclude @vlib/math/*.c.v test vlib/math/ - name: Self tests run: v -silent test-self vlib - name: Test v->js run: v -o hi.js examples/js_hello_world.v && node hi.js - name: Test v binaries run: v build-vbinaries - name: Build examples run: v build-examples - name: v2 self compilation run: v -o v2.exe cmd/v && .\v2.exe -o v3.exe cmd/v && .\v3.exe -o v4.exe cmd/v ================================================ FILE: .github/workflows/workflow_lint.yml ================================================ name: Workflow Lint ## Note: to install `prettier` locally, see https://prettier.io/docs/en/install, ## or just: `npm install --save-dev --save-exact prettier` ## If you already have `prettier` installed, to run it locally, ## just run: `npx prettier --check **.yml` . on: push: paths: - '**.yml' pull_request: paths: - '**.yml' jobs: lint-yml-workflows: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Verify formatting uses: creyD/prettier_action@v4.6 with: prettier_options: --check **.yml ================================================ FILE: .gitignore ================================================ # ignore sub-level build binaries and v binary */**/* v v.exe v2 v2.exe vdbg vdbg.exe !*/ !*.* *.exe *.o *.so .*.c *.tmp.c *.obj *.exp *.ilk *.pdb *.dll *.lib *.bak *.dylib a.out .noprefix.vrepl_temp # ignore v build files /vc /v.c /v.*.c /v.c.out /v_old /v_old.exe /vold /vold.exe /vnew /vnew.exe /vprod /vprod_gcc /vprod_clang /vprod.exe /vprod_gcc.exe /vprod_clang.exe /vprod_msvc.exe .vrepl_temp.v fns.txt .noprefix.vrepl_temp.v # ignore temp and cache directories temp/ tmp/ cache/ # unignore special files without extension !.github/PULL_REQUEST_TEMPLATE !.editorconfig !.gitattributes !.gitignore !BSDmakefile !Dockerfile !Dockerfile.alpine !Dockerfile.cross !LICENSE !Makefile !GNUmakefile # ignore editor files .idea .project .classpath .c9 .vs *.launch .settings/ *.sublime-workspace .vscode/ *.code-workspace *~ ~* .sesskey tmp* *.db *.swp *.swo *.swn .env # ignore debugger files cachegrind.out.* .gdb_history *.dSYM *.def vgcore.* # ignore system files .DS_Store ._* thumbs.db /.symlink /.bin _docs # ignore vs databases *.suo *.VC.db *.rsp # ignore cmd/tools/.disable_autorecompilation, which some package managers use. cmd/tools/.disable_autorecompilation test.bin # ignore codespace env .venv/ .direnv/ shell.nix default.nix flake.nix .envrc # generated by thirdparty/stdatomic/nix/cpp/gen.v thirdparty/stdatomic/nix/cpp/*.h # ignore thirdparty libs that are distributed separately thirdparty/binaryen* thirdparty/wabt* thirdparty/tcc/ thirdparty/sqlite/ # ignore VLS log vls.log # ignore v2go tmperror files *.tmperr */**/tmp.* # ignore Intellij files .idea/ /*.iml #ignore generated files: wasm.v # ignore large GTK *.gir files Gtk-4.0.gir *.gir vlib/builtin/js/*.js vlib/v/tests/*.js #ignore tags indexes, used by emacs/vim: ETAGS TAGS tags # ignore the old regexp based v.ctags file (people using universal ctags < 6.1.0, can still benefit from them) .ctags.d/v.ctags # ignore .NET7.0 Assembly Files bench/vectors/bin bench/vectors/obj autofuzz.log .project.gf .aider* #ignore common file names for bugs/reproductions bug* issue* # ignore cmd2/v stuff cmd/v2/*.txt cmd/v2/*.json ================================================ FILE: AGENTS.md ================================================ # V Repo Guide Practical quick reference for the V compiler, standard library, and tools. Written for AI coding agents; useful for humans too. ## Contents * Quick Start * Top Rules * Agent Rules * Safety (Do Not Brick the Repo) * Divergences From Repo Docs * Quick Decisions * Common Workflow * Reporting * Prerequisites * Build & Rebuild * Run Programs * Testing * Code Style * Modules and Imports * C/JS Interop Hygiene * Environment-Specific Code (files and `$if`) * Compile-Time Code and Reflection * Debug * Compiler Architecture * Key Directories * Test Locations * Error Reporting (checker/parser) * Option/Result Types * Tools * Commits and PRs * Environment Variables * Gotchas ## Quick Start Get operational from the repo root in three steps: 1. Build once (only if `./v` is missing): `make` 2. Build a working compiler: * Debug-friendly (recommended): `./v -g -keepc -o ./vnew cmd/v` 3. Use `./vnew` for everything: * Run a file: `./vnew run examples/hello_world.v` * Run tests: `./vnew -silent test vlib/v/` * Format: `./vnew fmt -w path/to/file.v` Then read Top Rules and Agent Rules before making changes. ## Top Rules * Use `./v` only to build `./vnew`; use `./vnew` for everything else. * Put all V flags immediately after `./vnew` and before the subcommand/file, e.g. `./vnew -g run file.v` (not `./vnew run file.v -g`); flags after the subcommand are passed to that subcommand. * Rebuild `./vnew` after compiler or core module changes (see Build & Rebuild). * Run the smallest relevant tests; see Testing for triggers and minimums. * Ask before large refactors or wide file touches (see Agent Rules). * Do not stash or modify unrelated files unless explicitly instructed. * This guide assumes agents run locally, not in CI; CI notes are informational only. * When a summary is required, include behavior change, tests run, and touched file paths. * If instructions overlap, prefer Build & Rebuild, Testing, and Reporting. * If duplicates drift, treat Build & Rebuild, Testing, and Reporting as canonical and align other sections to them. ## Agent Rules ### Repo root All commands assume the repo root as the working directory. The default location is `/opt/v`, but this may differ in your environment. If a command fails due to missing paths, verify with `pwd` and adjust accordingly. Use a per-command workdir only when a task requires a subdir. ### Tone and output * Be concise by default. If the user asks for depth, provide it while keeping structure tight. * Keep output easy to scan: short sections, bullets when listing, commands in backticks, no filler. * Use a strict, operational tone unless higher-priority instructions override it. * Ask only when required. If information is missing, ask a direct question. ### File access and edit scope * You may read and edit all files in the V repo without asking for permission. This is file access, not change scope; scope is constrained below. Reading is always OK. Edits to `ci/` or `Dockerfile*` still require an explicit ask. * Run build, test, and format commands without asking for permission. These are validation steps, not code changes. Only ask about edit scope, not about running `fmt`, targeted tests, or `check-md`. * Only modify files required for the user request; avoid unrelated refactors. If duplication is harmful, small refactors to remove it are OK only when needed. Only refactor duplication in code you are already touching, and only when it directly supports the request or fixes a bug there. "Touching" means files already modified for the request. * Avoid unrelated file changes; call them out if present. * Avoid touching `thirdparty/` unless explicitly requested. If changes are needed there, ask for approval before proceeding. ### When to ask * Ask before large refactors or wide file touches (more than 5 files, or changes across multiple repo-root directories like `cmd/`, `vlib/`, `doc/`, `examples/`). Exception: docs-only changes across many files are OK without asking; call them out in the summary. * Ask before large behavioral changes within a single subsystem or file, even if the file count is small. Examples: changes to parser rules, checker resolution, codegen output shape, diagnostic text/ordering, or tool CLI behavior. Large means user-visible changes in CLI flags, output, diagnostics, or codegen shape. If unsure whether a change is "large," ask. * Ask before touching `ci/` or `Dockerfile*` unless explicitly requested. If changes are needed there, confirm whether local validation is expected or if CI-only coverage is acceptable. ### Bootstrap * Bootstrap/compiler usage rules: see Top Rules and Build & Rebuild. ### Completeness and summaries * If you cannot complete a requested step, state the blocker and partial progress (what was attempted and what remains). * After substantial work, provide a short summary and list touched file paths. Substantial work means any behavioral change, or changes in more than one file. Always include tests run (or "Not run" with reason) in the summary. * Never change tests just to silence failures. Update expectations only when behavior changes are intended, and note the rationale in the summary. ### New files and deeper guidance * New file checklist: format with `./vnew fmt -w`, add doc comments for any public functions, run `./vnew check-md` for markdown files, and keep Markdown lines <= 100 chars. Add or update tests when introducing a new public API. * For deeper edge cases, consult `CONTRIBUTING.md` and `TESTS.md`. ## Safety (Do Not Brick the Repo) * Do not overwrite the working `./v` binary. * Never run `./v self` without `-o`. * Build with `./v -o ./vnew cmd/v`, then use `./vnew` for all checks. * Keep generated C when debugging backend issues: add `-keepc`. * Avoid hidden/bidirectional Unicode characters in source/markdown files. * If the compiler becomes unusable, recover with: 1. `git stash` 2. `make` 3. `git stash apply` Check `git status` before stashing to avoid hiding unrelated work. Do not stash unless explicitly instructed or the compiler is bricked. ## Divergences From Repo Docs The repo docs use `v` in examples. In this environment: * Use `./v -g -keepc -o ./vnew cmd/v` instead of `v self`. * Use `./vnew` for all builds, runs, and tests. * `TESTS.md` suggests `v test-all` before PRs; ask before running `./vnew test-all`. These overrides exist to keep agent workflows reproducible and to avoid breaking the bootstrap compiler. ## Quick Decisions * For rebuild and test choices, follow Build & Rebuild and Testing. * Follow Common Workflow for the default execution order. * For broader workflow guidance, see `CONTRIBUTING.md`. ### Compact decision table (rebuild/tests) Use this table to pick the minimum rebuild/tests quickly. See Build & Rebuild and Testing for full details and edge cases. Commands omit `./vnew` for brevity; assume the `./vnew` prefix. This table is the minimum set; check Testing for additional triggers. REPL and backend changes have additional triggers in Testing. Note: `cmd/v/` is compiler scope; treat changes there as compiler changes. When in doubt, ask before proceeding. If you read only one section for tests, **read Testing**. | Change area | Rebuild? | Minimum tests to run | | --- | --- | --- | | Docs only (`.md`) | No | `check-md file.md` | | Compiler (`vlib/v/`, `cmd/v/`) | Yes | `-silent vlib/v/compiler_errors_test.v`; `test vlib/v/` | | Core modules (builtin/strings/os/strconv/time) | Yes | Smallest relevant tests | | Parser-only (`vlib/v/parser/`) | Yes | `test vlib/v/parser/` | | Checker-only (`vlib/v/checker/`) | Yes | `test vlib/v/checker/` | | Comptime (`vlib/v/comptime/`) | Yes | `test vlib/v/tests/`; comptime-related tests | | vlib (non-compiler) | No | Nearest `*_test.v` or `test vlib/path/` | | Tools (`cmd/tools/`) | No | Tool-specific test; else nearest `*_test.v` | | Diagnostic/output changes | Yes | `vlib/v/slow_tests/inout/compiler_test.v` | | C codegen (`vlib/v/gen/c/`) | Yes | `vlib/v/gen/c/coutput_test.v` | ## Common Workflow 0. Before work: `git status`; ensure `./vnew` exists; rebuild if needed. If `./vnew` is missing, see Quick Start or Build & Rebuild. 1. Edit the relevant files. 2. If compiler sources or core modules changed, rebuild `./vnew` with `./v -g -keepc -o ./vnew cmd/v` (see Build & Rebuild). 3. Format touched `.v`/`.vsh` files and run `./vnew check-md` on touched markdown. 4. Run the smallest relevant tests for the change scope (see Testing). See Build & Rebuild for rebuild triggers and flags. ## Reporting * When a summary is required (see Agent Rules), it must include: * Behavior changes (or "No behavior change"). * Tests run (or "Not run" with a reason). * Touched file paths. * Note unrelated changes if present. * Note doc updates if public behavior/tool output changed. * If public behavior or tool output changes, update relevant docs (README.md, `doc/`, `tutorials/`) and note it. For example: README.md for top-level CLI usage, `doc/` for compiler/tool docs, `tutorials/` for learning material. * If you add or change a public API, update module docs or README and note it. Public API includes stdlib functions/types and user-visible compiler flags, diagnostics, tool CLI behavior (including `cmd/tools` and stdlib CLI tools), or output formats. * Update `CHANGELOG.md` or `ROADMAP.md` only when explicitly requested. * Public behavior includes compiler output, diagnostics, user-facing CLI, and stdlib API. This includes developer-facing flags, error codes, or output ordering changes. * Internal refactors with no public behavior change do not require doc updates. * If unsure whether behavior is public, ask the user before updating docs. * Acceptable reasons for not running tests: docs-only change, no relevant tests, or environment constraints. Be specific. * Docs-only changes: run `./vnew check-md file.md`; no other tests required unless a test explicitly reads those docs. No rebuild is needed unless compiler or core modules changed. * For docs-only, explicitly mention `check-md` in the summary. * If you update `.out` files, state the rationale in the summary. * Do not update `.out` files unless a behavior change is intended; otherwise treat mismatches as regressions. * Example summary line: `Behavior change: none` or `Behavior change: fixed X`. * Behavior change includes output, API, error messages, and test expectations. * If blocked, note what was attempted and why it failed. * If tooling/network restrictions block a step, state the restriction and the closest viable alternative. * Use `git status` to confirm touched files before reporting. ## Prerequisites * Toolchain: `make`, `git`, and a C compiler (`clang` or `gcc`). * Windows: use `make.bat` for the initial build. ## Build & Rebuild * Initial build (only if `./v` is missing): `make` (Windows: `make.bat`). * Build `./vnew` (debug-friendly, recommended for agent workflows): `./v -g -keepc -o ./vnew cmd/v` * Never run `./v self` directly; only build `./vnew` with the commands above. * If `./v` is missing, run `make` first, then build `./vnew`. * If `./vnew` is missing but `./v` exists, run `./v -o ./vnew cmd/v`. * This section is the source of truth for rebuild triggers. If a rule appears elsewhere, defer to this section. * Rebuild triggers: * Compiler sources in `vlib/v/` or `cmd/v/`. * Core modules: `builtin`, `strings`, `os`, `strconv`, `time`. * If `./v` exists but compiler sources changed, still rebuild `./vnew` before tests. * If unsure whether compiler/core changes happened, rebuild `./vnew`. * Common flags: * `-g` debug info (V line numbers). * `-cg` debug info (C line numbers); often combined with `-keepc`. * `-keepc` keep generated C file(s). * `-prod` optimized build. * `-o file` output path/name. * `-cc clang` pick a C compiler. * `-cstrict` be stricter about the generated C. * `-b js|native|wasm` select a backend. * `-os ` cross-compile target selection (when supported). ## Code Style * Comments: add succinct comments only when code is not self-explanatory. Do not delete existing comments unless they are incorrect; you may fix grammar or spelling without changing meaning. Add V doc comments right before each new or modified public function or method. The V doc comments should start with the name of the fn, example: `// the_name does ...` * Copy pasta: avoid copy pasta. If there's duplicate logic, move to a function only when it is required for the request and within code you are already touching. * Avoid using `unsafe{ code }` blocks where possible, and minimize their scope. `unsafe` is acceptable for low-level interop (e.g. C pointer casts, manual memory management) but should never wrap ordinary V logic. When `unsafe` is required, keep the block as small as possible and add a comment explaining why it is necessary. * Keep Markdown lines <= 100 chars (the checker is strict). Apply to touched lines in modified Markdown files. * Avoid hidden/bidirectional Unicode characters in source/markdown files. * Non-V files: keep existing formatting; only reformat if required by the change. * Treat `.vv` files in `vlib/v/slow_tests/inout/` as fixtures; avoid formatting unless a behavior change is intended and output expectations are updated. * Formatting and check commands are in Tools. ## Modules and Imports * Module names must match their directory name (no hierarchy in the `module` line). Mismatches cause silent import failures. * Imports follow the folder hierarchy (e.g. `import abc.def`). ## C/JS Interop Hygiene * Avoid using `C.` or `JS.` symbols in plain `.v` files. * Use `.c.v` / `.js.v` files. * Enable `-Wimpure-v` to catch accidental impurity. * Do not refactor existing `C.`/`JS.` uses in `.v` files unless required. If you must change those lines, prefer moving the interop code to `.c.v`/`.js.v`. * For C interop, use correct `const_` prefixes in C function redeclarations when needed (helps with `-cstrict` and C static analysis tooling). ## Environment-Specific Code (files and `$if`) V supports environment-specific file suffixes. Prefer them when the whole file is platform/backend specific. Common patterns: * Backend splits: * `*.c.v` (C backend), `*.js.v` (JS backend), `*.native.v` (native backend), `*.wasm.v` (WASM backend) * OS splits: * `*_windows.c.v`, `*_linux.c.v`, `*_nix.c.v`, with `*_default.c.v` as fallback * Flag splits: * `*_d_customflag.v` is included only with `-d customflag` * `*_notd_customflag.v` is included only when that flag is NOT passed Notes: * Do not use combinatorial suffixes like `_d_flag_linux.c.v`; use `_d_flag.v` plus `$if linux {}` inside the file. * For smaller platform differences, use compile-time `$if` blocks: * `$if windows { ... } $else { ... }` * See Compile-Time Code and Reflection for the full `$if` reference. ## Compile-Time Code and Reflection V uses `$` as a prefix for compile-time (comptime) operations. These are evaluated by the compiler, not at runtime. AI agents frequently confuse comptime and runtime constructs; this section clarifies the boundaries. ### Compile-time `$if` `$if` evaluates conditions at compile time. It is not a runtime `if`. Use it for platform, compiler, and custom-flag checks: * `$if windows { ... } $else $if linux { ... } $else { ... }` * `$if debug { ... }` (enabled by `-g` or `-cg`) * `$if prod { ... }` (enabled by `-prod`) * `$if custom_flag ? { ... }` (enabled by `-d custom_flag`) Full list of builtin `$if` options: see the table at . Common mistakes: * Using runtime `if` where `$if` is needed for platform-specific code. Runtime `if` will fail to compile if it references platform-specific symbols; `$if` excludes the block entirely on non-matching platforms. * Forgetting the `?` suffix for custom flags: `$if myflag ? { ... }`. Without `?`, the compiler treats it as a builtin option and silently ignores it. ### Compile-time `$for` `$for` iterates over type metadata at compile time. It works with: * `StructType.fields` - iterate struct fields * `StructType.methods` - iterate struct methods * `EnumType.values` - iterate enum values * `StructType.attributes` - iterate struct attributes * `SumType.variants` - iterate sum type variants * `method.params` - iterate method parameters Inside `$for` blocks, use `$if` to branch on field/method types: ```v oksyntax fn main() { $for field in MyStruct.fields { $if field.typ is string { println(field.name) } } } ``` Also works with generics: `T.fields`, `param.fields` where `fn gen[T](param T) {}`. Common mistakes: * Using runtime `for` to iterate struct fields. This does not work; V has no runtime reflection. Always use `$for`. * Calling `obj.$method()` outside a `$for m in Type.methods` block. The `$method()` call is only valid inside a comptime method iteration. * Assuming comptime `$for` produces a runtime loop. It does not; the compiler unrolls it into concrete code for each field/method/variant. ### Compile-time functions Only the following `$`-prefixed functions are supported: * `$embed_file('path')` - embed a file's contents into the binary. Paths can be absolute, relative to the source file, or use pseudo variables like `@VEXEROOT` or `@VMODROOT`. * `$tmpl('path')` - compile a V template file (used by vweb/veb). * `$env('VAR')` - read an environment variable at compile time. * `$d('ident', default)` - read a `-d ident=value` compile-time define, with a default fallback. * `$res('path')` - embed a resource (Android). * `$compile_error('msg')` - emit a compile-time error. * `$compile_warn('msg')` - emit a compile-time warning. * `$pkgconfig('name')` - query pkg-config at compile time. Common mistakes: * Inventing comptime functions that do not exist (e.g. `$typeof`, `$sizeof` as comptime calls). Use `typeof(expr).name` and `sizeof(Type)` instead; these are builtins, not `$`-prefixed. * Assuming `$embed_file` returns a string. It returns an `EmbedFileData` object; use `.to_string()` or `.to_bytes()`. * Using `$env` where a runtime `os.getenv` is appropriate, or vice versa. `$env` is baked in at compile time and cannot change at runtime. ### Compile-time pseudo variables These are `@`-prefixed identifiers substituted at compile time: * `@FN` - current function name. * `@METHOD` - `ReceiverType.MethodName`. * `@MOD` - current module name. * `@STRUCT` - current struct name. * `@FILE`, `@DIR`, `@LINE`, `@COLUMN`, `@FILE_LINE` - source location. * `@LOCATION` - file, line, and current type+method; good for logging. * `@VEXE`, `@VEXEROOT` - path to the V compiler and its directory. * `@VHASH`, `@VCURRENTHASH` - compiler commit hashes. * `@VMOD_FILE`, `@VMODHASH`, `@VMODROOT` - nearest `v.mod` info. * `@BUILD_DATE`, `@BUILD_TIME`, `@BUILD_TIMESTAMP` - build time (UTC). Override with the `SOURCE_DATE_EPOCH` env var for reproducible builds. * `@OS`, `@CCOMPILER`, `@BACKEND`, `@PLATFORM` - build environment. ### Compile-time type groups Comptime type groups combine multiple types into a higher-level type for use in generic or comptime `$if` checks: * `$int` - all integer types * `$float` - all float types * `$array` - all array types * `$map` - all map types * `$struct` - all struct types * `$enum` - all enum types * `$alias` - all type aliases * `$sumtype` - all sum types * `$function` - all function types * `$interface` - all interface types * `$option` - all option types Example: `$if field.typ is $int { ... }` ### Comptime changes and testing Comptime logic lives in `vlib/v/comptime/` and is exercised by the checker, parser, and cgen stages. Changes here require a rebuild of `./vnew` and should be tested with `./vnew -silent test vlib/v/tests/` plus any comptime-specific tests. See the decision table and Testing. ## Run Programs * Compile and run: `./vnew run file.v`. * Just compile: `./vnew file.v` (creates executable). * With debug info: `./vnew -g run file.v`. * Debug run (C line numbers): `./vnew -keepc -cg run file.v`. * Example: `./vnew run examples/hello_world.v`. ## Testing Run: * File (shows test output): `./vnew path/to/file_test.v`. * File (test runner report only): `./vnew test path/to/file_test.v`. * Dir: `./vnew -silent test path/to/dir/`. * Dir with statistics/metrics: `./vnew -stats test path/to/dir/`. * Compiler: `./vnew -silent vlib/v/compiler_errors_test.v`. * Fix outputs (only when intended): `VAUTOFIX=1 ./vnew -silent vlib/v/compiler_errors_test.v`. * All: `./vnew test-all`. Ask before running `./vnew test-all` unless explicitly requested. When: * Rule of thumb: for localized changes, run the smallest relevant tests. If any trigger below matches, run the listed tests. * Minimum tests listed are the floor, not the ceiling; add targeted tests for cross-cutting changes. * If unsure which tests apply, ask the user before proceeding. * If in doubt, prefer the smallest targeted test and ask. * Run all tests that apply. Start with the smallest targeted tests; add slow tests as needed. Order does not matter. * Compiler changes (`vlib/v/` or `cmd/v/`): Run `./vnew -silent vlib/v/compiler_errors_test.v`, `./vnew -silent test vlib/v/`. * Parser-only changes (`vlib/v/parser/`): Run `./vnew -silent test vlib/v/parser/`. * Checker-only changes (`vlib/v/checker`): Run `./vnew -silent test vlib/v/checker/`. * vlib changes: Run nearest `*_test.v` or `./vnew -silent test vlib/path/`. * Tool changes (`cmd/tools/`): Run tool-specific tests. If none exist, run the smallest relevant `*_test.v` that exercises the tool. Note: `cmd/v/` is compiler scope, not tools. Examples: `cmd/tools/vfmt` -> `vlib/v/fmt/fmt_test.v` . `cmd/tools/vdoc` -> `cmd/tools/vdoc/vdoc_test.v`. * Diagnostic/output changes: Run `./vnew -silent vlib/v/slow_tests/inout/compiler_test.v`. * C codegen changes: Run `./vnew -silent vlib/v/gen/c/coutput_test.v`. Consider a stricter validation pass: `./vnew -cstrict -cc clang -silent test vlib/v/`. * REPL changes: Run `./vnew -silent vlib/v/slow_tests/repl/repl_test.v`. * Broad refactors: Run `./vnew -silent test-all`. * Backend-specific changes: run the smallest relevant tests for the affected backend. JS/native/WASM backends are incomplete, so avoid broad `-b test vlib/` runs. Prefer targeted `*_test.v` files or small test dirs with `-b js|native|wasm`. If time-constrained, prioritize `./vnew -silent vlib/v/compiler_errors_test.v` and the smallest targeted tests. Run `vlib/v/slow_tests/inout/compiler_test.v` and `vlib/v/gen/c/coutput_test.v` when output or codegen changes are likely. See `TESTS.md` for more guidance on test selection and output expectations. See `CONTRIBUTING.md` for broader workflow guidance. Concrete triggers: * `vlib/v/slow_tests/inout/compiler_test.v` when error text or output formatting changes, or changes in checker/parser error reporting. * `vlib/v/gen/c/coutput_test.v` for changes under `vlib/v/gen/c/` or C codegen output paths. Types: * Standard: `*_test.v` files with `test_` functions. * Output: `.vv` source + `.out` expected output in `vlib/v/slow_tests/inout/`. Example: `./vnew -silent vlib/v/slow_tests/inout/compiler_test.v`. * `vlib/v/tests/**` may use `.run.out` expectations; run with `./vnew -silent test vlib/v/tests`. Docs-only guidance: see Reporting. If time-boxed, run at least the smallest relevant test and note skipped coverage in the summary. ### Useful env variables and flags while testing * `VAUTOFIX=1` - Auto-update .out files when tests fail (run twice). Use only when a behavior change is intended. * `VTEST_ONLY=glob_pattern` - Run only tests matching pattern. * `VTEST_HIDE_OK=1` - Hide successful tests, show only failures. * `./vnew -silent test path/to/dir/` - Show only failed tests (if any), and a summary report. * `-cc tcc` can speed test builds when TCC is available. * Output expectations: update `.out` files only when behavior changes are intended; note the rationale in the summary. ## Debug * See what the C compiler is doing: * `-showcc` prints the C compile command. * `-show-c-output` prints the C compiler output. * Build a temporary compiler for debug flags: * `./vnew -o ./w -d trace_checker cmd/v` * Then run: `./w file.v` * Keep and inspect generated C: * `-keepc -cg` is the common combo. * `-printfn -o file.c` emits only the named C function to standart output. The `name` uses the `modulename__fnname` format (e.g. `main__main`). This flag can be repeated to print multiple functions. Methods/generics may use more complex C names; use `-keepc` to confirm exact symbols. * Trace stages: `-d trace_scanner|trace_parser|trace_checker|trace_gen`. These flags can help diagnose a problem when a stage stops earlier than expected. * Time stages: `-d time_parsing|time_checking`. * V panics: `-keepc -g`. * C segfaults: `-keepc -cg -cc clang`. * JS/native/wasm: prefer small, focused test files with `-b js|native|wasm` and `-show-c-output` where applicable; avoid broad `-b test vlib/`. * Quick code location technique: When debugging code generation issues, add unique comment tags to relevant code generation points (e.g., `/*tom51*/`) in the compiler source. Rebuild and generate C code, then search the generated file for these tags to quickly map generated C code back to the exact compiler source location. This is especially useful when multiple code paths generate similar-looking output and you need to identify which path is actually used. Example: ```v // In vlib/v/gen/c/assign.v: g.write('builtin___option_ok/*tom51*/(&(${styp}[]) { ') // After rebuild, search generated C code for "tom51": // builtin___option_ok/*tom51*/(&(int[]) { ... }); ``` Remember to remove these debug tags after fixing the issue. ## Compiler Architecture The V compiler has the following stages, orchestrated by the `v.builder` module: `v.scanner` -> `v.parser` -> `v.checker` -> `v.transformer` -> `v.markused` -> `v.gen.c` Their corresponding folders are: vlib/v/scanner, vlib/v/parser, vlib/v/checker, vlib/v/transformer, vlib/v/markused, vlib/v/gen/c . There are additional subsystems (supporting or optional compiler modules) like v.comptime, v.generics, v.pref, v.reflection, v.callgraph, etc. ### Key Directories * `vlib/`: Standard library (changes here can affect the compiler itself). * `cmd/v/v.v`: Compiler entry. * `cmd/tools/`: vfmt, vdoc, vup, vquest, etc. * `examples/`: Example programs. * `thirdparty/`: Bundled C libraries (tcc, mbedtls, sokol, etc.). * `vlib/v/`: Compiler modules. * ast/ - AST node definitions * fmt/ - Code formatter * scanner/ - Tokenizer * token/ - Token definitions * parser/ - Produces AST from tokens * checker/ - Type checking and resolution * comptime/ - Compile-time evaluation support * transformer/ - Common optimisations and simplifications, makes the backends simpler * markused/ - Dead code eliminator * gen/c/ - C code generation (primary backend, known as cgen) * gen/js/ - JavaScript backend * gen/native/ - Machine code generation (ELF, Mach-O) * gen/wasm/ - WebAssembly backend ### Test Locations * `vlib/v/tests/`: Compiler feature tests (including comptime). * `vlib/v/slow_tests/`: Output-matching and slow tests for the compiler. * `vlib/v/slow_tests/inout/` - Output comparison tests (.vv + .out pairs) * `vlib/v/parser/` - Parser error tests * `vlib/v/checker/` - Checker error tests * `vlib/v/gen/c/testdata/` - C codegen tests (.vv + .c.must_have) * `examples/compiletime/` - Comptime usage examples (including `reflection.v`) ## Error Reporting (checker/parser) * Error: `c.error('message', pos)` - hard error, stops compilation. * Warning: `c.warn('message', pos)` - warning, allows compilation. * Notice: `c.note('message', pos)` - informational only. * Pattern: Most checker methods use `fn (mut c Checker)` receiver. * Location: `vlib/v/checker/errors.v`. ## Option/Result Types * Syntax: `?Type` (optional, can be none) vs `!Type` (result, can error). * Common bugs: Unwrapping in if guards, struct init with option fields, ternaries with options. * When changing option/result behavior, add a regression test in `vlib/v/tests/`. * Tests: Search `vlib/v/tests/` for option/result test files. * Pitfall: Options in ternaries, SQL statements, and fixed arrays need special handling in cgen. ## Tools * Note: if a rule overlaps with Testing, follow Testing. * Format: `./vnew fmt -w ` for touched `.v` and `.vsh` files. Format only touched files unless explicitly asked to reformat broader scope. * Treat new files as touched for formatting and markdown checks. * Check *all* files are formatted: `./vnew -silent test-fmt`. Run only when asked or when validating the full tree. * Check markdown: `./vnew check-md file.md` for touched `.md` files (required before commits). * Code style checker: `./vnew vet vlib/v` Run only when asked or when making broad checker changes (more than 3 files in `vlib/v/checker/`). * Module docs: `./vnew doc -readme -all -l module_name`. * Search: `rg pattern` (or `git grep`); list files: `rg --files`. * Auto-format hook: `./vnew git-fmt-hook install`. ## Commits and PRs * See `CONTRIBUTING.md` for full commit message conventions and PR workflow. * Keep commits focused: one logical change per commit. * If your branch has diverged and a rebase or merge is needed, do not force-push or drop hunks without asking. State the conflict and let the user decide the resolution strategy. When in doubt, prefer `git rebase` over `git merge` for a linear history, but always ask if the situation is ambiguous. ## Environment Variables * VFLAGS: Pass flags to all V invocations (e.g., `VFLAGS='-g' ./vnew test-all`). * VEXE: Path to V compiler executable (useful in CI/scripts). * TMPDIR: Controls where `.tmp.c` files are written (V uses `TMPDIR/v/`). * SOURCE_DATE_EPOCH: Override build timestamp for reproducible builds (affects `@BUILD_DATE`, `@BUILD_TIME`, `@BUILD_TIMESTAMP`). * V2-specific: `V2CC`, `V2CFLAGS`, `V2VERBOSE` (for v2 development). ## Gotchas * Core modules (`builtin`, `strings`, `os`, `strconv`, `time`) can affect the compiler because it is a V program. Rebuild `./vnew` when they change. * Module names must match their directory name; mismatches cause silent import failures. See Modules and Imports. * Some V programs and tools hardcode `os.execute('v ...')` in their source. The `./vnew` workflow does not protect against these; if you encounter unexpected behavior from such calls, check whether the code is invoking the system `v` instead of `./vnew` and adjust accordingly. * Stale `./vnew` can cause confusing failures; rebuild if behavior seems off. * Output tests require exact matches; whitespace changes break tests. * Formatting reminders: follow Code Style for `fmt` and `check-md`. * C compilation errors? Check generated C with `-keepc` (creates `/tmp/*.tmp.c`; see also TMPDIR in Environment Variables). * Compile-time code (`$if`, `$for`, `$embed_file`, etc.) is a common source of AI mistakes. See Compile-Time Code and Reflection for correct usage and pitfalls. * Broken compiler? See Safety for the recovery sequence. * Consult `CONTRIBUTING.md` and `TESTS.md` for: * New tests or test infra changes. * Output tests or `.out` updates. * Broad refactors or compiler-wide changes. * Unsure which slow test runner applies to your change. ================================================ FILE: CHANGELOG.md ================================================ ## V 0.5.1 *9 Mar 2026* #### Improvements in the language - New clean and fast v2 backends: cleanc (similar to the old C backend), ssa/arm64, ssa/amd64, cleanc backend can already self host! - Add a new generic solver stage (gated behind `-new-generic-solver`) (#26280) - Refactor $var to ${var} across entire repository, make vfmt always output the newer form `${expr}` (#26494) - Fix support for match exprs with nested if exprs (#26599) - Add OS-specific headers support for #include directives (#26654) (fixes #26562) #### Checker improvements/fixes - Fix compiler panic on wrong arg count with or block (#26665) - Support gotodef for fn param and []Type (#26193) - Error for unwrapped option/result types used with in operator (fix #26208) (#26223) - Expand @VEXEROOT, @VMODROOT, DIR, $d(), $env() inside $embed_file(path) too (#26319) - Fix global empty const type check (fix #26324) (#26332) - Add error message call stack support (requested by #16127, #24575, etc) (#26356) - Fix option in struct member infix expr and swapped none comparion (fix #26351) (#26373) - Disallow `foo()? == foo` where foo returns `!string` (fix #26383) (#26403) - Unset `@VCURRENTHASH` for V build/bootstrapped outside of a Git repository (fix #26407) (#26426) - Check generic struct fields and initialisation (fix #26433) (fix #26436) (#26450) - Preserve mut in other non-none if branch (fix #26491) (#26495) - Fix sql statement using an unwrapped option value from an if guard (fix #26496) (#26505) - Add type checking for param of fn passed as generic arg (fix #26195) (#26257) - Add warning for `fn f(x u8) {} f(999)` (fix #26584) (fix #26585) (#26586) - Add passes for top level decls (fix #26306) (#26589) - Avoid panic on unresolved infix operand types in -check (fixes #26458) (#26607) - Fix shared array slice type with implicit clone (fixes #26663) (#26666) - Fix autofree crash with option/result method chains (#26694) #### Parser improvements - Disallow `[3]!int{}` (fix #26244) (#26249) - Get correct generics for generics struct fn with generic param (fix #26191) (#26251) - Fix dump() free bug for v.ast.TypeSymbol (fix #26282) (#26283) - Disallow `[T]` as fn return type (#26530) - Show where another declaration is located (fixes #26483) - Fix `pub:` not being detected in structs in -vls-mode (#26581) - Fix anonymous function name collisions across files (#26642) - Remove @[minify] from structs with enum fields (#26661) #### Compiler internals - v.comptime,v.generics: unwrap receiver type, support more generic comptime exprs (#26350) - v.generic: improve new generic stage, unwrap generic ident info, set ct_expr to false if solved, update receiver_type generic flag (#26366) - v.generics: improve the new generics stage, by fixing unwrapping in nested generic struct, also fix suggestions from previous PR (#26430) - table: fix generics crash (fix #26438) - markused: add array method map and filter support (fix #26233) (#26238) - v.pref: exit early with an error message, if coroutines are not supported yet on the current platform, instead of producing a cgen error (#26342) - builder: fix compile error message for -m32 (fix #16639) (#26353) - v.builder: add -stats for top level statements and non-vlib top level statements (#26451) - v.pref: improve musl detection; fixes __atomic_thread_fence for all musl nixes (fix #26449) (#26460) - v.builder: always apply -fno-strict-aliasing too, on `-cc gcc -prod` to avoid the need for the `-cflags -fno-inline-small-functions` workaround with gcc > 12.0 (fix #26512) (#26552) - v.scanner: optimise ident_dec_number, ident_oct_number, ident_hex_number, by using precomputed digit_table and letter_table consts, instead of u8 method calls - v.scanner: eliminate str_helper_tokens changes outside string interpolation (fix speed loss after 106da40) - markused: add typ==0 guard for MapInit to fix panic in comptime $else branch (#26652) #### Standard library - builtin.closure: improve ppc64le closure if PIE (#26172) - rand.xoroshiro128pp: prevent generation of extra zeros in u16() (#26229) - thirdparty: fix tcc __atomic_thread_fence (fix #25856) (fix #26158) (#26185) - builtin.closure: use volatile register for s390x (fix #24383) (#26256) - thirdparty: update zstd patch with commit 8aa0369 (#26312) - regex.pcre: add non-greedy quantifiers like `*?`, `+?`, `??` (fix #26579) (#26582) - regex.pcre: optimise for speed the PCRE implementation (#26609) - atomic: and/or bitwise ops (#26646) - x.json2: add a `strict: true` mode for x.json2.decode(), that rejects string-to-number type casting during decoding (fix #26082) (#26220) - builtin: add array.last_index() (#26252) - bitfield: fix pop_count(), add test (#26262) - io: deprecate the `io.string_reader` module (not used in vlib, with confusing and under tested/documented API - see #25713 ) (#26274) - time: add Duration.times/1 - os: add Pipe.write_string/1 (#26286) - gg: add .draw_ellipse_filled_rotate and .draw_ellipse_empty_rotate APIs (#26309) - gg: add draw_ellipse_thick and draw_ellipse_thick_rotate (#26327) - os: fix args quoting in win_spawn_process (fix #26261) (#26339) - gg: optimize ellipses draw functions (#26340) - gg: text_width_f - math: fix acosh() for 0.0 (#26360) - math: rewrite round() to match closely the Go version (and mpfr's one), update test (#26381) - gg: optimise the ``draw_rounded_rect_filled`` function (#26390) - os: add missing is_opened checks to File.read* functions (fix #26096) (#26413) - x.json2: add `@[json: name]` attr support for enum values (fix #26437) (#26441) - x.json2: rename Any.arr() to Any.as_array() for consistency with as_map(), as_map_of_string(); deprecate Any.arr() (#26455) - breaking,x.ttf: extract vlib/x/ttf/render_sokol_cpu.v in a separate module x.ttf.render_sokol, to enable headless programs, that do not use gg, to not depend on OpenGL, DX12, Metal etc, through sokol (#26477) - crypto.blake3: add @[direct_array_access] and improve f() performance (#26480) - crypto.rc4: add `@[direct_array_access]` (#26507) - x.crypto.slhdsa: fix slh signature testing on latest version (fix #24086) (#26519) - crypto.pbkdf2: replace a panic with an error return (#26526) - regex: fixed missing OR operation on anchor flag (#26540) - regex: new PCRE compliant regex submodule written in pure V, available through `import regex.pcre` (#26545) - x.json2: fix decoding wrong value depending on field order (fix #26503) (#26571) - crypto: add shake128 and shake256 entries into crypto.Hash enum (#26576) - vlib: add x.atomics - implement native_x86-64_atomics in V and assembly, without depending on an external C library (impl #26474) (#26529) - os: use _dyld_get_image_name() to increase compatibility with older versions of Mac OS X like 10.4 (#26617) - crypto: move up AEAD interface from experimental namespace to `cipher.AEAD` (#26632) - builtin: fix `camel_to_snake` underscore placement in uppercase runs (#26634) - time: parse_http_header_string (#26636) - flag: add DocOptions/Show to FlagParser (#26630) - runtime: fix issues with nr_cpus() (#26679) - thirdparty,sokol: add wayland support (#26682) - thirdparty,sokol: fix frame pacing issues on xwayland sessions, prevent sending some keycode events on wayland (#26706) #### Web - net: add raw sockets support (implement feature request from #19565) (#26237) - veb: remove 2 clones of response bodies; reduce the GC load for the most common case (fix #25423) (#26236) - wasm: support basic match keyword handling (#26246) - wasm: fix infinite loop using continue in C-like for loops (#26250) - wasm: add basic `for x in start .. end {` support (#26248) - wasm: implement basic string operations (#26260) - veb: fix double-send error when after-middleware sends response (#26270) - builder,wasm: fix pointer size to 4 for `-b wasm` before the checker stage (#26281) - wasm: support basic string interpolation (#26288) - wasm: fix string plus assign with call expr (#26287) - wasm: handle `for` in strings and FixedArrays (#26290) - wasm: support WASI program arguments and IO functions (#26294) - net.mbedtls: increase default timeout to 10s (like in Go): 550ms was too low - net: add jsonrpc module (#26330) - fasthttp,veb: static files via sendfile - wasm: fix size of pointers in structs (#26357) - thirdparty.mbedtls: upgrade to v3.6.5 (#26365) - wasm: only compile `.wasm.v`, and platform independent `.v` files (#26386) - fasthttp: fix sendfile (#26402) - wasm: add run support with wasm-micro-runtime/iwasm (#26417) - veb: fix unset Content-Length header, in responses with an empty body (#26431) - veb: fix error lines for html templates via source to source mapping - net.http: enable test for relative redirects (#26513) - fasthttp: fix IPv6 support (fix #26548) (#26549) - mbedtls: better ux around client timeout by mentioning the mbedtls_client_read_timeout_ms flag (#26574) - Document `$veb.html()` too in the compiler error messages, as a known comptime function (#26605) - fasthttp: remove zero-byte initialization in read buffer #26640 - net.http: stop reading after Content-Length bytes on keep-alive responses (#26669) #### ORM - Add explicit JOIN support (INNER, LEFT, RIGHT, FULL OUTER) (fix #21635) (#26400) - Support embedded structs - Make work with generic structs - Fix generic struct creation inside a generic function - Resolve generic inserting object type - Cgen bug fix (fixes #25847) - Handle inserting enum fields (#26680) - Add aggregate function support (#26697) - Add transaction API with savepoint-backed nesting (#26707) #### Database drivers - mysql: use correct link flag for both tcc and msvc (#26539) - pg: exec_no_null(); gx: remove deprecated test; parser/tmpl: %raw translations; veb: time_to_render() - fix(db.sqlite): replace vstring() with tos_clone() to prevent use-after-free (#26700) - feat(db.sqlite): add Row.names, get_string/get_int, and improve exec_map (#26702) #### C backend - Fix multi dim fixed array with opt elem (fix #26243) (#26258) - Fix array.contains() when right is ref (fix #26253) (#26255) - Ast,checker,cgen,parser: fix comptime $if assign expr (fix #26061) (#26242) - Promote non generic sumtype pointer initialiations to the heap too (#26285) - Fix generic function error propagation type mismatch (fix #26263) (#26295) - Fix interface pass string ref arg (fix #26293) (#26296) - Fix shared array assigned call expr with fixed array (#26320) - Fix fixed array of option with different size (#26326) - Fix call with fixed array of builtin struct (#26328) - Fix array init with option array (fix #26329) (#26331) - Fix alias indent (fix #26272) (#26333) - Fix chan autostr (fix #26337) (#26338) - Transformer,markused,cgen: fix some problem for array init when use `-new-transformer` (#26341) - Fix `-assert backtraces` after e317c63 - Fix for function-like macro '_BIONIC_AVAILABILITY_GUARD' which is not defined in older termux releases (#26345) - Fix empty shared struct init (fix #16234) (#26354) - Add rv32 inline assembly support (#26362) - Fix fn arg for struct nested fields (fix #26346) (#26349) - Fix `+=` overloading for aliases, regression after 29e60da #23967 (fix #26416) (#26423) - Fix unused functions returning fixed arrays of custom structs (fix #26439) (#26440) - Fix or-block with fixed array constants with GCC 15.2 (fix #26442) (#26443) - Fix uninitialized interface bug (closes #17372) - Fix regression in `./v test vlib/toml` after 38ac4e6 (#26485) - Fix generation of struct initialisers for structs with option fields, inside ternaries (fix #26476) (#26493) - Fix the saving of g.skip_stmt_pos and g.stmt_path_pos when generating anonymous fns (fix #26498) (#26508) - Fix generic type handling bugs - Fix -autofree used for code doing "string ${f(@VEXE)} interpolation" (#26521) - Fix multi-return match in closure (fix #26558) (#26566) - Fix alias for interface and option types (fix #26551) (#26565) - Autofree fix generic math.min[T] used with time.Time (fix #26575) (#26577) - Fix extra dereference when indexing array of fns passed by pointer (fix #26556) (#26591) - Fix orm shared conn on sql expr (fixes #26479) (#26610) - Fix comptime match assign in generic fn, T.name string intp (fix #26053) (#26597) - Fix bit-field generation for option/result types in minified st… (#26670) - Use unsigned int for enum bit fields or unspecified size in @[minify] structs (#26678) - Fix auto-deref var in autofree string re-assignment (#26689) #### vfmt - Fix parser failing on duplicate methods in $if/$else blocks (fix #26271) (#26278) #### Tools - vwatch: fix process handle leak in kill_pgroup() (#26269) - vwatch: fix `-o` short flag conflict that broke hot reload (fix #26221) (#26277) - vcomplete: add git-fmt-hook command (#26396) - vrepl: fix handling of `//` inside string literals (fix #25603) (#26240) - v.help: add help for git-fmt-hook tool (#26394) - Add support for `v missdoc @vlib` - Add support for `v quest` - Add support for `v install --local gui` - Support .vcheckignore pattern files for `v check-md .` (#26623) #### Operating System support - msvc: split multi-token -I/-L values from pkg-config (#26637) - wasm: fix path separator in windows (#26264) - time: fix overflow in time.sys_mono_now() on windows (#26273) - sokol: fix errors for audio unsupported on OpenBSD (fix #26299) (#26305) - db.pg: improve support on OpenBSD (#26316) - os: fix get_raw_line for EOF on OpenBSD (fix #26361) (#26368) - Add support for vgit-fmt-hook on OpenBSD (fix #26344) (#26388) - builtin: use -Xlinker flags on macos, for compilers != tcc, to pass the rpath folder (fix for folders with spaces) - builtin: fix for tcc builds on paths with spaces on linux - os: implement readlink/1 on !windows (#26405) - builtin: fix compilation with tcc on OpenBSD using libgc (fix #26447) (#26448) - fasthttp: multi threading fix reads in the socket in linux (#26478) - time: prevent linux time functions from being included in non-linux platforms (#26596) - Fix hanging when printing to console in a `-subsystem windows` executable (#26572) - builder: fix Windows pkgconfig paths and MSVC flags (#26631) - net.vschannel: chunk large TLS payloads to fix 16KB EncryptMessage crash on Windows (#26681) #### Examples - examples,strings: add a new `strings.lorem` module; use it in the Markov chain text generator example (#26387) - Add examples/gg/pong/pong.v (#26528) - Improve pidigits.v using a much faster spigot algorithm - sokol: fix `v run examples/2048/` on macos (regressed after 5d6de17) (#26705) ## V 0.5.0 *31 Dec 2025* #### Improvements in the language - Add comptime `if is shared` support (fix #25600) (#25602) - Make `defer{}` scoped by default, use `defer(fn){}` to get the old behavior #25639) (#25665) - Add gotodef support for nested struct members, fn return types, etc (#26131) - Add a new v.comptime stage `COMPTIME`, that runs after the checker (`CHECK`), and before the transformer (`TRANSFORM`), to simplify the work that later stages do #26068 (#26161) #### Checker improvements/fixes - Correctly detect variadic arg passed to struct fn (fix #25504) (#25509) - Fix $(field.name) access on closure fn (fix #25513) (#25514) - vls: skip unrelated files (#25531) - Fix mutability in `for in` loops with pointer values (fix #25520) (#25536) - Fix type inference, when pushing an empty array to a 2D array (fix #23854) (#25508) - Prevent array.insert for array of references when non-reference is passed (fix #25511) (#25557) - Add more support for mod autocomplete, allow for .vv files too (#25562) - Fix cast from an empty struct to option (fix #25566) (#25581) - Ensure ?Struct is not parsed as ??Struct when param is ?T (fix #25559) (#25564) - Fix if branch type nr_muls mismatch (fix #25556) (fix #25555) (#25571) - Fix comptime else branch handling (fix #25586) (#25589) - Smart detect `or {}` inside loop when using `c <-val` (fix #24550) (#25435) - Vls fix goto definition (#25595) - Fix generic resolve for external module generic static method call (fix #21476) (#25634) - Correctly detect type, when prepending to generic array (fix #25585) (#25645) - Allow cast from voidptr to sumtype in unsafe block (fix #25652) (#25657) - Disallow calls to a shared receiver method, on a non-shared var (fix #25577) (#25656) - Fix or block endwiths expr (fix #25329) (#25667) - Set ast file fallbacks for vls (fix #25678) (#25679) - Error/warn when using `defer(fn)` inside function-scope and `lock` stmts (#25681) - Maintain correct ref level in generic fn (fix #25676) (#25687) - In vls mode, make ensure_type_exists return true (#25695) - Only collect/hoist inner vars, when `defer` is function-scoped (#25693) - Improve type checking for sumtypes with generics (fix #25690) (#25699) - Unwrap for base type if ft.typ and inferred_typ are both opt (fix #25517) (#25728) - Disallow deference of nil (fix #25740) (#25746) - Fix comptime main fn (#25747) - Parser,fmt,checker: use a trie for matching the generic array methods `all`, `any`, `count`, `filter`, `map`, `sort` and `sorted` (#25759) - Fix array fixed unresolved return check and resolver (fix #25774) (#25790) - Allow explicit sumtype to option casts (fix #25796) (#25812) - Fix possible race on expected arg types unwrapping on cgen (#25815) - Skip init check for options (fix #25798) (#25830) - Fix module var set at change_current_file() (fix #25845) (#25846) - Improve handling of array decompose for dynamic arrays and array init (fix #25838) (#25843) - Force all fn declarations to follow after all other top level statements (fix #25889) (#25890) - Fix used features tracking when printing pointer values (fix #25899) (#25901) - Match type when auto deref occurs (fix #25913) (#25916) - Relax the redundant () check to a notice, to enable a future `v -W test vlib/builtin` job on the CI - remove () from match branch exprs (fix #25950) (#25952) - Fix array map anon fn return fixed array (fix #25928) (#25977) - Cleanup the output of `v new --web abcd` after feedback from https://youtu.be/IuE6Bo1klK0?t=555 - Allow assign to a shared int var (fix #25986) (#25988) - Ensure type of global exists (fix #25910) (#25998) - Ensure fn pointer cannot be used as non-fn argument (fix #26017) (#26022) - Make sure `$for` eval body statements at least once to set types and avoid markused issues later (fix #26058) (#26063) - Fix return static method name (fix #26105) (#26110) - Support gotodef for struct init and sumtype rhs (#26157) - Detect circular type references in sumtype declarations (fix #24511) (#26162) - Add interface type handling and new testcase (fix #24116) (#26165) - Allow enum fields to reference previously declared fields (fix #25241) (#26173) - Clear all ref from autostr receiver_type (needed by #25857) (#26202) - Allow for `_` being used as both `import x as _` and `fn f(_ int) {` (fix (#26219) #26230 #### Parser improvements - Fix vls mode strut mut keyword (fix #25548) (#25551) - Fix vfmt comment in struct init after the update expr (fix #24361) (#25668) - Fix infix expr comment in middle (fix #24183) (#25671) - Disallow using generic functions as a field type name inside struct decl (fix #25452) (#25705) - Warn on `@[deprecated_after]` used without a corresponding `@[deprecated]` attribute (#25712) - Fix last stmt is fn call in or_expr (fix #25732) (#25739) - Allow for `|mut x, y|expr` (fix #25734) (#25735) - Allow using `a`, `b` and `it` as var names, when using the builtin array methods (fix #25729) (#25755) - Disallow generic function to be exported (fix #25794) (#25806) - Support `-d trace_parse` to ease diagnosing problems related to the order of parsing of .v files in modules - Fix the language support for a nested anonymous C.struct (fix #25807) (#25789) - Disallow untyped `chan` used as a fn parameter type (fix #25818) (#25854) - Improve the unused import warning message (add fixing alternatives) (#25880) - checker,parser,ast: make `type MyBuilder = strings.Builder` work (part 1); add `mod` fields to ast.SumTypeDecl and ast.AliasTypeDecl (#25943) - Remove dead code in Parser.is_array_type/0 (#26080) - Check invalid struct name in struct_init() (fix #26030) (#26093) - Remove the support for the obsolete generic fn call syntax f() (first deprecated in 2022/11) (#26126) - Fix comptime for lock shared field (fix #26143) (#26146) - checker,parser: add multifile gotodef support for -line-info (#26167) - Optmize Parser.call_kind (#26196) #### Compiler internals - markused: fix markused struct heap (#25542) - markused: fix array.prepend C code dependency (fix #25573) (#25582) - markused: fix fn marked as used when variable and fn uses same name (fix #25649) (#25650) - checker,transformer: add always true/false branch detection for the `if` and `match` constructs (#25674) - v.util: measure more precisely how long a new tool recompilation lasts in launch_tool, when using `v -d trace_launch_tool self` - transformer: fix struct init comparison turning into boolean (#25724) - v.builder: support V_NO_RM_CLEANUP_FILES=1, to ease debugging of -usecache issues - v.builder: make it easier to reproduce the exact specific stages of -usecache module compilation by logging the full CLI options for each - v.builder: fix `.vsh` mode doing an implicit `import os`, now only for .vsh file itself (fix issue spotted in #25736) (#25745) - v.builder: improve diagnostic information for a failed build_thirdparty_obj_file - transformer: transform ArrayInit into a function call for C and native backends (part 1) - builder,pref: add `-file-list` support (implement feature #25707) (#25749) - pref: for -usecache, set .parallel_cc = false and .no_parallel = true to make compilations more deterministic and ease CI diagnostics - markused: fix missing builtin__memdup definition, when an option struct field is used (fix #25801) (#25802) - transformer: move array logic to array.v - v.builder: improve the error message for failing cgen; suggest `-g` and `-show-c-output` - v.pref: fix GitHub download URL for the photonwrapper .so file (fix #25708) (#25831) - v.pref: use `v download` for downloading the prebuilt `photonwrapper` shared library (#25849) - markused: fix const as fn mark as used (fix #25888) (#25895) - transformer: disable generic str_intp opt (fix #25896) (#25897) - v.scanner: remove obsolete .is_crlf and .is_vh fields (#25918) - v.scanner: use a named return for decode_XXX_escape_single methods, to reduce the generated C diff churn, during scanner code updates - markused: add new auto_str() used funcs for bootstrap (#25938) - v.builder: provide more detailed error message, on `msvc: failed to build a thirdparty object`, not just the failed command - v.builder: improve formatting of the `failed to build a thirdparty object` message for msvc - scanner: remove old generic check logic (fix #25959) (#25997) - transformer: fix the setting of a generic flag for fixed array type with `-new-transformer` ( #26009) - transformer: add file/line info for fn with `expand_simple_interpolation` (#26135) - transformer: add early return to avoid transform getting applied twice for a `for x < y {` body ( #26153) - markused: fix option none markused (fix #26147) (#26151) - v.builder: enable gc back with msvc, build separate `.debug.obj` thirdparty files when -g is passed, to prevent linking issues (#26215) - v.builder: support compiling asm .S files to .o files, mentioned in #flag directives (needed for #26185) (#26211) - v.builder: fix compile asm file, followup of PR #26211 (#26227) #### Standard library - arrays: fix rotate_left() and rotate_right(), add test (#25539) - encoding.base58: fix encoding, add test (#25538) - x.crypto.chacha20poly1305: move up responsibility for allocs into higher caller (#25574) - crypto.cipher: fix decryption in CBC mode, add test (#25584) - os: use `@[noinline]` on os.create/1 to workaround a `-cc gcc -prod` panic (fix #25549) - time: fix non-digit checks for parse_rfc3339() (#25597) - gg: add explicit bounds checking for image caching methods in gg (fix #25590) (#25591) - time: fix quarter calculation in custom_format() (#25608) - rand: fix randomness in shuffle() (#25617) - gg: destroy unused GPU resources before replacing cached images (#25615) - encoding.binary: fix serialize skip struct shared fields (related to issue #25600) (#25613) - x.crypto.chacha20poly1305: make implementation use fixed sized arrays more (#25627) - builtin: make result string end with null in `u8(x).repeat(y)` (fix regression after #22100) ( #25625) - gg: fix address of const warnings for `v -experimental program_using_gg.v` - builtin: add .hex() methods to the `rune` and `char` types too (#25635) - datatypes: fix insert() and delete() for items in second half of DoubleLinkedList[T]{}, add test ( #25647) - builtin: use an explicit loop to determine min_common_indent in string.trim_indent/0 to reduce allocations and reduce the reasons for misfires of the closure detection heuristic - vlib: use `defer(fn) {` syntax where appropriate (part 2 of #25639) (#25653) - x.json2: fix decode_number not initializing value to zero (fix #25641) (#25675) - crypto.hmac: optimize hmac.new, support calculations with a blocksize > 256 (#25686) - math.unsigned: fix put_bytes(), add test (#25718) - builtin: reset .len and .cap to 0 too, in the array.free() method (#25717) - os: add pipe and stdio_capture support (implement #25714) (#25716) - encoding.utf8.validate: fix validation, add test (#25748) - crypto.blake2b,crypto.blake2s: add `@[direct_array_access]` to hot functions (#25750) - strconv: fix handling of subnormal numbers like `'1.23e-308'.f64()` (fix #25751) (#25752) - crypto.sha3: remove `import math` (just for int_max), to improve compilation time and complexity for code that uses sha3 - builtin: add declarations for C.GetCurrentThreadId(), C.gettid() and C.pthread_self() - builtin: add pid: and tid: fields to the panic reports (part 2 of #25808) (#25809) - gg: add doc comments for the FN** types (#25814) - rand: add missing i8() utility function (#25819) - builtin: fix C.SYSTEM_INFO (fix #25788) (#25823) - builtin: support `-d no_getpid` and `-d no_gettid` for systems that lack proper process management APIs - math: fix vec2,3,4 project not using the right formulas (fix #25811) (#25813) - math.vec: swap u and v in the .project() method of Vec2,Vec3,Vec4 (#25841) - crypto.cipher: fix xor_key_stream() for OFB mode, add test (#25844) - encoding.binary: use unions for small speed increase and readability (#25867) - math.complex: replace `==` with eq_epsilon() in equals() (#25873) - crypto.cipher: fix xor_key_stream() for CTR mode, add test vector created with OpenSSL (#25866) - os: enhance os.cp() to mimic Python's shutil.copy2() (#25893) - io.util: use correct TempDirOptions parameter type name in temp_dir() (#25904) - builtin,sync: eliminate calls to _us32_lt in new_map/6, and in the spinloops in Channel.try_push_priv, Channel.try_pop (#25912) - rand: restore error margin in dist_test.v back to 0.05 (the updated seeds were found by @tankf33er in #25907) - builtin: reduce the max size of string representations of integers (#25919) - builtin: remove commented code, improve comments - x.crypto.chacha20: fix deprecation warning during compilation of Cipher.rekey/2 - math.easing: fix in_out_expo(), add test (#25944) - builtin: split builtin.v and builtin.c.v into smaller, and more focused .v files, to ease working on unrelated subsystems (#25965) - transformer: fix `v -new-transformer vlib/strconv/atoi_test.v` (#26021) - gg: add more documentation for color substraction (fix #21549) (#26023) - toml: fix for single `\r` occurence in multi-line `"""` strings (`\r\n` is still allowed) (#26029) - toml: remove workarounds + `TODO`s for fixed issue #9507 (#26037) - x.json2: fix decode_number for u8 (fix #26027) (#26033) - rand.wyrand: switch to using the original C._wymix() as a performance optimisation (#26051) - strconv: fix float scientific notation (fix #26045) (#26046) - x.json2: fix decoding of float values in scientific notation (fix #26043) (fix #26062) (#26060) - builtin: add a declaration for C.memchr too (#26054) - toml: add compliance up until official toml-lang/toml-test@c6a78f1 (#26067) - builtin: fix some C fn parameter types (#26069) - toml: add compliance to official toml-lang/toml-test@8bb8d9c (#26070) - toml: remove special cases for `jq` normalization (#26092) - toml: fix remaining valid `key/*` exceptions (#26125) - builtin: make string.index_ public, to simplify code using a redundant `x := s.index(sub) or { -1 }` pattern (#26123) - builtin: add declarations for C.memmem and C.mempcpy (#26129) - builtin: speed up, fix and test impl_utf8_to_utf32 (#26109) - toml: fix remaining valid `array/*` exception (#26138) - toml: fix unicode decoding panic on invalid TOML `key/duplicate-keys-06.toml` (#26140) - toml: allow `true` and `false` as keys when parsing root table (#26144) - toml: allow dotted key lengths > 2 within nested arrays of arrays (#26145) - flag: fix `v vet -W vlib/flag/` (fix remaining doc comments) - x.json2: fix memory access error, when decoding string enum values (fix #26176) (fix #26179) ( #26178) - toml: fix invalid exception by erroring on duplicate keys in inline table (#26177) - time: implement faster and simpler `push_http_header` (#26155) - toml: fix remaining invalid exceptions for `table/*` (#26189) - toml: reach 100% TOML v1.0.0 compliance with the official test suite (#26203) - x.json2: remove workaround_cast(), add isize usize decode support (#26210) #### Web - net: fix cookie parsing when `;` is used (fix #25544) (#25561) - veb: new fasthttp module with -d new_veb (multithreaded, epoll/kqueue): makes veb multithreaded and fixes frequent hangs - veb: fix gzip middleware decode/encode (fix #20865) (fix #25753) (#25754) - veb: gzip support for StaticHandler (fix #20859) (#25758) - veb: support markdown content negotiation, compliant with https://llmstxt.org/ (#25782) - fasthttp: move kqueue related code to a separate file - veb: add zstd compression support (#25816) - veb: remove println('send_file ct=...') leftover (#25834) - ci: reduce false positives for veb_should_listen_on_both_ipv4_and_ipv6_by_default_test.v by retrying it 3 times (since sometimes binding to the port it listens to fails) - veb: add an early startup panic error message, when the result type of route handler methods *is not* `veb.Result` (fix #25970) (#25973) - net.mbedtls: make errors more verbose, to ease remote diagnosis of issues - net.openssl: make errors more verbose, to ease remote diagnosis of issues - veb: improve the before_request documentation - veb: add method.location too, to the invalid return type error, to ease diagnosing problems while prototyping - wasm: fix const reference another const (fix #25722) (#26010) - fasthttp: fixes and improvements (#25906) - wasm: export pub fns in main module when targeting wasi (#26041) - net.http: use error_with_code in download_file() (fix #26056) (#26057) - net.http,veb: fix detection of the headers/body boundary in parse_request_head_str (fix #26091) ( #26112) - fasthttp: expand http request parser (related to #26091 part1) (#26104) - net.ftp: fix get() command conversation, add test (fix #18858) (#26194) - x.sessions: verify HMAC signatures when extracting sessions IDs from cookies (#26199) - net.http: fix a panic in parse_multipart_form, for small/incomplete form data (fix #26204) - net.http: support keep-alive connections in server (fix #26136) (#26218) #### ORM - Mark orm_where_in_test.v to be skipped in the sanitize-memory-clang job - Fix fkey insert as assigment expr (fix #25568) (#25575) - Fix double fkey insert and update (fix #25593) (#25606) - Add index attr support (#25604) - Fix autofree detection for is_or with block style (fix #25969) (#26089) - Allow multiple set() in one update() call (fix #26116) (#26117) - Add check for invalid index field name (#26142) - Supoprt DISTINCT keyword (#26163) #### Database drivers - db.sqlite: fix orm f32 field retrieval for sqlite (fix #25583) (#25592) - db.pg: support returning `Result` type with column names (#25737) - db.sqlite: allow for `mut db := sqlite.connect_full(":memory:", [.readwrite, .create, .fullmutex], "")!` defaulting to unix/win32 depending on the platform - db.pg: support LISTEN/NOTIFY (implement feature #23983) (#26133) - db.pg: fix `v check-md vlib/db/pg/README.md` - Revert "db.sqlite: support calling exec_param_many with [][]string or []string (it now accepts a sumtype of both) (#26100)" - Reapply "db.sqlite: support calling exec_param_many with [][]string or []string (it now accepts a sumtype of both) (#26100)" #### Native backend - Fixed array, `-new-transformer` dynamic array (#25817) - Add `$if trace_native_todos ? {` to reduce noise in `v test-all` #### C backend - Fix resolution type Map[string]T when T is AliasToMap (fix #25494) (#25510) - Fix markused for option generic param (fix #25501) (#25525) - Fix empty struct initializer for clang (fix #25467) (#25526) - Fix match codegen for option match case (fix #25533) (#25537) - Fix codegen for alias for array fixed initialization (fix #25512) (#25540) - Ensure option none/ok state is also compared (#25532) - Fix match codegen for option expr on case (fix #25545) (#25553) - Add `-no-closures` option to detect closure usage earlier (for emscripten or for less well supported platforms) (#25565) - Create ctemp before lockexpr gen (fix #25576) (#25612) - Fix if expr with condition that requires temporary variable (fix #19584) (fix #23903) (#25621) - Fix multi return of a fixed array (fix #25626) (#25628) - Fix generic multiple indirections on print (fix #22793) (#25633) - Fix `fn (d Struct) a[T]() T { return d }` when T is a sumtype (#25644) - Minimize code generated for asserts (generate the common parts for the pass/fail case once) ( #25642) - Handle pointers in json map decode/encode (fix #25632) (#25646) - Fix `defer` stmts with `if` exprs and `or` blocks that return a value (#25651) - Fix infix expr ComptimeSelector type (fix #25659) (#25662) - Fix passing sumtype child to generic function taking sumtype parent (fix #25660) (#25664) - Fix multi generics fn name (fix #23886) (#25673) - Fix `defer` generation within comptime `$if`/`$match`/`$for` (#25677) - Fix codegen for if comptime and array fixed (fix #25691) (#25697) - Correct function definitions for callbacks in imported modules (fix #25700) (#25719) - Improve codegen for array fixed init for g++ compiler (fix #25723) (#25725) - Fix codegen for operator overload method_name on alias to builtin types (fix #25709) (#25726) - Fix missing cast if fixed array is surrounded in brackets (fix #25629) (#25741) - Fix comptime for types not being recognized with maps correctly (fix #25742) (#25743) - Fix dump(ptr_to_fixed_array_value) - it now returns the argument directly (thanks @tankf33der) ( #25764) - Cast member variables to correct types in comptime $for (fix #25771) (#25773) - Include `ast.ComptimeSelector` in fixed array checks (fix #25767) (#25777) - Checker,cgen,type_resolver: prevent stale type cast on comptime `$for`, handle in dumpexpr (fix #25781) (#25784) - Reduce the nested expr level complexity of Gen.ident - Fix tcc __attribute__, fix os.notify (followup to #25779) (#25804) - Ensure array of string is not cloned with depth 0 (fix #25783) (#25793) - Support `-d trace_check` and `-d trace_cgen` to help diagnose checker and cgen ordering issues - Support `-d trace_cgen_fn_decl` and `-d trace_cgen_gen_fn_decl` too - Show the v_gettid() hex with `-d trace_cgen_fn_decl` and `-d trace_cgen_gen_fn_decl` - Use variadic_count == 1 when passing variadic to call of same array type (fix #25827) (#25837) - Fix nested or in assign decl (fix #25864) (#25865) - Fix variadic on translated (fix #25862) (#25876) - Allow @[cinit] for const variables (#25881) - Fallback to field type when default_expr_typ is 0 (fix #25891) (#25903) - Fix map value init with array fixed const (fix #25887) (#25902) - Fix cast type changed before last stmt in `stmts_with_tmp_var` (#25915) - Update wyhash to version 4.2 (#25907) - Use final_sym for elem_sym in index_of_array (fix #25960) (#25961) - Fix variadic call on sumtype with array of itself (fix #25898) (#25964) - Correct T{} init for []Type aliases (fix #25962) (#25963) - Fix array init with fixed array from return call (fix #25954) (#25971) - Fix fntype unwrap on ifguard (fix #25911) (#25914) - Add a source .location field to `$for method in Type.methods {` (#25976) - Fix iterator on alias to fn ptr (fix #25911) (#25978) - Fix shared int string intp (fix #25984) (#25989) - Allow init shared field with default value (fix #25990) (#25991) - Allow init of struct from struct with array of optional values (fix #26000) (#26005) - Fix default value in if/else or block (fix #26002) (#26020) - Fix fnptr indirections declaration (fix #25940) (#25987) - Fix bool cast from value (fix #26028) (#26031) - Fix cast() generic type bug (fix #26065) (#26066) - Fix fn_var_signature() support nr_muls (fix #26049) (#26075) - Fix cast_expr() for alias (fix #26076) (#26079) - Handle CallExpr in dumpexpr (fix #26084) (#26087) - Clean code in return stmt (fix #25968) (#26118) - Fix cast to array (fix #26099) (#26102) - Fix fn_var_signature() allow option type (fix #26088) (#26120) - Fix scoped struct array fixed generation (fix #26111) (#26114) - Fix option array init with non option values (fix #26148) (#26170) - Fix heap fixed array assign (fix #26149) (#26169) - Fix stack overflow for `@[heap]` structs with large fixed arrays (fix #22690) (#26183) - Fix print interface when arg0 is function call (fix #26184) (#26188) - Checker,table,cgen: fix generic interface confusion (fix #25478) (#26181) #### vfmt - Force conversion of []Type{init: it} -> []Type{init: index} (#26201) #### Tools - ci: run `v doc` with VJOBS=1 on the CI, to make remote diagnosing of failures easier - Remove unused `sw := time.new_stopwatch()` call - Add support for VTEST_SHOW_CMD=1 in `v test .` too - ci: use VJOBS=1 for the `v test cmd/tools/vdoc` step too, to ease diagnosing remote CI failures - ci: bump cross-platform-actions/action from 0.29.0 to 0.30.0 (#25666) - Fix showing the *failed* compilation output with `v -silent test .` - ci: bump all `timeout-minutes: 15` to `timeout-minutes: 20` to reduce false positives due to network timeouts (mostly for the Termux job) - Note about `v help check-md` when `v check-md .` fails - ci: skip invalid_utf8_string.vv in compiler_errors_test.v for msvc - ci: reduce annotation noise, remove dead code - ci: skip the multistage v->v2->v3 -usecache checks for now (reduce false positives on the CI for unrelated PRs, until the root cause is fixed) - ci: add new job `sanitize-address-clang-without-gc` that passes `-gc none` through VFLAGS (#25780) - Support ``` VTEST_SHOW_LONGEST_BY_RUNTIME=5 \ VTEST_SHOW_LONGEST_BY_COMPTIME=5 \ VTEST_SHOW_LONGEST_BY_TOTALTIME=5 \ v test . ``` - Print total time at the *end* of the `v test-all` output to ease visual comparisons in separate shells, without scrolling - Use unbuffer_stdout in TestSession.test, to ensure consistent output on the CI jobs - v.builder: remove the obsolete check for V_NO_C_ERROR_INFO (VQUIET=1 replaced it in 2023); add VQUIET to the `-q` description - Make `v search` failures easier to diagnose (on the CI) - Support `v download -o some/folder/local.toml TOML_URL`, in addition to --target-folder - Add `--sha3-256` support for checksumming the content that `v download` saves - Add a watchdog timer in test_if_v_test_system_works.v to speedup the failure of stuck CI jobs - Use local `vtest build:` tags to eliminate the need for the skip_fsanitize_too_slow list in vtest-self.v - ci,vpm: make dependency_test.v more robust, and easier to diagnose remotely - ci: set VTMP too in set_test_env/1, to avoid cloning conflicts during parallel test executions - v.builder: do not produce `If the code is in a folder with multiple .v files` for temp V REPL files, to improve messages for `'asdas'.starts_wiz('xyz')` - Add a `-new-transformer` task to `v test-all`. Remove `-skip-unused` flags (it is the default for ~1 year). - Improve development experience for `v -W -silent test-self vlib` (especially on CIs); *always* show compilation errors for failures - Support `VTEST_KEEP_SESSION=1 ./v test vlib/math` - vet: use new annotation syntax ([] -> @[]) (#26026) - ci: bump cross-platform-actions/action from 0.31.0 to 0.32.0 (#26074) - Make the `is_sqlite3_present` check more robust (work with the system packaged sqlite library again too) #### Operating System support - ci: fix gcc-windows -std=c99 (#25534) - os: add windows stdin_write() support (#25546) - ci: use `macos-14` instead of `macos-13` (the older runner is being deprecated) (#25670) - v.builder: fix json-errors with a windows path separator (#25680) - ci: fix unsetting of VFLAGS in `v run ci/linux_ci.vsh v_self_compilation_usecache_clang` - ci: stop unsetting VFLAGS completely in ci/linux_ci.vsh and ci/macos_ci.vsh - builtin,os: fix windows execute ANSI encoding result, make msvc error messages readable in a Chinese locale (fix #25727) (#25736) - db.sqlite: update windows version to https://sqlite.org/2025/sqlite-amalgamation-3510000.zip ( #25766) - os.notify: fix struct epoll_event alignment on ARM64/Linux (fix #25778) (#25779) - fasthttp: Linux/epoll support - math: reduce the nested level of expressions, to reduce the chances of stack overflows on windows - net.http,ci,db.sqlite: rewrite .github/workflows/windows-install-sqlite.bat in .vsh, fix vschannel on windows downloading content > 32KB (#25792) - v.builder: bump the default stack size for executables, when compiling with msvc on windows, to 32MB (#25824) - ci: reduce the chances of false positives due to hangs of use_net_and_net_unix_together_test.v on windows - doc: add subsections about using SQLite on windows and about installing the self contained `sqlite` module. - v.builder: switch to using `-std=c99`, instead of `-std=gnu99` to avoid name colisions with C `linux` macros defined by gcc/clang (#25848) - gg: set more sensible and user friendly defaults for the width, height and the title of new windows - thirdparty: update thirdparty-openbsd-amd64_tcc.sh (#25945) - ci: install plain gcc on the OpenBSD jobs - ci: use `gcc` as the name of the compiler instead of `egcc` on OpenBSD - ci: remove the gcc-openbsd job, until OpenBSD people fix their broken conventions on 7.8 - ci: run `v -W -silent test-self vlib` on linux, so deprecations/warnings introduced in PRs, can fail (and be fixed) earlier (#25955) - ci: use VTEST_SHOW_LONGEST_BY_* vars on OpenBSD (#25958) - ci: update to use FreeBSD version 15.0 (#25985) - crypto.ecdsa: update to test and use OpenSSL 3.5 on OpenBSD (#25995) - x.crypto.slhdsa: add support on OpenBSD using OpenSSL 3.5 (#25996) - ci: reduce failure rate for the gcc-windows job, in test_if_v_test_system_works.v - ci: skip use_net_and_net_unix_together_test.v on gcc-windows (many weird timeouts on unrelated PRs) - db.sqlite: fix exec_param_many on linux for the case of a [][]string parameter - v.util: add `-d max_suggestions_limit=140` for v itself, to improve handling of large .v files with many thousands of lines on windows - v.util: bump max_suggestions_limit to 200, to account for windows - ci: extract windows_ci_msvc.yml from windows_ci.yml to enable finer grained workflow/job control - ci: extract and split windows_ci_tcc.yml and windows_ci_gcc.yml from windows_ci.yml for improved job control #### Examples - Handle closing of the window in the event manager in examples/viewer (#25522) - ci: add a report-wrong-examples-in-doc-comments job, that runs `./v doc -check-examples -f none vlib/` (#25554) - Make reproduction of failed examples easier (make sure that all the checked sources have an ending \n) - Use math.vec in path_tracing.v and in vyper.v - Support `v -d trace_execution run examples/brainvuck.v mandlebrot.bf` - ci: do not use `-silent` for the `v build-examples` task on windows, to make it easier to diagnose recent gcc-windows timeouts - doc: add an example for reading from a non empty buffered channel, after closing it - Fix and improve vanilla_http_server (#25905) - ci: remove `-silent` from the macos build_examples task too, to make remote diagnosing of CI timeouts easier - Add optional `update_fn: fn (dt f32, ctx &gg.Context)` to gg.Context and gg.Config . Pass consistently the current GG context to *all* callback functions, instead of nil. - Add expanding_rect.v (modeled after the example from https://love2d.org/wiki/love), add generic helpers gg.frgb/3 gg.frgba/4 - tools,examples,veb: fix `v -d trace_before_request run examples/veb/veb_example.v` after feedback from https://youtu.be/IuE6Bo1klK0?t=2100 - Move flag/ .v files 1 level up, to prevent module lookup confusion for unrelated examples - Add a Lorem Ipsum Generator (#26036) - examples,net.ftp,v.builder: remove remaining matches of `rg --multiline --multiline-dotall "continue\n\t+\}\n\t+\}\n\t+return" -B3 -A3 ` - Update lorem.v with a Markov algorithm for better text generation (#26085) - fasthttp: fix the correctness of the minimal server example, when tested with curl (#26072) - v.gen.native: fix `v -os macos -experimental -b native -o hw.macos examples/hello_world.v` on linux - tutorials: remove newline in the example for c2v's cc compilation to `doomv` (#26200) - Make all the labels fit in the default window size header in minesweeper.v ## V 0.4.12 *19 Sep 2025* #### Improvements in the language - json2: replace encoder with a new implementation. It's 70% faster than the old json2, and 110% faster than json that is based on cJSON (#25224) - Virtual C consts with custom types (const C.MY_CONST u8) - Support `-div-by-zero-is-zero`, which allows for `x / 0 == 0` and `x % 0 == x`, avoiding division by zero traps/panics (#24981) - Limit -div-by-zero-is-zero influence to just the integer types (for f32 and f64, / produces a +inf or -inf value, and the program continues to run) - VLS mode for the language server in pure V - Add support for `@OS`, `@CCOMPILER` `@BACKEND` and `@PLATFORM` (#25174) #### Breaking changes - Deprecate `gx` and replace all occurences with `gg` (which now contains all the functionality of `gx`) (#24966) #### Checker improvements/fixes - Fix `sizeof(T)` usage in generic struct (fix #24806) (#24808) - Add `$if sizeof(T) == int_literal {` support (#24831) - Improve virtual C consts - Markused,checker: fix hello world size after the introduction of `builtin.closure` in 2d87ac4 ( #24989) - Remove dump() dependency from ComptimeFor (#25000) - Cleanup - remove unused c.using_new_err_struct (#25036) - Cleanup `err` removal (#25043) - Add comptime support for s390x, ppc64le and loongarch64 platforms (#25048) - Allow for `v -is_o -o x mm.v`, where `mm.v` starts with `module abc` (i.e. not just `module main`) - Fix calls with result propagation, using other consts, in const declaration expressions (fix #21609) (#25060) - Fix array init with interface (fix #24255) (#25073) - Fix missing map float key duplicated checking (fix #25098) (#25117) - Fix missing check for struct generic init from call (fix #25084) (#25119) - Fix missing check for empty array to generic param (fix #25056) (#25118) - Rewrite comptime_if_cond() to support comptime if cond evaluate (fix #24938) (fix #25099) (#25122) - Add error for struct not init (fix #24893) (#25134) - Fix sql insert expr propagate result (fix #24833) (#25136) - Fix checking return type call disregarding unwrapping (fix #25140) (#25143) - Ensure the defer behavior matches that of cgen (fix #25148) (#25146) - Nil check for c.table.cur_fn in gen_branch_context_string() (fix #25170) (#25171) - Relax the "unreachable code after a @[noreturn] call" error to a warning to reduce prototyping friction (#25173) - Fix multi return arg passing checking (fix #25167) (fix #25180) (#25177) - Use keywords matcher trie for imported symbol presence checks, instead of `x in p.imported_symbol` (#25201) - Fix iteration over mutable option (fix #24860) (#25199) - Add `T.typ` and `T.unaliased_typ` checking to `$match` (fix #25200) (#25202) - Add more checks for map.delete (fix #25204) (#25205) - Fix static init var (fix #25203) (#25209) - Add top level comptime support for `$match @OS {` too (#25222) - Comptime match only eval true branch (fix #25223) (#25225) - Fix multi return var passing to fn arg (potential fix for #24870) (#25250) - Prevent usage of imported module name prefix as identifier names, to avoid cgen collisions ( #25280) - Disallow duplicate export names (fix #25301) (#25302) - Reduce the verboseness of `unsupported size ... for global` messages, for `v -b native examples/hello_world.v` #### Parser improvements - Split parser methods to files based on topic (#24786) - Fix arch loongarch64 comptime support (fix #24906) (#24907) - Fix const error - pref,parser: implement support for `-force-bounds-checking` to enable easier testing of functions tagged with `@[direct_array_access]` (essentially turning off that flag) - Allow keyword as struct param key on fn call (fix #24957) (#24958) - Fix syntax error for `for c in [othermod.Struct{field: 255}] {` (fix #24943) (#24978) - Reduce calls to util.contains_capital - Fix overriding of fn names in `-translated` mode (fix #25024) (#25061) - Fix asm modifier parsing (allow for `=r, =&r, +r, +&r,=m,=rm,=@ccl, =*r`) (fix #25070) (#25072) - Allow using aliased types in interface method implementations (provide backwards compatibility to `ui`, during the migration of code from `gx` to `gg`) (#25106) - Fix interface method declaration with fixed array return type (fix #25137) (#25145) - Prepare for eliminating a warning for `v -cross -o vc/v.c cmd/v` (part 1) (reduce CI annotation noise) - Add duplicate import symbol detect (fix #25185) (#25187) - vfmt,parser: move mark used from vfmt to parser (#25190) - v.ast: add a `mod` field to ast.FnTypeDecl too #### Compiler internals - scanner: fix multi-level string interpolation in if/match branch (#24805) - markused: fix mark for array init from sumtype (fix #24887) (#24889) - markused: whitelist `_option_none` too (fix #24862) (#24885) - markused: remove `@[markused]` from option and result fns (#24900) - markused: skip unused symbols, dump fns and generic specialization (fix #24921) (fix #24927) ( #24924) - parser,markused: support `@[markused]` for interface declarations too (#24963) - markused: fix interface fields and chan usage (fix #24961) (#24962) - v.builder: add a clearer error message for `v -shared run empty.v` (issue found by Felipe Pena) - markused: use eprintln for `PANIC DEPS` too (for consistency and easier redirection for the whole trace) - v.util: add support for setting VUTIL_RETRY_MAX_COUNT=1 to ease the workflow for developing backends - markused: improve the tracking of used closures (#25009) - markused: improve array resources tracking + remove all_fns loop for orm (#25007) - markused: fix generic map index (fix #25012) (#25022) - markused: improve array tracking (range, gated) (#25023) - markused: fix option tracking on sumtype (fix #25025) (#25028) - markused: fix thread type mark by go/spawn expr (fix #25049) (#25054) - scanner: refactor string interpolation (fix #24198) (#25053) - markused: fix array append c code dependency (fix #25057) (#25058) - markused: fix option array element (fix #23089) (#25179) - markused: fix option map value (fix #25186) (#25188) - parser,fmt,markused: add top level comptime `$if` support (enable `$if platform { import module struct Abc {} }`) (#25216) - v.builder: add -DNO_DEBUGGING in addition to -DNDEBUG, when compiling with -prod - v.builder: support `-d trace_type_symbols_after_checker` - scanner: uncomment working rune test (#25305) - v.util: fix handling of "start \u005c${...} end" in cgen (fix #25304) (#25306) - markused: fix marking of mutable generic method calls (fix #25312) (#25314) #### Standard library - x.crypto: initial addition of curve25519 module (#24748) - thirdparty: add NDEBUG check before glGetErrorCode if-statement in sokol_gfx.h (#24754) - math.big: remove unnecessary code from / and % (the same is done in div_mod, which they call) ( #24766) - builtin: add a rune iterator method to strings, allowing `for for i, r in s.runes_iterator() {` without first allocating an array for all the runes (#24769) - builtin: support `-d builtin_free_nop` to help diagnose problems with too early manual free() calls - builtin: use s.runes_iterator() in trim_runes/2 to avoid needless allocation - builtin: add string.expand_tabs() (#24781) - os: do not resolve symlinks in os.find_abs_path_of_executable/1 (fix #24759) (#24761) - os: improve documentation (#24790) - gg: allow for `-d gg_memory_trace_frame` to be used in combination with `-prealloc -d prealloc_dump` - sync: add SpinLock (#24788) - os: fix documentation for environ function (#24796) - sync: fix documentation for new_spin_lock function (#24795) - sync: add implementation for WaitGroup.go/1, add test (#24797) - sync: improve documentation (#24799) - sync: fix spin lock, add destroy() and try_lock(), add valgrind annotate support (#24798) - os: add os.write_bytes/2 as a complement to os.read_bytes/1, add test - sync: use SpinLock for channel (fix #24680) (#24802) - crypto: fix ambiguous expressions in DES implementation (#24814) - sync: use an atomic counter in test_waitgroup_go in waitgroup_test.v - datatypes: add lockfree version of counter and ringbuffer (#24839) - sync: add thread local storage (TLS) support (#24849) - math.unsigned: fix rotate_left() for uint256, add test (#24872) - math.unsigned: replace untested comments for uint256 public APIs (#24873) - log: use `@[noinline]` for level_from_tag/1 and target_from_label/1 to avoid triggering panics for programs using `log`, compiled with -prod and -cc gcc>10 (fix #24874) - math.big: fix toom-cook 3-way multiplication (#24888) - runtime: add used_memory() (#24897) - runtime: add note for the availability of the used_memory implementation (#24913) - os: remove commented code in home_dir() function (#24929) - math.big: fix the order of calculations in mod_pow() to improve performance (#24935) - math.big: add shrink zeros to karatsuba and toom-cook (#24937) - math.big: fix big_mod_pow() (#24939) - os,runtime: move some C struct and fn def to `builtin` (#24942) - math.big: fix validate_string and integer_from_regular_string (check for characters.len > 0, before accessing characters[0]) - builtin: prepare for adding a `-force-bounds-checking` option - strconv: fix bounds check bug, discovered by the equivalent of `./v -g -force-bounds-checking test vlib/toml/` (thanks to tankf33der) - builtin: fix OOB bugs in s.is_bin, s.is_oct, s.is_hex, discovered through `./v -force-bounds-checking test vlib/builtin/` - regex: fix OOB bug discovered through `./v -g -force-bounds-checking vlib/regex/` (fix by @penguindark) (#24960) - time: fix custom_format panic (fix #24977) (#24987) - time: fix more panics in the supported specifiers in Time.custom_format/1 (#24988) - vlib: add `archive.tar` module to enable reading of .tar ang .tar.gz files (#24995) - builtin: fix warnings for `./v doc -m -f html vlib/builtin/` - sokol.gfx: set the missed array_count field too in the `set_vert_uniform` and `set_frag_uniform` APIs (#25019) - builtin: fix `assert "ä ö å æ ã ø ô é ë".title() == "Ä Ö Å Æ Ã Ø Ô É Ë"` (fix #25017) (#25026) - Apply `@[markused]` to builtin_init, remove its heuristic from markused.v - gg: improve drawing effect and logic of draw_rounded_rect_empty (#25062) - math.bits: add asm implementations for some 64 bit ops (#25020) - vls: autocomplete for module functions: e.g. `os. ...` - math.big: move from u32 to u60 digits (#25018) - os: simplify file.c.v using cross platform f.seek/2 calls, add EINTR handling to f.write_full_buffer/2 (fix #25107) (#25110) - builtin: add arr.pop_left() func (#25133) - math.big: refactor add_digit_array() (#25138) - math.big: optimize add_digit_array() (#25139) - math.big: optimize subtract_digit_array() (#25142) - strconv: produce a maximum of 8 digits after the `.` for f32.str() (fix #25141) (#25144) - math.big: restore and refactor str() and integer_from_string() (#25154) - os: remove `unknown host OS` panic from os.get_host_os() - flag: fix tail/single bool flag error condition logic in `flag_to.v` (fix #25166) (#25172) - flag: improve the fix for #25166 tail/single bool flag error in `flag_to.v` (#25189) - readline: fix wide char display width for Chinese characters (fix #25219) (#25220) - repl: fix handling of lines with comments like `math.pi // comment` (fix #25229) - time: always return utc() timezone for Time.unix/0 (fix #17784) (#25233) - builtin: fix C prefix for proc_pidpath() (#25239) - math.big: replace division with Knuth, improve performance (#25242) - time: move the nanosecond comparison before the rest in the Time == Time implementation - builtin: add a temporary ctovstring_impl/1 API to enable `ui` to compile cleanly for PR#25264, part 1 - json2: replace encoder with new implementation (#25224) - json2: improve enum decoding; fix handling of required fields at the end of a json string (#25289) - json2: improve checker with better EOF detection (#25075) - json2: prepare for moving into json2 (#25039) - json2: fix remaining json2 discrepancies (#25029) - json2: support custom decoders (#25021) - json2: fix number decoding and improve errors (#25015) - json2: add support for decoding utf-16 surrogates, produced by some JSON encoder implementations ( Python, Java, C#) (#25193) - x.crypto: add a new `ascon` cryptographic module, based on https://doi.org/10.6028/NIST.SP.800-232 (Lightweight Cryptography Standards for Constrained Devices) (#25260) - x.crypto.ascon: improve the core of Ascon permutation routine (#25278) - x.crypto.ascon: improve single-shot functions of ascon hashing variant; add benchmark (#25282) - x.crypto.chacha20: improves the internals of chacha20, add a bench (#25311) ### V interpreter - Add comptime-if support (#24919) - Reset return value after const eval and fix if-expr (#24955) - Add more infix op support; fix early func return (#24965) - Fix if-else; add infix op; fix func calls (#24972) #### Web - picoev: fix documentation (#24811) - veb: fix `app.text()` -> `ctx.text()` in `README.md` - net.http: fix panic in parse_multipart_form for invalid boundary (fix #24974) (#24976) - net.http: remove debug println statement from post_multipart_form (#25030) - net.http: reduce the false positives on the CI for server_test.v, let test_host_header_sent_to_server return early, when the server can not start - net: improve tracing output for `-d trace_tcp`; move `error_code()` calls right after the corresponding C APIs (errno is a global that should be read immediately to be valid) - veb: fix a spurious error with Chromium, for POST requests, split into 2 parts, 1st with only http headers, without body (fix #25191) (#25195) - net.http: Use a full url when using a proxy, instead of only the path (#25228) - net.http.file: allow for serving requests to static files with cache busting suffixes like `/dist/littlejs.js?1117` - veb: fix generic field access from alias (fix #25215) (#25246) - ci: change url to http://archive.ubuntu.com in .github/workflows/disable_azure_mirror.sh #### ORM - Support lowercase operators `like`, `in`, `not in` etc (fix #25032) (#25035) - Fix sub_structs (fix #25104) (#25105) #### Database drivers - db: modify mysql/pg/sqlite interface for pool working (#24780) - db.sqlite: fix get_text trimming data after (including) first 0 character (#25040) #### Native backend - Add comptime cpu archs support (#24956) - Add support for (elf) globals (#25016) - Improve consts, support more assigns (#25277) - Structs multi_assign and multi_return (#25281) - Support more assign ops, reduce code duplication (#25283) - Begin array support, `a := []Type{len: x, cap: y}` and `a[i]` read/write (#25299) #### C backend - Only run freestanding_module_import on amd64 (#24763) - Fix sumtype option unwrapping (fix #24746) (#24770) - Protect against unlimited recursion in type_default_impl, by converting to a verror/1 call instead - Fix `static` and `volatile` var deref (fix #24778) (fix #24779) (#24807) - Fix codegen for interface method closure get (fix #24810) (#24818) - Fix codegen for multi return assignment with option type (fix #24812) (#24817) - Fix if codegen when func parameter is option type (fix #24813) (#24816) - Skip `struct none {` in cgen, if `none` is not used by V code reachable from `fn main() {` ( #24824) - Skip `struct map {` and related type declarations, when no V maps are used (#24826) - Fix anon struct encode (fix #24836) (#24852) - Fix json decode option alias (fix #24843) (#24853) - Fix const indexexpr dep (fix #24850) (#24851) - Fix codegen for generic interface with multi return generic type (fix #24838) (#24858) - Fix anon struct init passing (fix #24879) (#24884) - Allow alias to map `type Dict = map[string]string` (fix #24878) (#24883) - Builtin,cgen,markused: add struct @[aligned] support for structs allocated on the heap too ( #24886) - Add a `__closure_init` call for sokol/gg programs on android as well (#24892) - Allow alias types to be iterated if parent type has `next` method (fix #24890) (#24894) - Use alias `next` method if defined in `for x in iterator {` (#24905) - Fix const fixed array with type alias (fix #24936) (#24946) - Fix callback codegen on generic struct resolution (fix #24947) (#24948) - Move sort fn after interface definitions(fix #24465) (#24967) - Fix struct field init within fn without result type (fix #24970) (#24973) - Move closure C code to V code under vlib/builtin/closure/ (#24912) - Parser,ast,checker,cgen: use enum comparisons instead of string ones on ast.ComptimeCall.method_name (#25003) - Fix generic key's type with `in` operation (fix #24983) (#25011) - Remove unused enum declarations too (#25033) - Parser,checker,cgen: remove unused `err` declaration or `or { }` blocks (#25034) - Add a test for builtin_init being present (part 2 of 4a6941a) - Fix closures on s390x, ppc64le, loongarch64 platforms, add test to s390x CI (#25047) - Fix anon fn checking adding unresolved generic type on codegen (fix #25050) (#25055) - Fix building on Termux after fa904c4 - Use `#if defined __BIONIC_AVAILABILITY_GUARD && ...` to be compatible with more Termux versions - Fix asm stmt separators (#25067) - Fix translated file fixed-array assignment (#25080) - Fix codegen for passing int from selector to voidptr expect arg (fix #25081) (#25083) - Fix codegen for option void fn return block unwrap (fix #25074) (#25082) - Fix alias to sumtype cast initialization (fix #25086) (#25091) - Allow alias sumtype smartcasting (fix #25085) (#25096) - Fix codegen for generic struct field array option (fix #25093) (#25097) - Fix mutable sumtype (fix #25108) (#25111) - Fix generic return assign to ComptimeSelector (fix #25125) (#25131) - Fix address of call with `cast(&(arr.last() as Type))` (fix #23528) (#25132) - Fix eq for anon C structs (#25152) - Fix generated str method for enums that have C values (use ifs, instead of switch) (fix #25135) ( #25157) - Fix autofree with option array (fix #25124) (#25149) - Fix assigning fn address (fix #24537) (#25158) - Fix veb alias type identification and generic CastExpr (fix #24895) (#25155) - Revert "checker,cgen: evaluate comptime `$if` results in checker *only* (fix #25123) (fix #25156) (#25150)" - Evaluate comptime if results in checker only (with fixed -cross compilation) (#25162) - Fix generic_fn_name generating incorrect names for C structs (#25164) - Add comptime match support (#25165) - Fix resolving generic interface field from generic struct (fix #23556) (#25182) - Fix autofree used vars on return (fix #25196) (#25198) - Fix hash stmt code generation (fix #25184) (#25207) - Expose is_embed in FieldData (#25232) - Fix alias enum used in comptime `$for` (fix #25211) (#25212) - Ensure variable names do not conflict with builtin methods (fix #25063) (#25178)" - Add `@[reused]` attribute to mark methods, reusing the receiver memory on return (needed for autofree) (fix #25221) (#25235) - Fix gen_struct_equality_fn null pointer crash (fix #25237) (#25231) - Allow generic alias enum comptime (fix #25249) (#25251) - Fix big IntegerLiteral LL postfix (fix #25269) (#25275) - Prefix `builtin` APIs with `builtin__` (#25264) - Fix fixed-array const initializer (fix #25291) (#25293) - Fix generic cast to sumtype of empty struct (fix #25263) (#25290) - Fix option variadic arg passing (fix #25261) (#25273) - Support for 64bit int 1 (#25236) - Cgen,parser,markused: add export const support (fix #25300) (#25303) - Fix i64 enum as a map key, when the enum values are too small (fix #25294) (#25310) #### JavaScript backend - Simplify comptime if; catch up with cgen (fix #25295) (#25313) #### vfmt - Fix `if x := g() { x } else { return }` adding newline after `return` (fix #24908) (#24945) - Fix eating the attribute from `@[deprecated] pub type Alias = int` (fix #24968), workaround -usecache bug (#24969) - Fix call expr with single line comment in or expr (fix #24659) (#25159) - Fix comment line number in file with crlf line separator (fix #23524) (#25163) - Add support for 64bit int with `-new_int` (part 2) (#25298) #### Tools - v.vmod,tools: support a repo_branch property in v.mod files, in addition to the existing repo_url property, to allow for backlinks to repos that use `main` instead of `master` as their core branch - Make the output of `v should-compile-all` more immediately useful in CI jobs (turn off stdout buffering) - Add support for `// vtest vflags: -w` in `_test.v` files, to allow `v -W test .` later, for files, that have known warnings - ci: make sure the generator for vlang/docs can be compiled with latest V (prevent silent doc update stops, after breaking changes) - Add cmd/tools/gg_split_memdump_to_frames.vsh to ease working with memdump.bin files generated by gg programs (split by frames) - Add find_doc_comments_with_no_dots.v - Improve summary output of find_doc_comments_with_no_dots.v - Skip _test.v and _test.c.v files in find_doc_comments_with_no_dots.v - ci: add report-missing-dots-in-doc-comments job - ci: mark tcp_test.v and unix_socket_test.v as flaky (they still fail sporadically on the CI, although very rarely now) - ci: add `-prealloc` self compilation checks on more platforms (#24891) - docs,ci: check more vlib modules in the report-missing-dots-in-doc-comments job (#24928) - ci: add a watchdog timer thread to ringbuffer_test.v, to make sure the program exits in a reasonable time (~10s). Let the test be retried 2 times in a row if it fails. - ci: bump cross-platform-actions/action from 0.28.0 to 0.29.0 (#24952) - ci: retry session_app_test.v 2 times, since it is network dependent, and sometimes (rarely) fails - v.help: document the new `-force-bounds-checking` option - Improve alignment for `v repeat "program" "program_that_is_over_10x_faster"` - ci: add checks for compilation of vlang/gui to v_apps_and_modules_compile_ci.yml - ci: retry 2 times vlib/net/http/server_test.v to avoid false positives for unrelated commits/PRs - ci: force changes to vlib/x/json2 to trigger the full sanitized checks (the implementation there uses unsafe blocks and vmemcmp/3...) - ci: workaround -usecache issue afte 2d87ac4 - ci: add a performance-compare-with-master job - Fix `return""` in vdoc html output (fix #24979) - ci,tools: implement support for VREPEAT_SILENT=1 and `v repeat -S`, to only show the summary of the runs, without the progress lines - ci: fix the performance-compare-with-master job, when run on PRs (#25014) - ci: trigger updates to the module docs, even if just only the static files for the doc generator are changed - ci: make sure to always compare with the latest commit on the main V repo's master branch, when running .github/workflows/compare_pr_to_master.v - ci: compare the sizes of small programs like hello_world.v, but generated with `-cc gcc` too - ci: improve the alignment of the results of file size comparisons in compare_pr_to_master.v - Improve the output of `./v doc -m -f html vlib/` - Use `Copying` instead of `Generating` for the static resources in `./v doc -m -f html vlib/` - ci: bump actions/download-artifact from 4 to 5 (#25051) - v.help: document the `-is_o option` (in `v help build-c`) and add a test for it (#25052) - ci: add experimental support for building V and testing on a Termux docker container (#25059) - ci: use retry.sh for the `pkg install` in termux_ci.yml to reduce false positives. - ci: update vlang/gui commit its latest e5cc33fe816fef33d718cb1b91f66d6bd38fb4a4 - ci: bump actions/checkout from 4 to 5 (#25095) - ci: retry 3 times vdoc_file_test.v - ci: add a build_on_ubuntu_25_ci.yml script, for testing bootstrapping with GCC 14.2.0 (#25109) - ci: define TERMUX_VERSION in .github/workflows/termux_ci.yml instead of using `-os termux`, to make the emulation closer to a real Termux (#25128) - ci: reduce timeout-minutes for CI jobs that are normally fast to help detect anomalies earlier ( #25129) - ci: add a disable_azure_mirror.sh script, and use it before `apt update` to reduce the recent timeouts during installing dependencies (#25147) - ci: bump timeout-minutes to 15 in termux_ci.yml - ci: bump actions/setup-java from 4 to 5 (#25153) - ci: retry vlib/v/eval/interpret_test.v 2 times - ci: bump retry time from 10 to 15 minutes (reduce false positives for slow dependency installations on the CI) - ci: change the azure mirror URL in /etc/apt/sources.list too - ci: use `awalsh128/cache-apt-pkgs-action@v1.5.3` instead of a manual `apt update/apt install` step, to leverage caching more (#25256) - ci: check if `awalsh128/cache-apt-pkgs-action@v1.5.3` works on master (#25257) - ci: extract .github/actions/cache-apt-packages-action/action.yml, use it in puzzle_vibes_ci.yml #### Operating System support - docs: add section in README for compilation on OpenBSD (#24775) - crypto.ecdsa: add support for OpenSSL on OpenBSD (#24772) - picoev: add implementation for OpenBSD using kqueue (#24801) - log: fix `Unhandled Exception` on windows 7 (#24803) - ci: migrate the remaining jobs from the deprecated windows-2019 image to windows-2022 (#24825) - os: fix windows get_error_msg() leak (#24899) - runtime: reduce allocations done in runtime.used_memory/0 on linux (#24901) - ci: skip checking vlib/datatypes/lockfree/ringbuffer_test.v on the gcc-windows job for now - runtime: add used_memory() implementation for FreeBSD (#24909) - runtime: add used_memory implementation for OpenBSD (#24918) - ci: skip ringbuffer_test.v in the tcc-windows and msvc-windows jobs too, to avoid flakyness for unrelated commits/PRs. - ci: use FreeBSD version 14.3 after the bump of cross-platform-actions/action to 0.29.0 (#24953) - time: fix timezone test on windows - ci: add a release build for Linux on arm64 to release_ci.yml (#25064) - thirdparty: add `thirdparty-linux-armv7_bdwgc.sh` for building `libgc.a` on ARMv7 CPUs (#25077) - ci: bump retry count for server_test.v to 5 (reduce false positives on windows) - ci: use `v build-tools` without flags for the tools-windows job - os: eliminate warning for `v -cross -o vc/v.c cmd/v` on linux (part 2, see also 037a3b4) - os,sync: enable running `v -cross -o x.c cmd/v` on windows too (part 1, fix V errors) - ci: run .github/workflows/disable_azure_mirror.sh before all `apt update` commands, in ci/linux_ci.vsh, when run in a github CI runner - ci: retry 3 times cmd/tools/vtimeout_test.v on windows, before failing - os,ci: use a conditional include, instead of a platform file, to include libproc.h on macos only - ci: run input_rune_iterator_test.v only on linux for now - builtin: fix thread naming issue on Windows by ignoring RaiseException (0x406D1388) (#25270) #### Examples - Fix for `v build-tools` and `v build-examples` running on a i686 (the problem was discovered by @tankf33der) - Add examples/sokol/sounds/simple_keyboard_synth.v - builtin,markused: consider println of non string to use .str() method calls too, reduce generated C code for `v -cc gcc examples/hello_world.v` (#24996) - Use a sieve of Eratosthenes in primes.v, to handle bigger inputs more efficiently - vdoc: make -run-examples compatible with all output modes, not just the plaintext one - vdoc: extract vdoc_run_examples_test.v from vdoc_file_test.v - vdoc: implement -unsafe-run-examples and -check-examples support, add tests and document them - builtin,vdoc: fix the examples for the builtin methods, so that `v doc -check-examples -time -f ansi vlib/builtin/` pass - builtin,vdoc: make `v doc -unsafe-run-examples -time -f ansi vlib/builtin/` pass too - vdoc: improve failed example report - vdoc: support `v doc -check-examples -f none vlib/builtin` - bitfield: fix `v doc -unsafe-run-examples -f none vlib/bitfield/` too - arrays.parallel: fix `v doc -unsafe-run-examples -f none vlib/arrays/parallel/` too - arrays: fix `v doc -unsafe-run-examples -f none vlib/arrays/` too - compress.deflate,compress.gzip,compress.zlib,compress.zstd: fix `v doc -unsafe-run-examples -f none vlib/compress/` too - sokol.audio: fix doc comment examples - encoding.base64: fix doc comment examples - math: fix doc comment examples - readline: fix doc comment example by removing it - semver: fix doc comment examples - vdoc: enable example lines that have explicit imports too, fixup the remaining vlib examples, so `v doc -v -unsafe-run-examples -f none vlib/` could be added to the CI - Add euler.v - examples,gg: add examples/gg/grid_of_rectangles.v; add gg.Context.draw_rect_filled_no_context/5 and gg.Context.draw_rect_empty_no_context/5 - veb.auth: update the README.md example (#25245) - builtin: fix `v -W -Wimpure-v examples/hello_world.v` (move ctovstring_impl to builtin.c.v) - Fix rune casting from u32 in rune.v (#25307) ## V 0.4.11 *19 Jun 2025* #### Improvements in the language - Support a new CPU architecture s390x (#24107) - Add initial support for ppc64le (#24287) - Add initial support for loongarch64 (#24343) - Support `js"string literal"` for JavaScript strings (#24653) - VLS mode in the parser for the new language server in pure V #### Breaking changes - Remove deprecations made before 2024-11-06 - Add a deprecation note for `any` arg, prevent `any` from being used as map key,value or array type (#24277) #### Checker improvements/fixes - Fix chan element type validation with inexistent type (fix #23978) (#24008) - Do not allow auto (de)reference in PrefixExpr * - Fix check for pushing on an unwrapped option array (fix #24073) (#24093) - Fix wrong type hint on predicate arg type mismatch (fix #24122) (#24123) - Fix array generic return checking (fix #24104) (#24214) - Fix stack var outside usage when var is a mutable param (#24249) - Fix codegen for multi return with array fixed (fix #24280) (#24282) - Check anon struct field valid case (partial fix of #24284) (#24286) - Add check for recursive array init on struct (fix #21195) (#24278) - Fix inherited var turning in auto heap (fix #24306) (#24312) - Remove redundant callexpr `c.expr(mut node.left)` rechecks for `ast.CallExpr` (fix #24353) ( #24380) - Do not allow &u8(0), force nil like we do with &Type(0) - Relax the new warning, allow for `pub const pname = &char(C.SDL_POINTER)` to fix the clean compilation of code using vlang/sdl3 - Fix for with mut generic value (fix #24360) (#24426) - Add check for decomposing to interface (fix #24441) (#24453) - Fix generic option array arg passing to `[]T` (fix #24423) (#24457) - Fix resolver for returning struct generic (fix #24493) (#24506) - Reallow passing closures as voidptr parameters with no warning, to enable convenient interfacing with C libs - Disallow invalid expr for `filter`, `count`, `any`, `all` (fix #24508) (#24540) - Replace warning by notice for UTF8 strings validation (fix #24538) (#24543) - Revise logic for reporting import conflicts with module names (#24539) - Fix struct update expr checking, when an alias is used (fix #24581) (#24582) - Fix fn var resolver (fix #24525) (#24542) - Fix checking for int to array of interface (fix #24624) (#24625) - Cycle through all `ast.ParExpr` first in `prefix_expr` (fix #24584) (#24588) - Move `arr <<` logic to `check_append()` - Fix mutable const bug (fix #14916) - Allow for calling main() inside _test.v files - Fix missing type bounding to match expr on `or{}` expr (fix #24656) (#24658) - Add error for `if mut x != none {`, when `x` is an immutable option (fix #24692) (#24694) - Fix compound selector smartcasting/option unwrapping (fix #24662) (#24712) - Fix mutable option (fix #18818) (fix #24622) (fix #24101) (#19100) #### Parser improvements - Fix parse_cflag() support other flags between allowed_flags (fix #24121) (#24146) - Minimise allocations done for the common case in find_struct_field - Fix orm generic struct table type parsing (fix #24049) (#24149) - Fix mutiple imports at one line (#24241) - Fix range expr precedence on compound logical and operator (fix #24252) (#24275) - Fix invalid field name checking (fix #24279) (#24283) - Fix wrong string parsing (fix #24297) (#24298) - Fix panic for `struct Abc { pub mut: }` (fix #24404) (#24403) - Allow `mut static counter := 0` inside `unsafe {}` blocks (prepare for removing a `-translated` mode quirk) - Fix duplicate mod imports (fix #24552) (#24559) - Reduce memory usage of ast.ScopeObject and ast.Ident instances (#24704) #### Comptime - comptime: fix comptime parameter resolve for `unsafe { nil }` to be `voidptr` (fix #25558) ( #25570) - comptime: fix codegen ptr field reading from comptimeselector (fix #25616) (#25620) - comptime: dont emit empty blocks (#26171) - comptime: support type interpolation in the msg argument of `$compile_warn(msg)` and `$compile_error(msg)` (#24992) - comptime: fix $match with fn type (#25271) - Support `$if T is $pointer {` and `$if T is $voidptr {`, to make it easier to implement a pure V dump(), without cgen specific code (#24628) - i32 is now `$int` too (fix #24346) (#24378) - Fix `$dbg` with `@[heap]` structs (fix #23979) (#23989) - Check invalid comptime field name assignment (fix #24415) (#24421) - Enable s390x + docs (#24114) #### Compiler internals - Remove closure usage from the compiler frontend (simplify bootstrapping/porting on more exotic platforms) - markused: support orm or expr (fix #24040) (#24059) - markused: fix for gated index range on string (fix #24187) (#24200) - v.util.version: fix output for V full version when VCURRENTHASH not defined (#24264) - markused: fix generic method call mark (fix #24395) (#24399) - v.pref: add get_build_facts_and_defines/0 and set_build_flags_and_defines/2 - v.util.version: fix output for V full version (followup on issue #24263 and PR #24264) (#24478) - v.util: use internal diff (#24495) - v.pref: prevent overriding backend (fix #21758) (#24526) - markused: fix for generic ptr receiver on method call (fix #24555) (#24558) - markused: fix `x := t.wait()`, when `t := go fn () string {` (fix #24577) (#24580) - markused: fix printing smartcasted interface values (fix #24579) (#24583) - pref: avoid changing the backend with `.js.v` when `-backend` has already been used (fix #7840) ( #24654) - Remove dump() calls inside the compiler itself (make bootstrapping of dump() implemented before cgen easier) #### Standard library - builtin: string.index_after() ?int - cli: account for initial indent on subcommands (#23985) - Remove `strings.Builder.clear()`, fix `array.clear()` not working in the JS backend (#23992) - gg: make draw_rect_empty/5 draw more exact borders, independent of the device, and fitting the draw_rect_filled/5 shapes (#24024) - sync: fix a helgrind false positive, for a data race, on PoolProcessor (#24023) - sync.pool: restore the parallel operation (surrounding the cb call in process_in_thread in a lock in 1b52538, effectively disabled parallelism) - x.crypto.chacha20: change internal cipher to support a 64 bit counter (related to #23904) (#24039) - os: fix swap_bytes_u64 (#24033) - x.crypto.chacha20: fix `xor_key_stream` failing after a while (fix #24043) (#24046) - crypto.sha3: be big-endian friendly (#24045) - x.crypto.chacha20: makes the underlying cipher routine aware of the 64-bit counter (#24050) - x.crypto.chacha20: enable support for 64-bit counter (fix #23904) (#24053) - x.crypto.slhdsa: add a SLH-DSA implementation, a stateless hash-based DSA, a post quantum cryptographic module (#24086) - encoding.binary: add encode_binary()/decode_binary() generic functions (#24106) - crypto.rc4: change the return type of `new_cipher` to be `!&Cipher` (#24113) - crypto: add a `crypto.ripemd160` module (#24119) - encoding.iconv: fix iconv on termux (fix #23597) (#24147) - sync: remove the call to C.pthread_rwlockattr_setpshared (not needed, since it is the default on POSIX) (#24166) - pkgconfig, termios: Support NetBSD (#24176) - encoding.binary: fix serialize map struct (fix #24190) (#24192) - builtin,v.gen.wasm: support `-b wasm -d no_imports` (#24188) - datatypes: add a Set.array/0 method to help get all the elements from a set as an array (#24206) - json: fix option time (fix #24242) (fix #24175) (#24243) - log: add local time / utc time selection support (#24268) - json: link with libm (fix #24272) (#24273) - rand: add uuid_v7(), session function, simplify uuid_v4() (#24313) - toml: fix handling of multiline string with CRLF (fix #24321) (#24322) - toml: fix crlf escape check (fix #24328) (#24329) - x.json2: add u16(),u32() (fix #24337) (#24342) - rand: fix uuid_v7 seperator (#24348) - rand: check the separators for the generated UUIDs in random_identifiers_test.v - builtin: add string.is_identifier() (#24350) - x.crypto.chacha20: add a check counter overflow to set_counter for standard mode (#24365) - comptime: fix `$if var.return_type == 1 {` (fix #24391) (#24393) - comptime: enable ppc64le, add docs (#24433) - toml: add compile error when passing `encode/1` types of T != struct (fix #24435) (#24443) - sync.stdatomic: workaround for libatomic.a indirect symbols tcc bug (fix #23924) (#24472) - math.big: fix the + operator for big.Integer for negative numbers, add test (#24487) - math.big: respect the sign of the dividend in % operator, add test (#24489) - os: add note for the availability of the debugger_present implementation (#24492) - term: add writeln_color() (#24463) - math.big: add missing assert for test_multiply_karatsuba_02 (#24534) - builtin: fix mix prod and debug ucrt lib (#24498) - math.big: fix Karatsuba's add_in_place() function, add carry handler on exit (#24541) - math: add `exp_decay` to `interpolation.v` (#24545) - math.big: optimize divide_array_by_digit() (#24566) - sync.stdatomic: add atomic types (#24561) - sync.stdatomic: turn panic() in new_atomic[T]() into a $compile_error() (#24573) - sync: add condition support (#24574) - builtin: flush stdout on panic (#24606) - Document the behaviour of % for negative numbers; in V: -10 % 7 == -3 (#24604) - math.big: remove unnecessary casting from Integer.is_power_of_2/0 (#24614) - math.big: make is_power_of_2() be false for negatives (it now matches Julia's ispow2/1) (#24619) - vlib: vanilla_http_server (#24202) - os: support `dotfiles := os.walk_ext('.', '', hidden: true)` (#24617) - builtin: remove playground related code (the current playground uses a container/sandbox) (#24632) - comptime: fix `T.indirections` comparison (fix #24630) (#24636) - math.big: add test for radix_str() and integer_from_radix() (#24644) - runtime: make free_memory() and total_memory() return Result types to allow for reporting errors ( #24651) - math.big: improve the performance of radix_str() ~9 times (#24666) - math.big: speed up ~10x integer_from_radix() (#24674) - sync.stdatomic: fix bug with add() and sub() returning the new values, add voidptr support, add swap() and compare_and_swap() (#24685) - sync.stdatomic: add atomic_thread_fence(), cpu_relax() (#24690) - v: support `@DIR` (as a comptime equivalent to `os.dir(@FILE))` at runtime) (#24742) - thirdparty: print the glGetError() code on failure too in sokol_gfx.h, to make diagnostic easier - builtin: make array.ensure_cap/1 public - os.font: fixes for `-os android` - vlib: add a pool module (#24661) - zstd: make the api more V like - szip: fix panic on empty files (#24335) #### Web - net: add `read_ptr/2` (from `read/1`) to `UdpConn` for consistency with `TcpConn` (#24000) - net: make `close/0`, `select/2` and `remote/0` methods of `UdpSocket` `pub` (#24004) - Fix $dbg on function that uses veb comptimecall (fix #23999) (#24088) - veb: allow route methods, that are tagged with `@[unsafe]` - veb: support `-d veb_max_read_bytes=16384`, `-d veb_max_write_bytes=16384`, `-d veb_default_port=1234`, `-d veb_max_http_post_size_bytes=8388608` - net.http: support `v -http -d http_folder=vlib/_docs` (allow customizing the folder, port, and index file through CLI arguments to v -http) - thirdparty: upgrade to mbedtls v3.6.3.1, add a .patch file with the local changes (#24602) - veb: fix handling of default CorsOptions.allowed_headers (#24703) #### ORM - orm: fix default value quote (fix #24052) (#24057) - orm: fix type alias not supported in table columns (fix #15478) (#24062) - orm: fix gen sql complex where (fix #24136) (#24138) - orm: skip orm_complex_where_test.v for `sanitize-memory-clang` too - orm: add function call based builder API for dynamic queries (fix #24178) (#24196) - orm: set default value for require field if database value is null (fix #24221) (#24222) - orm: fix option field with default null value (fix #24222) (#24228) - orm: add or_where() method to the builder (fix #24244) (#24250) - orm: add IN and NOT IN (#24634) - orm: add `in` and `not in` to orm_func (fix #24639) (#24642) - breaking,orm: add table attrs; add table/field comment support for mysql and pg (#24744) #### Database drivers - db.mysql: use mysql datatype for alloc string_binds_map, not orm's (#24126) - db.mysql: fix handling of nullable timestamp (fix #24120) (#24125) - db.mysql: add null result support (fix #24130) (#24131) - db.mysql: use hardcoded const declare (fix #22086) (#24162) - db: connection pool (#24161) - db: mysql,pg,sqlite add transaction support (fix #24290) (#24352) - db.pg: fix incompatible fn signature (#24549) - db: add redis (#24730) #### Native backend - native: use builtin exit function (#24578) - native: improve string support (#24600) - native: implement `for in string` for amd64 (#24613) - native: support nested structs, improve support for right expr of IndexExpr (#24627) - native: leave only the unique paths in g.linker_include_paths, before doing lookups - native: support C constants (#24660) - native: add a temporary special case for `C.EOF` (#24724) #### C backend - Fix parallel cached_type_to_str access (fix #23980) (#23998) - Fix codegen to make mutable sumtype working (fix #23982, part 1, needed for bootstrapping) ( #23988) - Fix arm64 asm operand position; fix arm64 asm imm; support arm64 dot instruction (#24017) - Fix mutable ptr sumtype (#24021) - Fix asm comments of arm32 (#24025) - Allow asserts inside fns, called in const/global initialization, in test files (fix #24029) ( #24031) - Fix codegen for option return unwrapping on last statement (fix #24026) (#24030) - Fix match option with case non option (fix #24047) (fix #24048) (#24051) - Support measuring programs, that use multiple threads in the new profiler column (turn `prof_measured_time` into a thread local, for the supported C compilers) (#24061) - Fix `@[keep_args_alive]` with ptr (fix #23973) (#24058) - Remove unused macro V64_PRINTFORMAT - Fix option array push on unwrapped array (fix #24073) (#24079) - Fix nested array support for the orm (fix #19327) (#24080) - Fix `x in [...]!` operator with fixed arrays (fix #24082) (#24083) - Fix codegen for comptime multiline attr (fix #23964) (#24087) - Fix codegen for selector with embed field option (fix #24084) (#24085) - Fix generic result return (fix #24097) (#24100) - Fix showing the expression, as literal value, in case of `assert s[x..y] == "literal"` (fix #24103) (#24105) - Fix codegen for option unwrapped var passed to generic option type (fix #23972) (#24096) - Fix selector option unwrapping on infix (fix #24108) (#24115) - Sort the paths, used in coutput_test.v - Skip emitting mman.h and pthreads related code, for freestanding builds (#24118) - Add s390x assembly support + test (#24129) - Parser,checker,cgen: fix wrong auto heap deref of auto `index` loop var (fix #24117) (#24124) - Fix non-voidptr to voidptr on `-cstrict` + notice about such usage (fix #24139) (#24143) - Fix multi return with option type (#24144) - Remove obfuscation (`strip` should be used instead); temporary fix for usecache + toml - Fix zero left padding (fix #24199) (#24201) - Fix variadic sumtype args passing (fix #24150) (#24207) - Fix codegen for const to c string (fix #24235) (#24248) - Fix codegen for fixed array init with init using structinit (#24269) - Fix missing braces for const init with castexpr from option unwrapping expr (#24276) - Fix codegen for index expr on for loop with branchstmt (fix #22760) (#24289) - Fix codegen for assigning fixed array on defer var (fix #24300) (#24305) - Fix codegen for multi return with aliased fixed array (fix #24280) (#24295) - Fix codegen for nested selector unwrapping on lhs (fix #24292) (#24293) - Add ppc64le assembly support + test (#24299) - Fix s390x closure thunk (use floating point register) (#24258) - Fix riscv64 closure thunk (use floating point register) (#24315) - Fix codegen for writing on unwrapped selector (fix #24316) (#24323) - Fix codegen for thread.call() on var auto heap (fix #24326) (#24327) - Fix codegen for handling multiple return result type on call (fix #24341) (#24344) - Fix codegen for nested selector option ptr (fix #24339) (#24345) - Fix arm64 closure + remove stub in test (#24332) - Workaround tcc aarch64 bug (fix #24331) (#24354) - Fix riscv32 closure (#24355) - Fix codegen for anon option fn struct field init (fix #24392) (#24400) - Fix `if mut var != none {` for optional interface values (fix #24351) (#24410) - Fix interface `unsafe {nil}` comparison and initialization (fix #24374) (#24411) - Ast,cgen,parser,pref: support loongarch64 inline assembly, add test (#24440) - Fix array init with interface element type (fix #24442) (#24454) - Fix const declaration dependant mapping when using update_expr (fix #24437) (#24455) - Fix comptimecall with map receiver (fix #24448) (#24449) - Fix assign from `for mut var in arr {` to pointer (fix #24432) (#24456) - Workaround tcc aarch64 fn call bug (fix #24473) (#24477) - Workaround tcc aarch64 spawn call bug (fix #24482) (#24483) - Fix map of fixed array value in if guard (fix #24488) (#24496) - Fix codegen for assigning `nil` or `0` to option ptr field (fix #24447) (fix #24500) (#24502) - Fix codegen for array of option element auto eq `a == [?int(none)]` (#24504) - Fix codegen inconsistency handling `nil` param to arg expecting ptr (fix #24491) (#24503) - Fix pattern generated by `const_init_or_block.vv` in `vlib/v/gen/c/coutput_test.v`, when VFLAGS=-no-parallel is used - Fix tmp var redeclaration on const inited later (fix #24521) (fix #24517) (#24524) - Fix generic name handling for struct generic (fix #24530) (#24565) - Fix initialize error object in or_block (fix #24529) (#24576) - Improve the readability of `switch() {` statements, generated by `match() {` ones (#24618) - Reduce v.c size by ~4% by removing comments and using shorter literals - Fix enumval str() call on stringinterliteral (fix #24702) (#24705) #### JavaScript backend - Fix array type checking in sum type match expressions (fix #24237 ) (#24259) - js: fix callbacks in structure parameters (fix #24260) (#24324) - Fix array initialization with "index" and "it" (fix #24397) (#24429) - Cannot assign unsafe nil values (fix #24407, #24436) (#24458) - Fix alias type initalization (fix #24475) (#24480) - Fix casting (fix #24512) (#24519) - Alias types are not properly resolved (fix #24486) (fix #24507) (#24514) - Implement Map.keys() and Map.values() methods (fix #24209) (#24608) - Fix string.runes method (fix #20500) (#24609) - Fix direct map key access and map.len (fix #24616, fix #24605) (#24620) - Fix map to string fails on rune keys (fix #24637) (#24638) - Fix maps being always constructed using string keys (fix #24607) (fix #24671) (#24673) - Fix slightly incorrect JS (esbuild was broken on master) (fix #23711) (#24676) #### vfmt - Convert `"hello".str` => `c"hello"` (fix #24635) (#24652) #### Tools - Let test_os_process.v use `unbuffer_stdout()` to make the output more reliable - os,tools: make easier analyzing process_test.v failures on the CI - ci: fix build conditions that had `sanitize-memory-clang?` instead of `sanitize-memory-clang` - ci: skip running the `s390 CI` job for simple doc/yml changes (#24160) - ci: fix shell script issues reported by actionlint (#24168) - Remove the `src` subdir from projects, created by `v new` (#24236) - Add support for `// vtest build: !os_id_ubuntu?` tags in the _test.v files, detected by `v test` - ci: fix `v -o v2 -usecache cmd/v` after ad5b829 - Fix vrepl for `import mod { f }` (#24340) - ci: debug hub_docker_ci.yml issue (try 1, disable cache, run linters) - ci: debug hub_docker_ci.yml issue (try 2, add concurrency group, add a persistent single builder `gh-builder`) - ci: debug hub_docker_ci.yml issue (try 3, restore the cache-from:/cache-to: lines) - ci: fix hub_docker_ci.yml issue - comment out the cache-from:/cache-to: lines again - Support vreduce timeout, vreduce custom run command (#24359) - Rewrite `v timeout`, support killing the child process on timeout by default (#24367) - Use breadth first search in vreduce (#24369) - Vreduce fix var names (#24373) - Fix `v timeout 2 sleep 5` - Fix `./v -d network test cmd/tools/vpm` - ci: reduce false positives for cover_test.v and vdoc_test.v - Save the modified content more frequently in `v reduce`, fix timeout leaks (#24405) - Reduce padding for `v doc` produced html nodes too - ci: reduce the noise in check annotations for github PR reviews, due to the new warning in option_test.c.v - Improve show_ancient_deprecations.v, by ignoring false positives for deprecation tags in // comments - Check for Git repository in `v doctor` (packaged V versions often lack a .git/ folder) (fix #24419) (#24420) - vlib,tools: add an `arrays.diff` module, implement a simple platform independent tool `v diff file1.txt file2.txt` using it (#24428) - ci: bump creyD/prettier_action from 4.3 to 4.5 (#24439) - ci: use `v retry` to reduce the false positives for retrieving the dependencies for vinix too - ci: show `hg version` too, to ease the diagnosing of install_version_test.v failures - Let cmd/tools/vpm/install_test.v use a .hg/hgrc file too - repl: fix typeof(a) with warning (fix #24499) (#24515) - Make `v doctor` show CFLAGS and LDFLAGS too (if set) - Make `v search ui` work again through the vpm site (fix #23966) (#24535) - ci: fix unused var warning in cmd/tools/vpm/common.v - ci: prevent future changes to cmd/tools/vpm/common.v, that introduce warnings/notices to pass in PRs - x.benchmark: align the output of BenchmarkResult.print/0 - Ease diagnosing CI failures of vtimeout_test.v - ci: make sure that only one copy of native_test.v is executed at once, when run through `v test vlib` (fix #24505) - Ignore .db and .sqlite files by default in `v watch` (such DB files are very likely to change during prototyping) - .gitignore: ignore .db and .sesskey files as well - ci: bump creyD/prettier_action from 4.5 to 4.6 (#24687) - Make `v doc -f md module` output useful by default (#24737) - ci: fix native_backend_ci.yml concurrency group setting (prevent jobs for different commits on master to cancel each other) - Fix overflow detected in the sanitized runs on the CI (#24064) - ci: reduce code duplication in linux_ci.vsh #### Operating System support - os: implement Process.is_pending() on windows (fix #23990) (#23993) - os: support .set_environment() on windows too (fix #10628) (#23996) - thirdparty: update thirdparty-linux-amd64_tcc.sh, to also record its own full invocation command, and commit the changes automatically - thirdparty: add thirdparty/build_scripts/thirdparty-freebsd-amd64_tcc.sh - ci: reduce false positives for slow runs of the gcc-windows job - gg: fix screen_size() on macos with multiple displays - ci: add riscv64_linux_ci.yml (based on QEMU) as well (#24181) - ci: use `apt update` before `apt install` in cross_ci.yml, to make the linux job more robust - thirdparty: add thirdparty/build_scripts/thirdparty-macos-arm64_tcc.sh for compiling tcc on macos (first draft) - Simplify the implementation of get_linux_os_name in `v doctor` - os.filelock: compile without warnings with gcc on windows - ci: use windows-2025 for the gcc-windows job (since it has gcc 14.2.0) (#24304) - ci: skip option_ptr_unwrap_test.v on windows with msvc (#24320) - os: fix windows rmdir GetLastError() (fix #24356) (#24357) - Enable windows tcc_backtrace() support (#24377) - ci: reduce false positives for init_global_test.v on windows (retry it 2 times) - ci: reduce false positives for orm_func_test.v on windows (retry it 2 times) - os: force using `C.CREATE_NO_WINDOW` on windows in os.raw_execute/1 (fix #24390) (#24418) - Fix v doctor output on FreeBSD ; do not run ldd to get the glibc version (#24427) - runtime: improve free_memory implementation for OpenBSD, by getting the stats from its UVM system (#24431) - runtime: fix cast error in free_memory implementation for OpenBSD (#24445) - Use a `.hg/hgrc` file for install_version_test.v (workaround windows failure) - os: add debugger_present implementation for OpenBSD (fix #23603) (#24490) - veb: reduce veb_max_write_bytes from 16KB to 2KB (fix sending large dynamic responses from veb on macos/freebsd) (fix #24523) (#24522) - os: fix os.File's tell/0 method for windows (fix #24217) (#24218) - net.openssl: replace SSL_get1_peer_certificate by SSL_get_peer_certificate for OpenBSD (#24556) - net.mbedtls: disable AES-NI on OpenBSD with tcc (fix #22239) (#24560) - net.mbedtls: enable MBEDTLS_THREADING_C and MBEDTLS_THREADING_PTHREAD on OpenBSD (#24572) - thirdparty: add thirdparty/build_scripts/thirdparty-openbsd-amd64_tcc.sh for compiling tcc on OpenBSD (#24592) - v.builder: enable -fwrap for C compilation on OpenBSD too (#24585) - v.pkgconfig: add the default `/opt/local/lib/pkgconfig` for MacPorts on macos (#24626) - sync: increase retries for vlib/sync/select_close_test.v to 3, to reduce CI false positives in the gcc-windows job - ci: remove script to build tcc on FreeBSD (obsoleted by thirdparty/build_scripts/thirdparty-freebsd-amd64_tcc.sh) (#24681) - encoding.iconv: add path for iconv library on FreeBSD (#24682) - native: skip linux.vv too, for the sanitized jobs (similar to libc.vv) - ci: migrate from windows-2019 runner to windows-2025 runner in most jobs (github deprecated the 2019 runner) (#24672) - runtime: fix -cstrict compilation (use usize() cast in free_memory) on OpenBSD (#24696) - Remove specific case for FreeBSD in `cmd/tools/vtest_test.v` (#24707) - docs: add section in README for compilation on FreeBSD (#24706) - thirdparty: add script to build libgc on FreeBSD/amd64 (#24717) - builtin: use local static libgc for FreeBSD with tcc (fix #24710) (fix #24683) (#24720) - ci: update and improve FreeBSD CI (#24726) - ci: add CI for OpenBSD (#24732) - gg: fix .char event handling for backspace, delete, tab and enter for linux/x11 (send appropriate .char codes to the apps, similar to macos) - Add aarch64 atomics support in thirdparty/stdatomic/nix/atomic.h (fix #24294) (#24296) - v.trace_calls: now musl has gettid(), there is no need for the shim on newer Alpine etc (#24245) #### Examples - Fix `v -os wasm32_emscripten -o ms.html examples/gg/minesweeper.v` (use os.asset to load the font, avoid the implicit closures for the frame/event callbacks)' - Update rotating_textured_quad.v with instructions on how to compile/run it with emscripten and a browser - Add a small examples/gg/bouncing_balls.v simulation of falling balls - Fetch 30 stories instead of 10 in examples/news_fetcher.v - Add sync_pool.v for easier testing/diagnosing issues with the `sync.pool` implementation on different platforms - Add a `-profile` report column, to show only the func time, *excluding* the accumulated children calls time (usable through `./v -profile - run a.v |sort -nk3` for example) (#24056) - doc: improve Shared and Channels's topics, add more examples (#24155) - orm: fix option type, convert from int to i8, add examples, etc (fix #24211) (#24213) - Fix optional callback parameter and improve examples (fix #24325) (#24336) - Reduce padding for code examples, to fit more examples on the same screen without scrolling - Cleanup unsafe{} blocks that are not needed anymore in examples/sokol/08_sdf/sdf.v - Show the number of pushes in sokoban too - os.asset: add read_text/2 too, use it to simplify the sokoban example - Support directly loading sokoban level files by path - Add more Sokoban levels - Support boxoban style collections of levels files ( from https://github.com/google-deepmind/boxoban-levels/) - Add a simple sudoku solver - Add primes.v, that shows how to get command line arguments, and use loops and functions - Add a small memory game (#24643) - Cleanup memory.v (reduce it to 135 lines) - builtin,os: enable no warnings for gg programs like `v -gc boehm_leak -cg -keepc run examples/gg/minimal.v` (part 1 - before the `gg` loop) (#24749) ## V 0.4.10 *20 Mar 2025* #### Improvements in the language - Implement assignable anonymous struct (fix #23855) (#23857) - Remove ancient deprecations (#23479) #### Breaking changes - Make old `[attr]` syntax an error (`@[attr]` has to be used instead) - builtin: `string.index_after()` now returns an Option (like `string.index()`), use `string.index_after_()` for the old behavior - Vweb is now deprecated in favor of faster and more stable and easy to use veb #### Checker improvements/fixes - Allow `none` to be passed to `?T` param (fix #23381) (#23385) - Fix `for` iterator method `.next()`, not marked as used (fix #23312) (#23321) - Fix generic var inferring to be passed to `[]T` (fix #23315) (#23322) - Clean up and optimise infix - reduce `as` casting (#23327) - Fix structinit validation on nested generic Map[K]V (fix #23329) (#23332) - Fix comptime indexexpr resolving (#23333) - Fix comptime evaluation on infix expr (fix #23341) (#23344) - Fix alias to fixed array w/ size defined by constant (fix #23356) (#23357) - Fix missing option variable checking when casting using `as` operator (fix #23349) (#23358) - Fix assign expected type on rechecking enum assigns (fix #23366) (#23367) - Allow calling `foo(?i64(123))` for `fn foo(x ?I64) {` and `type I64 = i64` (#23373) - Cache `node.args[0]` on `fixed_array_builtin_method_call` and `array_builtin_method_call` (#23411) - Fix missing check for invalid prefixexpr expression `&(&var)` (fix #23365) (#23418) - Disallow `&((&a))` and similar expressions, with innermost `ast.PrefixExpr` (enhance #23418) ( #23419) - Fix call with mut arg with different pointer levels (fix #23157) (#23428) - Fix missing detection for `return` in lockexpr stmts (fix #23434) (#23435) - Do not allow auto reference of voidptr params - Check if unwrapped `m[key]` if m is `Option` (fix #23446) (#23459) - Builtin,checker: remove `@[markused]` from `fn isnil()`, set `c.table.used_features.auto_str_ptr = true` instead (#23464) - Fix checker generic alias type (fix #23474) (#23475) - Fix missing check for `a := [none]` (fix #23457) (#23504) - Fix missing check for concrete type on match branch expr (fix #23506) (#23508) - Fix missing check for invalid argument for builtin (fix #23511) (#23515) - Fix selector nested unwrapping (fix #23519) (#23521) - Fix message with old attr syntax (#23529) - Cache repeated `node.args.len`, `method.generic_names.len`, `node.concrete_types.len` and `node.op.str()` (#23536) - Disallow `expr is Type` if expr is Optional (fix #23486) (#23510) - Make `option_var.str()` an error, when done without unwrapping it first (fix #23557, fix #23558) ( #23563) - Fix private symbol visibility checking (fix #23518) (#23543) - Disallow constant modification on unsafe {} (#23588) - Fix sumtype variant option type mismatch (#23659) - Disallow `arr = voidptr(0)` (fix #23675) (#23687) - Allow for `module no_main` programs, that can redefine their own main function, or not define any of their own as well - Fix match branch checking of nonreturn call on last expr (fix #23698) (#23699) - Check and error for invalid utf8 string literals (#23721) - Fix call from unknown enum (fix #23728) (#23730) - Add checker for passing multi return as arg to func that expects less param (fix #23735) (#23744) - Fix spreed operator ref field validation (fix #23759) (#23760) - Fix missing check for method that returns veb.Result (fix #23647) (#23762) - Allow generic operators to be called in fn (fix #23773) (#23774) - Fix missing struct cast validation (fix #23748) (#23788) - Fix map when casting to interface (fix #23790) (#23799) - Allow for `pub type C.HINSTANCE = voidptr`, being used in ``` @[export: "wWinMain"] fn mymain(x C.HINSTANCE, xprev C.HINSTANCE, lpcmdline &C.WCHAR, cmdshow int) int { ``` in `module no_main` programs (#23812) - Add option type inference on if expr (implement most of #23827, except the error for `v := if c { none } else { none }`) (#23829) - Add missing check for IfExpr and MatchExpr with no valid type (#23832) - Fix MatchExpr type inferring, when `none` is used (fix #23831) (#23833) - Add missing check for generic fntype type names (fix #23453) (#23850) - Add checking for comptime assign without comptime if checking (fix #23796) (#23848) - Fix option ptr field assign checking (fix #23879) (#23880) - Add missing `any` type validation on assignment (fix #23905) (#23906) - Add fntype casting validations (#23872) - Fix signed integer literal overflow error, when most significant bit occupies signed bit (fix #23782) (#23919) - Add missing check for casting generic type to literal values (#23915) - Check if next() method infers generic type correctly (fix #23927) (#23932) - Disallow references to constants (fix #23935) (#23942) - Fix typeof evaluation for generic reference (fix #23951) (fix #23952) (#23958) #### Parser improvements - Reduce allocations in empty_comptime_const_expr (#23324) - Add error for array init of Results `[]!type{}` (fix #23360) (#23375) - Allow map cast syntax `map[k]v(expr)` (#23401) - Inline some commonly used fns (#23535) - Fix anon fn return type option/result followed by comment parsing in vfmt mode (fix #23607) ( #23608) - Keep track of the number of all scanned tokens too, and show it with `-stats` - Fix the error message position, for a `struct Abc`, that lacks a body (#23627) - Prevent unused warning on `import mod { Sym }`, when `Sym` is later used, for more cases (fix #23412) (#23626) - Add support for `-d trace_parse_file_path_and_mod`, to help diagnosing module lookup problems - Allow for `@[has_globals]` to be used for all V programs, turn the `@[wasm_import_namespace]` error into a notice - Remove table dep for script main check - Fix enum value parsing inside array initialization (fix #23937) (#23941) - Fix the registration of fixed arrays, when size_expr is a const (fix #23946) (#23949) - Disallow invalid expr in comptime `$for` (fix #23953) (#23959) #### Compiler internals - markused: fix `-skip-unused` on a short program, that prints array (fix #23436) (#23437) - markused: fix `eprintln(err)` on imported module on short program (related: #23498) (#23499) - markused: fix markused auto str detection (fix #23501) (#23503) - markused: fix option ptr printing (fix #23559) (#23562) - checker,markused: add identification for sumtype.type_name() call (fix #23732) (#23739) - markused: improve stability (avoid runtime crash) when processing generic functions (partial fix for #23927) - markused: fix markused behavior on array / map index getter / setter / slice (#23931) - markused: fix markused behavior on struct field's default expression (fix #23909) (#23933) - builder: do not search for msvc when it is not needed (#23386) - pref: stop parsing CLI options, on encountering `--` (#23470) - util: show `unknown command` suggestions, for more misspelled variants, like `v sefl`; make util.new_suggestion calls parametrizable - pref: add Preferences.vroot_file/1 (done here, without using it, to ease the bootstrapping of the cheaders extraction, that will follow next) - pref: fix panic in parse_args_and_show_errors, called with no args (fix #23713) (#23794) - pref: allow for `-os wasm32_emscripten` and filtering `_d_wasm32_emscripten.c.v` and `_notd_wasm32_emscripten.c.v` files. (#23797) - v.builder: show the last line of the C compiler output, in case of errors, in addition to the truncated first lines (the last line is useful, since it usually has an error counter) - os,v.transformer: fix warnings for `./v -os cross -o vc/v.c cmd/v && clang-18 -o v_from_vc vc/v.c -lpthread` - util: fix stack overflow during parsing of `#flag -DName=$d(...)` (#23895) - builder: extract Builder.show_parsed_files/0 to make it easier to debug import/parsing issues - builder: remove forgotten b.show_parsed_files/0 call - util.version: centralise the use of `@VCURRENTHASH`, to minimise the vlang/vc diffs for each commit - builder: support `-d trace_parsed_files` - util: shorten the V paths used in the C `#line` directives with tcc (the ../../../.. etc is no longer needed with newer tcc) (#23974) #### Standard library - json: fix default struct field initialization with long array (#23355) - markused,builtin,strconv,vlib: reduce generated C sizes for compilers != tcc, for short programs, by simplifying the generation of backtraces, and reducing string interpolations in panics (#23380) - thirdparty/sokol: allow `-cflags -D_SGL_DEFAULT_MAX_VERTICES=4194304` to customize how many vertices you can send through gg/sokol in a frame - crypto.ecdsa: expand ecdsa module, to support other curves like secp384r1, secp521r1, secp256k1 ( #23407) - crypto.ecdsa: fix memleaks, reported by the CI sanitizer jobs (#23450) - ci: force the checking of changed vlib/crypto/ecdsa files with the sanitizer jobs - builtin: add a `@[markused]` tag to `isnil()`, because cgen generates calls to it in some cases ( #23462) - builtin: reduce a bit the generated #if defined checks for small programs (#23484) - crypto.ecdsa: improve safety checking, unify signing (and verifying) api to accept options ( #23463) - regex: fix misspelled word "firts" in replace_n description (#23514) - os: add split_path/1: `os.split_path('/usr/lib/test.so') -> ('/usr/lib','test','.so')`; fix platform dependent behaviour of os.dir/1, os.base/1, os.file_name/1 (#23532) - breaking,log: set stderr as default log output, add .set_output_stream() to allow for opting in the old default of stdout (#23444) - builtin: add `-prealloc -d prealloc_memset -d prealloc_memset_value=65 -d prealloc_dump`, to better analyze the memory patterns of running V programs - builtin: change the default builder size used for string interpolations, from 256 bytes to 64 bytes - gg: mark create_image_with_size as deprecated (image resizing is done by `stbi.resize_uint8/3`, with a different fn signature) (#23580) - crypto.ecdsa: split out the C wrapper to a new .c.v file (#23595) - builtin: add &u8.free() (fix #23592) (#23598) - crypto.ecdsa: fix bug in .with_no_hash handling (#23612) - crypto.ecdsa: fix handling of sign() with custom_hash (#23619) - runtime: add note for the availability of the free_memory/0 implementation (#23620) - builtin: make public the `FnGC_WarnCB` alias (#23633) - os: add disk_usage/1 (#23634) - builtin: add string.split_by_space() (#23651) - crypto.ecdsa: migrate `ecdsa.PrivateKey.new()` to use a high level API (#23640) - gg: fix incorrect Event.mouse_x and Event.mouse_y on gg.Context.event_fn and gg.Context.on_event on HiDPI displays (#23668) - crypto.ecdsa: migrate generate_key and simplify it (part 3) (#23662) - encoding.csv: add support for multithreading to `encoding.csv.RandomAccessReader` (#23677) - v.builder: add` os.quoted_path()` to os.system calls using v.pref.out_name, for the compress flag (fix #23685) (#23686) - time: reduce chances of failures on the CI, by time_test.c.v; make the failure diagnostic easier - time: improve the robustness of time_test.c.v (check if the diff is within ±1 second of the current timezone difference) - crypto.ecdsa: migrate core routines for signing (and verifying), it now requires using OpenSSL 3 ( #23705) - all: use arguments() instead of os.args in some files - math.big: fix 1/115792089237316195423570985008687907853269984665640564039457584007908834671663 leading to panic (fix #23771) - v.cflag: support `#flag $when_first_existing(libABC.a, /some/path/libABC.a, ...)`, without panicing (unlike `#flag $first_existing(...)`) (#23780) - term: add more comments in vlib/term/README.md - log: fix panic on mutex destroy, when exiting a program, while a thread is still logging - log: fix valgrind_test.v failure - math.vec: add `rotate_around_*` (cw/ccw) functions to `vec.Vec2[T]` (#23807) - math.big: bump newton_division_limit to 1_000_000 (workaround issue #23806) - math.big: add vlib/math/big/big_division_test.v (follow-up to 270941a) - strconv: fix strconv.atof64() inconsistency with the other .ato functions; make it return an error by default, when it detects an extra non number character after a number (#23815) - os: add File.write_u8/1 and File.read_u8/0 helper methods - ci,os: fix bootstrapping with `-os cross -o vc/v.c` (avoid the generic calls in the new write_u8 and read_u8) - log: remove the notice about the stdout -> stderr migration (#23837) - veb: fix "error parsing request: io.Eof" when expecting a request body, but the data is not ready yet (fix #22464) (#23842) - json: fix json.decode autofree codegen (fix #23834) (#23839) - time: add .week_of_year() method for time.Time instances (#23838) - time: add documentation for remaining time-related functions and ISO 8601 parsing (#23867) - crypto: add missing doc comments for public methods (#23864) - builtin,os: fix warnings for `./v -os cross -o vc/v.c cmd/v && cc -o v_from_vc vc/v.c -lpthread` - crypto.ecdsa: migrate new_key_from_seed to use high opaque, simplify the logic (#23876) - math: fix `./v -prod -cstrict -cc gcc-11 vlib/math/math_bench_test.v` (use unions to implement f64_bits/1 and f64_from_bits/1 for compilers != tcc) - crypto.ecdsa: complete the migration to the newer OpenSSL APIs (follow up to #23876) (#23877) - x.json2: add a convenience Any.as_map_of_strings/0 method - cli: add missing struct members to str() method and fix some comments (#23893) - crypto.ecda: improvement the performance of `PrivateKey.new` by avoiding match+assignments ( #23899) - crypto.ecdsa: improves internal function of `calc_digest_with_evpkey` (#23901) - crypto.aes: fix notices about order of operations (fix #23898) (#23902) - Revert "math.bits: port changes from e66e996, so that `-cstrict -cc gcc-11` passes for `markdown` as well" - crypto.ecdsa: improve the performance of the `.public_key` method of `PrivateKey` (#23920) - gg: add is_key_down/1 helper method - datatypes: optimize linkedlist (fix #23928) (#23934) - x.json2: fix "\\" scanner bug, disallow (ch < 0x20) unescaped control characters (#23954) - crypto.ecdsa: improve internal `sign_digest` routine (#23960) #### Web - veb: add `ctx.no_content()` + prevent content-type being set if the mime type is empty (#23425) - net.ftp: use unsafe { nil } - net.smtp: make public the Attachment fields (to be used as plain structs in initialisation) ( #23477) - x.vweb: remove the entire module (it's now veb) - ci: fix failure of the docker-ubuntu-musl job (keep vlib/vweb/vweb_app_test.v in the skip_files) - picoev: enable running veb services on Termux - thirdparty: improve `-cstrict -cc clang-18 -prod` compatibility for programs that do `import net.mbedtls` - net.http.file: use urllib decode uri, to handle urls to files that have unicode characters in their name (fix #23683) (#23684) - veb.csrf: do not print anything by default, add an `verbose: true` option, to restore the old behavior if needed (#23725) - net.unix: make unix_socket_test.v trace its actions more thoroughly - veb.request_id: new middleware that implements request ID tracking (#23727) - veb: update the blog tutorial - net.openssl: use proper library search path for local installations of OpenSSL 3, use `SSL_get1_peer_certificate` instead of the deprecated `SSL_get_peer_certificate` . - ci: fix vweb_run_at.run.out and vweb_run_at.skip_unused.run.out, ensure stable ordering of stdout/stderr for `v run file.v`, in case of compiling a program with warnings/notices. - veb: handle sendfile errors, when the connection is canceled, before the file is completely transferred (#23891) #### ORM - orm: fix codegen for option fk (fix #23383) (#23400) #### Database drivers - db.sqlite: add tracing for more calls, when using `-d trace_sqlite`, not just for the ORM - db.pg: add support for prepared statement, with db.prepare/3 and db.exec_prepared/2 (#23442) - db.mysql: add SSL support; turn ConnectionFlag into `@[flag]` (#23975) #### Native backend - native: fix convert_int_to_string, add comments in the verbose (-v) mode (#23743) - native: fix int prints (#23747) - native: for statement : add support for all expressions handled by g.condition (#23752) - native: fix inc and improve support for i32 (#23753) - native: support negative integer literals (#23755) - native: fix missing symbols CaptureStackBackTrace and __debugbreak (#23765) - native: fibonacci test - native: add support for enums of different types (#23786) - native: fix unsigned and signed int comparison (#23808) #### C backend - Fix type_default for option type, when the default expr is `none` (fix #23318) (#23320) - Remove double string cloning (#23331) - Fix type_default for array init >= 8 items (spotted while building the vhamll project) (#23334) - Fix codegen for alias struct embed (fix #23347) (#23353) - Fix codegen for sumtype casting on selector on as cast with non pointer field (fix #23387) ( #23391) - Fix generic alias option assigning (fix #23382) (#23393) - Fix codegen for selector on shared var with embed (fix #23378) (#23394) - Fix codegen for nested selectorexpr on unwrapped option (fix #23406) (#23409) - Cache return_stmt()'s node.exprs[0] and node.types[0] (#23408) - Fix codegen for indexing generic map (fix #23376) (#23402) - Support `-d trace_unused_by_main` and `-d trace_skip_unused_just_unused_fns`, to find out potentially obsolete functions that are not used at all in a project - Fix shared array indexing (fix #23410) (#23413) - Fix shared array fixed initializing with `-cstrict` (fix build of chip8-v project) (#23414) - Fix codegen for array fixed comparison on MatchExpr (fix #23403) (#23415) - Fix struct init for anon struct field on C structs (fix #23421) (#23422) - Fix shared array slice (fix #23426) (#23427) - Fix array of sumtype initialization with var string (fix #23429) (#23432) - Fix codegen for ifguard indexing array of option (fix #23438) (#23439) - Fix assigning option of array index (fix #23451) (#23455) - Fix compilation for a project using a lot of json, threads, embeds + parallel-cc (#23467) - Fix cgen error for `instance.t.wait()` on default 0 initialized thread field `t` (fix #23390) #23392 - Fix array decomposing on variadic call (found while working on solving #23474) (#23476) - Fix option var nested unwrapping from sumtype (fix #23478) (#23485) - Fix option unwrapping on heap var (#23489) - Fix codegen for indexing anon_fn (fix #23493) (#23495) - Fix nested option selector unwrapping (fix #23500) (#23497) - Fix interface casting in anon fn (fix #23530) (#23533) - Fix codegen for spawn with interface on submodule (fix #23471) (#23517) - Parser,ast,cgen: support nested unions with `field union {`, to improve interoperability with C ( similar to `field struct {`) (#23539) - Fix unwrapping option interface field (fix #23540) (#23541) - Fix codegen for assign from unsafe fn returning fixed array (fix #23546) (#23548) - Fix codegen for a fixed array init with different node types (fix #23545) (#23547) - Fix return on last statement of return IfExpr (fix #23550) (#23551) - Fix auto str which expects ptr for ptr type (fix #23552) (#23553) - Fix codegen for assigning from infixexpr with generic operand (fix #23560) (#23561) - Fix codegen for array's .grow_cap and .grow_len methods for generic arrays (fix #23566) (#23568) - Fix codegen for const fixed array initialization with another const as item (fix #23565) (#23572) - Fix codegen for unwrapping option comptime var (fix #23590) (#23591) - Fix hash functions for `map[Enum]Value`, and `enum Enum as u64 {` (fix #23630) (#23632) - Fix unwrap option ptr selector (fix #23631) (#23638) - Fix codegen for `for` or-block (fix #23625) (#23644) - Fix codegen for option value on `map_set` (fix #23650) (#23652) - Fix codegen for option sumtype with option variant (fix #23653) (#23656) - Remove commented code blocks using `if true {` - Reduce interpolations when a method is not found in Table.find_method/2; merge rand.constants back to rand.v (#23660) - Fix `$if typeof[T]().idx`, `$if typeof[T]().unaliased_typ` checking (#23665) - Fix codegen for sumtype cast from option variants on map_set (fix #23654) (#23669) - Fix codegen for a const assigned a fixed array, initialized with unsafe exprs (fix #23674) ( #23676) - Fix `@[sql: serial]` and `@[serial]` are not the same (fix #23346) (#23678) - Improve support for `v -path bootstrap_alternative_backend/ run simple.v` (#23679) - Fix codegen for array fixed on if and match expr (fix #23577, fix #23589) (#23682) - Add support for a `#postinclude` directive - Fix #preinclude, add test case for #postinclude too - Fix codegen for returning an initialised fixed array (fix #23693) (#23700) - Use `global_g.out << g.out` instead of `global_g.out.write(g.out) or { panic(err) }` - Fix issues found with the stricter sanitizers in clang-18 on Ubuntu 24.04 (#23710) - Fix codegen for nested if on return (fix #23723) (#23729) - Fix sumtype smartcasted var as inherited var (fix #23716) (#23731) - Fix map with an Enum as key type, with size < 4 bytes on tcc (fix #23714) (#23738) - Fix codegen for match with sumtype ptrptr (fix #23776) (#23785) - Fix aggregate var handling on match branch (fix #23768) (#23787) - Fix gowrapper codegen for receiver ptrptr (fix #23798) (#23800) - Fix regression, preventing the use of `-gc none -d no_main -no-builtin -no-preludes` to compile C style V programs - Fix array fixed assignment for `@[keep_args_alive]` (partial fix for #23804) (#23805) - Fix nested option fixed array (fix #23708) (#23845) - Fix codegen for match on return (fix #23661) (#23851) - Fix casting primitive type to alias, where option alias is expected (fix #23859) (#23860) - Fix interface method list ordering to make test buildable with `g++` (fix #23701) (#23870) - Make `./v -prod -cstrict -cc gcc-11 test vlib/math/` pass cleanly (workaround a problem in V's cgen, that -cstrict discovered) - Fix codegen for global array passed as mut (fix #23873) (#23881) - Fix msvc build filename, remove temp files (#23890) - Improve the stability of generated code for auto string methods - Fix codegen for array of anon struct (fix #23896) (#23907) - Make sure to call the overridden `pub fn (mut a []string) free() {` method, NOT the generic `fn (a &array) free() {` one. (#23911) - Fix generic container init (fix #23910) (#23912) - Fix codegen for generic structinit and generic array return (fix #23916) (#23943) - Implement alias operator overloading for generic struct parent type (fix #23965) (#23967) - Add `T.key_type`, `typeof(expr).key_type`, `T.value_type`, `typeof(expr).value_type`, `T.element_type`, `typeof(expr).element_type` for getting `Map[K]V` and `[]T` types (fix #23914) ( #23962) - Builtin,markused,pref,cgen: improve markused for small programs #### vfmt - Fix formatting for an option array of anon structs (fix #23841) (#23844) - Fix comment handling on ending of struct decl (fix #23947) (#23948) #### Tools - ci, vc: use the full V repo commit hash, when generating vlang/vc commit messages - Support `v should-compile-all folder/`, where `folder/` contains project subfolders (containing v.mod files and multiple top level .v files) - Improve `v should-compile-all .` with support for compiling .wasm.v and .js.v files; skip `module name` files, compile projects that have .glsl files - Improve `v bug` report wording - v.help: improve message formatting (#23363) - Restore `emcc --version` diagnostic in `v doctor`, when emcc is present - ci: fix `v -W build-tools` (#23368) - ci: force all tools to build without warnings/notices in tools_ci.yml (#23371) - Fix `v buf file.v`, when run in a folder != vroot - Improve output of `v bug file.v`, fix `v bug /long/abs/path/file.v` too - ci: make show_manual_release_cmd.vsh use a fixed weekly.YYY.WW format for the weekly release tags - ci: make easier the debugging of the `docker-alpine-musl-gcc` job (#23399) - vvet: fix for `v vet folder/` + new features (track long fns, empty fns and repeated code), enabled by the new -F and -r flags (#23405) - v.help: add a message for `v help crun` (#23431) - Make cmd/tools/vretry_test.v independent from the presence of git (fix issue #23398) - ci: add compile_herolib.sh, use it to make sure it keeps working (related #23467) (#23469) - ci: fix toml-module-pass-external-test-suites after the CI image runner upgraded jq to version 1.7, by downloading and using the release version of jq-1.6 - ci: fix failure of the check-markdown job - vet: add an `-I` option to notice fns, with the potential to be inlined (#23534) - ci: update last known good commit hash for herolib to ca8799af39228a5678a7be81128c5b0c342c9efc - Make `v check-md .` print the actual length of lines too, when reporting errors/warnings about them (#23606) - Restore previous behavior of `v download` (show progress on stdout, when it is connected to an interactive terminal; hide log stdout->stderr notice) - ci: fix `CI=name ./v -d network test cmd/tools/vpm/` ; update the image runners in vpm_ci.yml ( #23628) - Add `v reduce program.v`, in order to make smaller reproductions (`rpdc.v` files), before filing cgen bugs (#23636) - Add a small utility script `cmd/tools/vrun`, to make it easier to use .vsh scripts on systems, with `/usr/bin/env` still not supporting `-S` - Describe a more direct way to use a `v run` shebang in cmd/tools/vrun - Fix show_manual_release_cmd.vsh, use .strftime(%V) for calculating the proper default week number - Improve the `v reduce` parser for functions, and add more loops to reduce more (#23694) - Improve `v reduce` output; bump version, warn on failed string_reproduces/3, but continue to run ( #23697) - Fix warnings in `v reduce` (#23709) - Move `cmd/tools/vdoc/doc` to `cmd/tools/vdoc/document`, so that it can be imported from other programs through `-path`, without conflicting with the top level `doc/` folder in the main repo ( #23733) - ci: avoid duplicating work by removing the remaining `-skip-unused` tasks, since that is the new default (#23746) - ci: use distinct names for the jobs, for easier filtering/searching in the Github's UI - ci: fix job names in cmd/tools/modules/testing/common.v as well - ci: fix github job names in cmd/tools/vtest-self.v - ci: update the remaining runners from ubuntu-20.04 to ubuntu-22.04 and ubuntu-24.04 (#23754) - ci: rebuild V with `v -g self` in .github/workflows/native_backend_ci.yml, to improve remote diagnosis of panics in PRs - ci: use `-silent` for the longer test runs (suppress most OK lines, to reduce scrolling on failure) - .gitignore: ignore the project settings file for gf2 (a very nice GUI gdb frontend) - vrepl: fix slow response for empty line input (after just pressing 'enter/return') (fix #23856) ( #23858) - Make `v repeat failing_cmd` show the error output *just once*, but also still measure the time it took to execute - Add --check flag to `v ast` (#23938) - Add `v timeout` to be able to later use `v timeout 5.1 git -C . fetch V_REPO` in `v doctor` and other tools. - Add a custom timeout of 5s for the network using command `git -C . fetch V_REPO` in `v doctor` (it normally takes <1s) (fix #23955) - Support `v doctor -skip-github` to fully skip the fetching step, in places that have limited connectivity (alternative fix/workaround for #23955) - ci: use -silent in more jobs that produce a lot of OK lines normally (for test-cleancode, test-self, build-examples, build-tools) #### Operating System support - Avoid os.glob, in favour of os.walk_ext (which works consistently even on windows) - gg: add linux support for `fn screen_size() Size` (fix #23146) (#23326) - Define _GNU_SOURCE on Linux (#23364) - Fix `v doctor` format, fixes for windows, tcc and others (#23361) - picoev: fix for windows apps with veb in a thread, parallel to a webview, that opens a lot of file descriptors (#23492) - v.pref: set `DYLD_FALLBACK_LIBRARY_PATH` on macos, when `-use-coroutines` is used, so that `v run` can work, and the executable can find the downloaded photonwrapper shared library (#23516) - encoding.iconv: add flag for OpenBSD to find iconv include and library (fix #23573) (#23575) - runtime: add free_memory/0 implementation for OpenBSD (fix #23579) (#23583) - Fix `v doctor` output on OpenBSD: get gcc version from egcc; do not run ldd to get the glibc version (fix #23576) (#23578) - make.bat: add note about antivirus programs on windows and compilation slowdowns (#23586) - runtime: add free_memory/0 implementation for FreeBSD too (fix #23581) (#23594) - log,sync: fix macos CI failure when log.ThreadSafeLog is used explicitly in `v download` (#23613) - Let `v test .` show the running _test.v files each minute (set by `VTEST_REPORT_RUNNING_PERIOD_MS`); diagnose stuck windows gcc CI jobs (#23649) - ci: run FreeBSD on a VM in github ci, instead of on the Cirrus service (which stopped working today) (#23692) - cgen,builder: fix windows 32bit dll function name mangle (fix #23689) (#23690) - ci: update linux image runners from `ubuntu-20.04` to `ubuntu-24.04` (#23706) - ci: do not use `VJOBS: 1` in the windows tcc job anymore - make: use .exe only on Windows - ci: reduce the timeouts in windows_ci.yml to 60 minutes (V is now faster, and the runners use faster hardware as well) - native: allow for searching for wine system32/ .dlls, and for adding more paths for .dll lookups, by setting `VNATIVE_PE_DLL_PATH`, to make it easier to diagnose problems with PE generation on non windows platforms (#23756) - ci: skip fibonacci_native.vv on windows for now - sync: support x86_64-alt-linux gcc paths too when tcc is used (needed for ALT Linux) - ci: make freebsd_ci.yml runnable on personal forked repos, that are not named `v` (#23779) - ci: remove the VJOBS=1 restriction for test-cleancode on linux (#23801) - os: fix buffer overflow in os.get_raw_line under Windows (#23816) - ci: move test in pe_test.v to native_test.v (both used `-b native`, competing the creation of the backend executable => CI failures on the gcc-windows job) - Make `v install` avoid using `--filter=blob:none --shallow-submodules --also-filter-submodules` on windows (#23840) - os: fix get_raw_line() on windows (fix #23843) (#23846) - ci: add a limit of 20 minutes to the test-on-freebsd-14-2-x86 CI job - Support `// vtest build: !do_not_test ?`, `// vtest build: !windows && tinyc` to skip files during testing on specific platforms, without having to keep centralised skip lists (#23900) - cgen,dl: remove workaround in `dl`, generate a DllMain() in cgen instead for `-shared` on windows (#23961) #### Examples - Allow for passing arbitrary compiler flags to `v bug`, for example: `v bug -cg -autofree file.v` ( #23335) - examples,builtin,cgen,live: fix windows hot reload with `-cc tcc`, improve the infrastructure, use a V global instead of a C one (fix #23214) (#23350) - Fix unused db.pg import warning for examples/database/psql/customer.v - gg,sokol,examples: add example of overriding _SGL_DEFAULT_MAX_VERTICES in code - Mention also the RAM usage increase in many_thousands_of_circles_overriding_max_vertices.v - gg: enable clean compilation without notices for `./v -check-unused-fn-args examples/tetris/` - Add vascii.v showing a table of the first 128 ASCII characters with their names and codes in dec, oct, hex, bin formats (#23466) - Add a solution to the "1 Billion Row Challenge" (#23458) - examples,io: add sha256sum_with_io_cp.v, make the size of the buffer used by io.cp parametrisable (#23585) - log: add `log.use_stdout()`, use it to silence the transition note for the most commonly used V tools/examples (#23642) - Implement an -s option for `v ast`, to skip all nodes with default values like [], {}, 0, false; with it `v ast -pts examples/hello_world.v | wc -l` is 36 lines - gg: fix `./v -gc none -autofree run examples/tetris/` (avoid `return s1 + s2 + s3`, clone the arrays, passed to the fontstash wrapper) - examples,gg: modify all remaining calls to fons.add_font_mem/3 to use an array.clone() - Add examples/hot_reload/tunnel.v - Add minimal_c_like_program_using_puts.v showing how to produce a much smaller executable on Linux, using clang, mold and sstrip. - Build examples, that start with `module no_main` as well - ci: fix `v build-examples` failure on gcc-windows - Support `module no_main` based examples in `v should-compile-all` - term: make the second example in the README.md compilable as well - Show how to use a v file server for the wasm version of 2048, instead of emrun - sokol: allow for `v -os wasm32_emscripten -o examples/tetris/tetris.html examples/tetris/` (avoid using `-sMODULARIZE`) (#23814) - Fix poll_coindesk_bitcoin_vs_usd_rate.v, use the new v2 API endpoint - math,examples: add examples/sokol/sounds/simple_sin_tone_using_audio_push.v, cleanup math - Add a small breakout game, supporting keyboard and touch controls (#23861) - Cleanup snek.v, by using `math.vec`, the builtin array support, instead of `datatypes`, and by removing casts that are no longer needed - Fix `v -cstrict -cc gcc-11 examples/sokol/particles` and the same but with clang-18 too - Fix more compilation errors with `-cstrict -cc clang-18` for the sokol examples - Fix `VFLAGS='-no-skip-unused -cstrict -cc clang-18' v should-compile-all examples/sokol/` too - Add a small minesweeper game in examples/gg/minesweeper.v - Add a small Sokoban puzzle game with levels (see https://en.wikipedia.org/wiki/Sokoban) - Use textures in the sokoban game, instead of colors - Shorten the periodic output of examples/hot_reload/message.v - Fix (ball->side edge of brick) collision detection in breakout.v - Add subtle light and shadow effects to the breakout game, to give it a little depth (#23885) - Run the update method of breakout on its own frame independent rate - gg,examples: use a timer to limit the rate of updates in breakout, instead of a separate thread, restore ability to run in a browser through emscripten - Make the tetris update rate, independent from the frame rate too - Make the 2048 game update rate, independent from the frame rate as well - Fix panic, discovered by fuzzing examples/2048/2048.v with zzuf on the CI - Add `vanilla_http_server` - a fast, multi-threaded, non-blocking, port and host reuse, thread-safe, epoll server (#23094) - v.build_constraint: support comments too, for example `linux&&gcc // some comment` - Make `v repeat -R 5 -r 10 "v run examples/hello_world.v"` also show the time it took for all runs in each repeat - Add an asteroids game (it is currently < 400 lines of V, using gg) - Remove the generic alias type overloaded operator workaround, after 29e60da - Fix `v should-compile-all examples/` ## V 0.4.9 *22 Dec 2024* #### Improvements in the language - `-skip-unused` is now on by default resulting in much smaller cgen and binaries. 70% reduction for hello world. - `-parallel-cc` for speeding up `-prod` and `-cc clang/gcc` compilation by up to 14 times! - C functions no longer need to be manually defined. An `#include "foo.c"` is enough (behind `-experimental` for now). - Fixed arrays now have `.index .any .all .map .sort .sorted` methods - Remove inline sum types completely - Support `in` expr with number ranges: `if var in 1..4 {` (fix #20352) (#22754) - Optimize literal string comparison (`match`, `in` and `==`) (#22643) - Allow `map[k]()?` and `map[k]()()` (#22740) - Add selector option unwrapping inside `if tree.root != none {` (#22895) - Add `array.count` as a method that accepts a predicate, similar to filter, but returning just the number of matches (#23054) - Allow option array element comparison `==` and `!=` (fix #23108) (#23113) #### Breaking changes - time: rewrite parse_rfc3339/1 to improve performance, reject partial timestamps, that miss date info like `22:47:08Z` (#22585) #### Checker improvements/fixes - Optimize identical type checking (#22596) - Fix `T.unaliased_typ` if branch evaluation (fix #22587) (#22598) - Fix lambda expr with fntype params and restore fixed_array_any_all_test.v (#22625) - Check fixed array builtin method args mismatch (#22626) - Fix generic fn call return type resolve on var assignment (fix #22612) (#22627) - Improve checking parameter mismatches for fixed array builtin methods (#22630) - Add tests for checking the new errors for fixed arrays .sort() calls (#22656) - Fix index expr that left is if expr (fix #22654) (#22661) - Fix return type checks, when returning struct values, implementing IError in non-result fn (fix #22659) (fix #22658) (#22660) - `App.method` field initialisation, for fn fields, initialised with generic methods (#22665) - Allow for `f() or { T{} }` in a generic method, for `fn f() ?T {`, being called with `T`, being a container like []int etc, not just a primitive type like int (#22672) - Allow for `f() or { T{} }` part 2, see also cc55aa5 (handle the case of an ignored result as well) (#22687) - Fix selector with prefixed `&` structinit (#22689) - Fix missing check for fn var with generic return inherited to anon fn (fix #19045) (#22683) - Check for receiver name clashing with global var (fix #22698) (#22708) - Fix none check for match expr with option (fix #22728) (#22732) - Fix option map fn type and missing check for result param type (fix #22736) (#22738) - Fix missing info about generic fn var usage without concrete types (fix #22733, #22734) (#22743) - Fix missing check for stack pointer return (fix #22726) (#22756) - Improve static method call resolution (fix #22773) (#22787) - Skip redundant message for int overflows, while casting integer literals (fix #22761) (#22788) - Fix callexpr after auto C func identification (fix #22800) (#22809) - Fix missing auto `from_string` type restriction (related to #22783) (#22803) - Fix match expr with empty array init expression (#22832) - Disallow `foo[T]` as a value (#22820) - Fix if expr with empty array init expression (related #22832) (#22841) - Improve the position underlining, for last statements in branches of `if` expressions (#22845) - Fix generic fn call with empty array argument (fix #22843) (#22846) - Fix missing or-block check for callexpr (fix #22835) (#22840) - Check array builtin method calls, that do need a mutable receiver, but are called on an immutable one (fix #22850) (#22853) - Check alias of array op overloading and fix op overloading (fix #22851) (#22854) - Disallow struct init with `mutable_field: const_array` (fix #22862) (#22863) - Check struct aliased field unsign type assigning negative value (fix #22868) (#22871) - Fix alias to struct generic type (fix #22866) (#22872) - Fix `json.encode_pretty` with a struct init expression argument (#22897) - Fix codegen for fixed array initialization with a fn call (fix #22887) (#22891) - Fix or-expr check on invalid method call (fix #22949) (#22950) - Fix mut var option unwrap with `!= none`, support `if mut x != none {` too (fix #22936) (#22943) - Prevent a compiler panic, while running `v -check file.v` on files with parser errors (fix #22981) (#22982) - Allow array sort with callexpr (#22989) - Fix `$res()` used in `defer {}` blocks with more statements, add a test (#22998) - Fix generec fn returning generic closure (#23047) - Fix generic fn returning generic closure (related #23047) (#23055) - Fix missing checker for cast from mut var to non-ptr type (fix #23017) (#23056) - Check fn call argument mismatch (fix #23016) (#23061) - Fix empty array append multi dims (fix #23092) (#23096) - Fix selector generic or block (fix #23088) (#23102) - Fix veb route method param with non ctx name (fix #23105) (#23107) - Allow fixed array where voidptr is expected (fix #23090) (#23100) - Fix immutable to mutable reference (fix #22653) (#22663) - Fix missing check on range expr when high var is same iteration value var (#23130) - Allow `[]Enum{len: 10, init: .thing}` (fix #23077) (#23165) - Fix option unwrapping and call from option struct field (#23182) - Add a notice for global variable redeclarations (#23162) - Fix assign check, when rechecking for another concrete type (#23212) #### Parser improvements - Fix generic struct init detection `T{}` (#22682) - Improve the assert informations (related #22668) (#22679) - Make C struct fields public and mutable by default (fix #22695) (#22706) - Fix enum redeclaration error (fix #22759) (#22766) - Fix struct field name using keyword (fix #22826) (#22829) - Optimise mark_var_as_used calls, by moving it to an ast.Scope method (#22842) - Optimize method parameter detection in used check (#22915) - Fix block position's last line (#22913) - Support `@[must_use]` tag for fns/methods, and an experimental `-check-result` option (#22983) - Allow `type` as field type on params struct construction (fix #23091) (#23098) - Allow `type` and other keywords as plain attr value (fix #23150) (#23154) - Support `@[tag]` for hash statements, like `#define` and `#flag` (#23210) #### Compiler internals - Add `:parse_text` to the paths of .v files, printed by `-print-v-files`, for parse time generated snippets - v.pref: support a `_wasm32_emscripten.c.v` suffix for platform files too - builder: fix msvc build thirdparty obj file from .cpp (fix #22772) (#22789) - v.util: use temporary workaround for the vinix build problem (when VFLAGS is set, and `-ldflags ` is passed at the same time) - Allow getting notified about unused function params (#22879) - v.scanner: remove `Scanner.is_started` field (#22918) - v.scanner: fix string interpolation for float e format (fix #22429) (#23147) - cbuilder: remove flto with parallel-cc, it slowed down linking 10x - cbuilder: store split up C files in vtmp - v.builder: integrate more compile/linker options into parallel_cc.v (#23190) - v.builder: prevent passing `-x objective-c` with `-parallel-cc` for now - v.builder: move filtering logic for `-parallel-cc` to parallel_cc.v - v.pref: support `-debug` and `-cdebug`, as more explicit alternative names for `-g` and `-cg` ( #23208) - v.builder: fail the whole v compilation, if linking or compiling during `-parallel-cc` fails ( #23211) - v.pref: implement `-no-prod-options` to turn off passing `-O3 -flto`, while still keeping the `$if prod {` branches (passing custom flags with `-cflags -Os` already works) - v.builder: support `-no-prod-options` with `-cc msvc` as well #### Standard library - builtin: improve performance of `string.starts_with/1` and `string.ends_with/1`, when compiled with tcc (#22620) - builtin: improve `fixed_array_any_all_test.v` (related #22609) (#22621) - builtin: temporary fix fixed_array_any_all_test.v (#22624) - builtin: support `-d no_gc_threads` for turning off passing `-DGC_THREADS=1` while compiling the GC library - encoding.utf8: fix is_punct func (fix #22646) (#22647) - log,time: improve performance for writing a line to a log, add Time.format_rfc3339_micro/0 ( #22662) - flag: add missing short flag match in `flag.to_struct`, add test (#22696) - bitfield: add `shift_left/1` and `shift_right/1` methods to `BitField` (#22700) - x.json2: pre-arranging the replacement of the decoder, to match https://github.com/enghitalo/v/tree/decoder2_to_json2 (#22729) - builtin: improve fixed_array_any_all_test.v (#22746) - builtin: add `string.is_pure_ascii()` (#22748) - os: document the various enum values in os.Signal (#22770) - builtin: fix runes.to_upper() (fix #22742) (#22755) - ci: use os.system to redirect output - vlib: initial addition of `x.encoding.asn1` (#22783) - os: work towards being able to again use `-autofree` while recompiling the V compiler several times - x.encoding.asn1: fix time creation to also accommodate negative timezone offsets (#22861) - vlib: remove modules/functions/fields, deprecated in 2023 (#22750) - term: improve performance of repeated can_show_color_on_stdout and can_show_color_on_stderr calls, by caching their results (#22893) - builtin: make int_min/2 and int_max/2 public - json: mark json_print_pretty/1 with `@[markused]` (used by cgen) - math.big: use `@[manualfree]` to workaround -autofree compilation issues with gitly, and other projects using `crypto.rand` and `math.big` - x.encoding.asn1: improve performance (#22948) - gg: use a larger fontstash text atlas by default (2048x2048, and customizable), instead of 512x512 (fix #21610) (#22959) - Revert "os: deprecate `os.getwd` in favor of `os.get_current_dir` (part 1) (#22966)" - log: tag log.fatal with @[noreturn] (#22986) - runtime: force runtime.nr_jobs() to return 1, while V is bootstrapping itself, from vc/ source, that was compiled with `-os cross` (fix #22991) - json: fix decode codegen for []&type (fix #23007) (#23010) - os: add os.get_trimmed_lines() too - crypto.sha3: add support for Keccak-256 and Keccak-512 (#23058) - rand: add missing i32 APIs, corresponding to the int ones - math.big: fix `assert big.integer_from_int(1) == big.integer_from_bytes([u8(0), 0, 0, 0, 1])` (fix #23115) (#23124) - math: use libc wrappers for math.log2/1, math.log10/1, math.log1p/1 and math.log_b/1; make `assert math.log10(10) == 1.0` pass in the common case (#23129) - gg: add `icon` field to gg.Config, for easier access (fix #23135) (#23138) - math: fix math.log10() for `-exclude @vlib/math/*.c.v` (fix #23136) (#23140) - json: add primitive type validation (fix #23021) (#23142) - json: fix memory leak on result messages (checked with `json_option_raw_test.v`, compiled with `-fsanitize=address,pointer-compare,pointer-subtract`) (#23172) - vlib: add new `rand.cuid2` module (#23181) - json: fix memleak on sumtype decoding (#23197) - vlib: enable more satnitized memleak detection runs without false positives on the CI (#23200) - json: fix argument freeing for json.encode and json.encode_pretty calls (#22781) #### Web - veb: translations via %translation_key - picoev,net.http: use Time.http_header_string method, to improve performance (#22619) - Do `import veb`, only for templates that do use functions defined in `veb` - picoev: support `-d picoev_verbose_errors`, do not use any naked `eprintln` by default, since that is a low level module - picoev: fix the incompatible pointer type cast error in the C.epoll_wait call (#22785) - net.mbedtls: define MBEDTLS_THREADING_PTHREAD, in mbedtls_config.h; call C.mbedtls_ssl_conf_read_timeout explicitly in the wrapper, with a shorter timeout value of 317ms ( determined experimentally) - veb: fix large file transfer timeout (fix #22489) (#22924) - net.http: send Host headers with port (when the port is != 80 or 443) (fix #22941) (#22942) - net.mbedtls: support compiling with `-d mbedtls_client_read_timeout_ms=7000`, `-d mbedtls_server_read_timeout_ms=60000`, and `-d trace_mbedtls_timeouts` - net.urllib: fix parse of url relative address (fix #21061) (#23180) - veb: fix key value and translation file name (#23203) #### ORM - Fix orm.Connection only allowing immutable Connections (#22684) - Fix order by with custom column name (#22813) - Support plain `@[serial]` attribute for marking struct fields (#22814) - Fix crash when working with array field (fix #22822) (#22824) - Fix list generation and escape loose backtick (#23039) - Fix mark as used var on insert statement (fix #23032) (#23038) - Fix update stmt with enum value (fix #23031) (#23037) #### C backend - Fix codegen for fixed array contains - `[1,2]! in a` (fix #22559) (#22579) - Improve fixed array literal in operation and index calls (#22590) - Add codegen for auto free methods for interface type (#22555) - Add test for #22586 (#22600) - Parser,ast,cgen: do is_builtin sym marking during parse time just *once*, to save multiple checks later (#22580) - Cache the results of g.base_type/1 (#22613) - Add caching to contains_ptr return (#22605) - Add .write2/2 and .writeln2/2 methods to reduce consecutive write calls (#22610) - Optimise the generated code for returning literal values and option/result values (#22622) - Optimize literal string comparison (string__eq -> vmemcmp) (#22614) - Fix selector indexexpr with fntype on assignment (fix #22635) (#22637) - Fix anon fn with `&` prefix (fix #22628) (#22638) - Fix struct field init with fixed array using index (fix #22616) (#22641) - Fix interface conversion codegen race issue (fix #22640, #17943) (#22655) - Fix waiter funcs declarations (fix #22640) (#22649) - Improve the assert informations (fix #22666) (#22668) - Fix dump of alias to option fn type (fix #22670) (#22676) - Fix array append map value with or expr (fix #22674) (#22678) - Ensure proper saving/restoring of cgen `map[k] := fn ()` state, when assigning anonymous fns (fix #22705) (#22707) - Implement methods sort_with_compare()/sorted_with_compare() for fixed arrays (#22702) - Implement methods reverse()/reverse_in_place() for fixed arrays (#22712) - Fix ptr field encoding for `json` (fix #22717) (#22720) - Fix `[1, 2, 3]!.map(it * 2)` (#22722) - Fix `assert [1, 2, 3]!.contains(2)` (#22725) - Fix `assert [1, 2, 3]!.index(2) == 1` (#22727) - Fix spawn with non-pointer receiver (fix #22718) (#22719) - Fix `assert [1, 2, 3]!.reverse() == [3, 2, 1]!` (#22745) - Fix codegen for `-no-builtin` flag (when used separately from `-d no_main`) (#22765) - Apply the `a in [x,y,z]` optimisation for `ast.IndexExpr` and `ast.SelectorExpr` again (#22767) - Fix codegen to emit callexpr one time for `in` expr optimization (#22764) - Fix c codegen formatting for return match (#22768) - Avoid generation of empty `or` blocks for `f() or {}` (#22775) - Fix struct field name using c keyword `typeof` (fix #22779) (#22782) - Remove unused code generated for unwrapping temp var from callexpr (detect unused return value from CallExpr), fix parser bugs (#22769) - Enable if guard to add `err` var on else branch, after last `else if` (fix #22784) (#22786) - Fix option struct default value init with `-cstrict` (spotted in #22783) (#22802) - Fix codegen for fn fixed array param w/ size defined by const (fix #22811) (#22812) - Fix wrong type resolution on infix (#22804) - Fix default `T{}` when `T` is ref type + dereferencing issue when comparing int alias to int (fix #22795) (#22807) - Fix generation of a missing return in `return if cond { x } else { return missing }` (fix #22838) (#22839) - Fix generic static method call return type resolution (#22865) - Fix array fixed code generation for more than 1 dimension (fix #22866) (#22876) - Fix codegen for `$if` in an if expression, when compiled with `-g` (fix #22873) (#22888) - Make errors more informative (resolve empty panics) (related: #21184) (#22898) - Generate json array line on uniform indent lvl (#22899) - Fix codegen for returning a fixed array as a result (fix #22894) (#22896) - Fix codegen for alias type interface methods (fix #22901) (#22902) - Fix codegen for assigning aliased fixed array (fix #22907) (#22909) - Fix codegen for returning option aliased fixed array (fix #22910, fix #22911) (#22912) - Fix aliases of fixed array infix expression (fix #22925) (#22928) - Fix aliases of fixed array append to array (fix #22926) (#22929) - Fix option unwrap for fields of interface type (fixes #22930) (#22931) - Fix aliased fixed array option fn call (fix #22927) (#22934) - Move the `msvc compiler does not support inline assembly` to cgen (so it will only get triggered, when ASM blocks are still present, in what is passed to cgen) - Fix dump fixed array on array append (fix #22935) (#22940) - Fix enum value string interpolation, like its declared enum underlying type (fix #22938) (#22945) - Allow unwrapping of `x as string` expr, when `x` is a `?string` value (#22953) - Fix codegen for result/option propagation out of fn context (fix #22961) (#22963) - Fix codegen for option on concatexpr (fix #22951) (#22964) - Reduce code for returning and extra whitespaces on `return` (#22967) - Allow unwrapping of `foo.bar as string`, where `foo.bar` is `?string` (fix #22960) (#22973) - Add thread timing stats too, on `-show-timings -stats` (#22990) - Patch missing `gettid()` on glibc < 2.30 (#22987) - Fix array fixed on update expr and alias type to multi dimension of fixed array (fix #22971) ( #22972) - Fix sumtype with embedded struct of option field (fix #22984) (#22996) - Fix autostr for interface with circular type (fix #23022) (#23026) - Fix array.delete_many() codegen (fix #23024) (#23025) - Fix callexpr or-expr codegen on const decl (fix #23029) (#23043) - Fix struct update embed expr for fixed arrays (fix #22999) (#23040) - Fix update expr with embed fixed array with multiple dimensions (fix #23048) (#23049) - Fix cast interface value in match expr (#23068) - Prevent too long lines in array initialisations (#23074) - Fix smartcast codegen for msvc (#23084) - Fix option codegen for accept IError value (fix #23076) (#23085) - Fixed for in loop with generic fixed array (fix #23075) (#23101) - Fix printing fn call of returning c struct value (fix #23104) (#23106) - Fix array fixed comparison from fn return (fix #23071) (#23114) - Fix array map to fixed array (fix #23116) (#23118) - Fix codegen for returning different option alias type (fix #23087) (#23125) - Fix for in for interface type (fix #23119) (#23127) - Fix codegen for generic selector expr (fix #22974) (#23132) - Fix different option alias type as fn arg (fix #23086) (#23131) - Fix codegen for returning option reference from indexexpr (fix #23133) (#23139) - Fix array fixed auto str on `-cstrict` (#23144) - Fix codegen for array append on indexexpr (fix #23156) (#23160) - Fix assert for alias to fixed array (fix #23149) (#23161)" - Fix auto eq for fixed array (fix #23149) (#23169) - Fix fixed array option cast with `none` (fix #23164) (#23168) - Fix selector call with reserved c name (fix #23170) (#23175) - Parser,checker,cgen,fmt: fix array fixed option initialization (`none`) (complete #23164) (#23176) - Fix option fn with voidptr arg (fix #23170 for !=tcc too) (#23179) - Fix missing validation for selector unwrapping + fix default `return none` for unwrapping (#23183) - Fix assign optional aliases of fixed array (fix #23185) (#23188) - Fix struct field init with optional fixed array (fix #23193, fix #23195) (#23199) - Reduce RAM usage, by avoiding a .str() call, for the final string builder, containing the final C program, used to write it to a file (#23226) #### vfmt - Add support for comments inside `sql db { ... }` blocks (fix #22601) (#22602) - Fix formatting fixed array size of struct member (#22815) - Fix formating non-unsafe blocks with break line (fix #22900) (#22903) - Fix shared receiver formatting (fix #23151) (#23153) #### Tools - ci: add benchmark_footprint_json_decode.yml and benchmark_footprint_json_encode.yml (#22592) - Use a `~same~` label, when the results in `v repeat` are not different enough - Allow for fast exiting in compare_pr_to_master.v through Ctrl-C (or any failed command) - ci: fix failing jobs after 4ed9d13 (#22606) - Discard the top 7 results for each 10 runs, from `v repeat` runs, done by compare_pr_to_master.v, to reduce σ on machines with more varied load - Allow for `v repeat -N ./cmd/tools/vtest_test`, by adding a -N/--no_vexe_reset option to `v repeat` - Show more details in compare_pr_to_master.v - ci: fix failing musl jobs after 2684ef9 (#22667) - ci: run `zizmor .github/workflows/paths_ci.yml` and fix reported issues (#22681) - Show the full test output, on known flaky test failure with `v test folder/` (#22716) - Change `v test` to allow for `// vtest hide_retries` so that retry_test.v can hide its own ( deliberate) retries - ci: rename one of the duplicate `main_test.v` files, to reduce false positives (workaround) - Fix `v doctor` output for missing `cc`. Add a diagnostic line checking for `emcc --version` too - ci: run `v fmt -w vlib/v/pref/should_compile.v` - ci: reduce flakyness of cmd/tools/vcover/cover_test.v (workaround for a race condition while updating the OK tasks counter in `v test`) - Improve the diagnostic output of compare_pr_to_master.v - ci: add a problem matcher support, to get error/warning/notice annotations in V CI jobs (#22790) - Bump default `v retry` timeout to 10 minutes, clarify the usage of its `--timeout` option. - ci: fix Build V - ci: silence compilation warning for bench_string_key_in_map_vs_string_value_in_array.v - ci: fix vinix_ci.yml for latest Vinix commits (#22818) - Improve output of compare_pr_to_master.v - Use `v retry` in more places, that do network operations that can fail temporarily (#22836) - Allow for `v download -RD URL/script.vsh`, to download `script.vsh`, then run it locally, then remove it, in a single command - v.help: add topic for `v help retry` - v.help: add help topic for `v help repeat` - ci,v.help: work around -autofree bugs, fix `./v -autofree -o v2 cmd/v` - ci: add .yml file for testing compilation of Larpon's Shy library and the Puzzle Vibes game ( #22874) - ci: check more compile flag combinations in puzzle_vibes_ci.yml - Fix compilation of hw with vnew -> vold, in compare_pr_to_master.v - ci: fix for `v build-tools` - ci: check that more apps/modules do compile with -skip-unused (#22904) - vet: make `v vet` produce a nicer note, including the offending files, instead of `file.v` ( #22957) - ci: extract the VTL&VSL jobs from v_apps_and_modules_compile_ci.yml to vsl_and_vtl_compile_ci.yml - Make oldv aware of when to pass -no-parallel when bootstrapping V from v.c (fix #22990, part 2) - markused: only add .vtest_ functions, *when* compiling _test.v files (#23003) - Improve oldv compatibility for using new stricter C compilers like clang-18, to compile older V versions from 2020 and 2019 - Use -Wno-error=incompatible-pointer-types in oldv, which is more permissive than just -Wno-error=incompatible-function-pointer-types, and works with gcc too, not just clang - Describe more precisely what commands are used by `oldv`, so it can fail early, with a meaningful error message, if they are not present. - ci: fix ROADMAP.md checks (#23059) - vrepl: shrink .repl inputs, so repl_test.v runs faster - ci: update compile_v_with_vtcc.sh, enable its CI task again (#23063) - ci: extract .github/workflows/compile_discordv.sh, enable its CI step again - json2.decoder2: prepare decoder in json2 to be replaced by json2.decode2 (#23078) - Let oldv fail early, when git fails to do network operations or checkouts - ci: fix for `-cc tcc -no-retry-compilation`, do not use more complex constants, but functions in vlib/math/vec/vec2_test.v - ci: fix option_fn_voidptr_test.v after a200c45 - ci: make the CI more robust, by retrying commands and `v download` instead of wget (#23196) - ci: use `v retry -- v setup-freetype` to make the CI more robust against random network failures - ci: change exec name for parallel cc - ci: speed up again sanitizer runs (#23222) #### Operating System support - builder: change linuxroot repo URL to https://github.com/vlang/linuxroot - ci: test -os linux cross compilation on macOS - ci: test the cross compilation from macos to linux sooner, show more information - ci: move the macos->linux check even higher, to make easier testing and diagnosing linuxroot update failures - orm: cross compile pg to linux; openssl: make cross compile work - ci: use `macos-14` instead of `macos-12` because of https://github.com/actions/runner-images/issues/10721 - ci: macos_ci.vsh - ci: fmt macos_ci.vsh - ci: use thew new macos_ci.vsh (github) - ci: improve output of macos_ci.vsh - ci: extract `ci/common/runner.v`, use it to simplify ci/macos_ci.vsh even more - ci: fix spurious failures for printing_struct_with_thread_field.vv on windows - net.http: ensure that http.download_file_with_progress/3 works (in a degraded mode), on windows, even without passing `-d no_vschannel` - builder: fix cross compiling from linux to windows, when passing -g/-cg - docs: update the documentation of the @[console] tag, add advice to use `-subsystem windows` instead - Make compare_pr_to_master.v use /opt/homebrew/bin/gtime on macos, and a pure V fallback, not just for windows - ci,thirdparty: enable MBEDTLS_THREADING_PTHREAD and MBEDTLS_THREADING_C only on Linux for now (fix windows CI) - thirdparty: enable MBEDTLS_THREADING_C and MBEDTLS_THREADING_PTHREAD on FreeBSD too - os: use _wputenv instead of _putenv to stay in sync with _wgetenv (fix changing env variables with non ASCII content on windows) (#22920) - ci: avoid false positives for the existing PRs, by comment out the task `V self compilation with -usecache` on macos for now (#23145) - ci: linux_ci.vsh; cgen: parallel-cc fixes - ci: remove extra EOL from linux_ci.yml (#23187) - Fix profile time on windows (#23227) #### Comptime - Add `typeof(var).indirections` and `T.indirections` (#22805) - Add `typeof(expr).unaliased_typ` (#22806) - Allow sumtype init by variant comptime var `T(v)` / `SumType(v)` (#22664) - Fix missing bool AttributeKind.kind (#23159) - Fix comptime `T.methods` with generic types and interface checking with `is` operator (fix #22721) (#22724) #### Examples - Fix some of the instructions in `examples/thread_safety/` (#22571) - builder,pref: fix `./v -os linux examples/json.v` on macos (#22651) - Add examples/assets/v.svg and examples/assets/v_16x16.svg - v.comptime: fix compilation of `examples/veb/veb_example.v` with V compiled with tcc on macos - ci: ensure that all examples can still be compiled, by `v` compiled with tcc on macos - Add poll_coindesk_bitcoin_vs_usd_rate.v - Simplify and reorder output of poll_coindesk_bitcoin_vs_usd_rate.v - builtin: fix `v -skip-unused -cc tcc examples/hello_world.v` on *BSD - net.mbedtls: bump mbedtls_ssl_conf_read_timeout value to 550ms (tested with `v run examples/net_t.v`) - Add a cpu_features/ folder, with several examples, using SSE and MMX assembly instructions ( #22645) - v.builder: fix `./v -check -stats examples/hello_world.v` - docs: add a small sumtype match example in the Match section too - Add TextScanner .skip_whitespace/0, .peek_u8/0, .peek_n_u8/0, add examples/mini_calculator_recursive_descent.v (#23001) - Reduce completion friction, when doing the very common `v run examples/hello_world.v` in a shell ## V 0.4.8 *28 Sep 2024* #### Improvements in the language - A new `implements` keyword for explicit interface implementation - Allow multi return as fn argument (#21991) - Define a default sumtype value (based on the first variant type) (#22039) - Remove the obsolete .code and .msg fields of IError (#22066) - Fix generic lambda type binding and resolution (#22083) - Comptime support for traversing the method parameters with `$for param in method.params {` ( #22229) - Show missing variants in the sum type error - A much better and detailed unmatched fn arg error - Add support for `@BUILD_DATE`, `@BUILD_TIME` and `@BUILD_TIMESTAMP`, all using v.util.get_build_time(), and overridable through SOURCE_DATE_EPOCH (#22213) #### Breaking changes - Deprecate `x.vweb` and `vweb` in favor of `veb`, a faster, easier, and more stable framework. #### Checker improvements/fixes - Disallow static fn call when receiver type is unknown (#21970) - Fix sumtype checking for voidptr variant (#21955) - Check comptime veb.html('index.html') (#21961) - Check if a parent generic struct has concrete types or not (#21962) - Add support for static methods in `@FN` and `@METHOD` (#21990) - Add a deprecation warning for `const ()` groups (an error after 2025-01-01) (#22019) - Improve `-d trace_checker` and error diagnostic information on compiler panics - Add error when initializing sumtype with struct as first type (#22067) - Add infix checks for nil (#22045) - Fix map generic fn arg passing (#22071) - Disallow using a preexisting const name in a for loop, as either a key or value ident (#22108) - Fix generic lambda type binding resolution (fix #22109) (#22115) - Fix array alias (#22175) - Restrict multiple union fields initialised at once with a nicer checker error, instead of producing an enigmatic error at cgen time (#22196) - Fix compilation of vlib/v/slow_tests/assembly/asm_test.amd64.v (regression after dfc0c91) - Add missing check for ref passing to non-ref (#22194) - Check struct implements non interface type (fix #22200) (#22218) - Suggest using the `@[_allow_multiple_values]` attribute, when declaring enums that have duplicate values (#22224) - Check for duplicate interface names in the `implements` parts of struct declarations (#22230) - Fix missing struct field type checking for type mismatch (ref vs non-ref in `mt sync.Mutex = sync.new_mutex()`) (fix #18088) (#21949) - Fix fntype var marked as auto heap (#22290) - Check array.delete() argument mismatch (#22307) - Add missing check for duplicated items on in expr (fix #22305) (#22308) - Disallow infix expr on left side of assign (#22322) - Fix array fixed return type for interface methods (#22320) - Check arguments mismatch of array.sorted_with_compare() (fix #22327) (#22328) - Add an error for returning an `any` value in pure V code (prevents invalid cgen) (fix #12623) ( #22334) - Cleanup the checking of array method calls (#22338) - Fix voidptr type checking (#21923) #### Parser improvements - Fix lots of parser panics, discovered through fuzzing with radamsa - Improve the error for keyword `lock`, used as a variable name (#21937) - Improve the error message position for invalid array attr keys (#21944) - Fix const field str() (#21998) - Update `@include` in templates, to work with relative paths & prevent recursive calls (#21943) - Check fn call args without comma between them (related #22021) (#22075) - parser,scanner,ast: make the scanner and parser more robust, by implementing more limits ( preventing panics, discovered by fuzzing) - Protect against too deep recursion in Expr.pos() calls - Check too many layers embedded generic type (fix #22089) (#22091) - Cache ident lookups for consts in ast Expr str (#22101) - Improve Type and TypeFlag related operations (#22107) - Fix parsing map value inside or expr (fix #12164) (#22180) - Fix const field str() (#22192) - Fix `.${var}` used in a template, compiled by `$tmpl()` (fix #22231) (#22270) - Check enum method duplicated (fix #20924) (#22294) #### Compiler internals - scanner: guard against scanner panic, discovered by fuzzing in PR#22016 - v.builder: show the thirdparty object compilation commands too, when using `-showcc` (when the cache is empty) - builder: allow for `v -dump-defines - -check cmd/v`, which is faster, because it can skip code generation - Reduce allocations for the most common cases (#22142) - transformer: add support for instrumenting the V compiler with `-d trace_transformer` #### Standard library - encoding.base58: fix notice for slice creation (#21935) - gg: reset ctx.mouse_d? and ctx.scroll_? at the end of each frame (fix #21945) (#21946) - builtin: v_segmentation_fault_handler signal_number i32 - builtin: fix 'aaaa'.split('aa') (fix #21936) (#21951) - builtin: panic on trying to grow arrays with capacity bigger than 2^31, instead of overflowing a.cap (partial fix for #21918) (#21947) - gg: add a note that Context.new_streaming_image has to be called after Sokol's setup - gg: add more documentation comments for gg.Config (the parameters of gg.start and gg.new_context) - regex: fix regex.split() (fix #16876) (#21953) - json: increase test cases before enabling sumtype decode in all json libraries (#21958) - gg: change the type of gg.DrawImageConfig.rotate from `int` to `f32` - gg: deprecate gg.DrawImageConfig.rotate, in favor of gg.DrawImageConfig.rotation, improve the documentation comments (#21963) - x.crypto.chacha20: make Cipher struct public (fix #21967) (#21968) - tmpl: fix an extra newline in @for; builtin: some i64 fixes - gg: add an optional size: parameter to the .draw_pixels and .draw_pixel methods (defaults to 1.0) - sokol: update to match upstream at c0e0563 (#21971) - Add support for `Any` in `decode_struct`, `encode_struct` and `to_any` (#21972) - crypto.cipher: make Stream.xor_key_stream implementers require a mutable receiver (#21974) - sokol.audio: fix `./v -cc clang-18 -gc none simple_bytebeat.v` (the audio depends on threads) - time: `d`,`c`,`dd`,`ddd`,`dddd` pattern support for parse_format() (#22003) - flag: add optional value description to string parameters (#22024) - flag: add custom value descriptions for bool, int, and float flags too (#22032) - flag: fix assigning to `@[tail]` field when no fields has been matched yet in `flag.parse[T]()` ( #22043) - crypto: add a crypto.pbkdf2 module (#22047) - hash: add more methods to the hash.Hash interface, to match the ones in Go (#22001) - arrays: simplify arrays.sum and arrays.reduce (#22076) - x.json2: support @[skip] as well (#22077) - builtin,thirdparty: fix compilation of libgc with `-cc msvc -gc boehm` (thanks to @Ekopalypse) - stbi: change Image.data from voidptr to &u8, to reduce casts (#21977) - time: update parse_format comment description in parse.c.v (#22104) - vlib: add an `arrays.parallel` module, containing `parallel.run/3` and `parallel.amap/3` implementations (#22090) - builtin: support `-d builtin_print_use_fprintf`, make the C fn declarations stricter (#22137) - builtin: fix map.clear() not resetting map's metas and keys blocks (fix #22139) (#22140) - builtin: fix incomplete m.clear(), allowing the map to have a duplicated entry for its first key ( fix #22143) (#22144) - builtin: fix m.clear() having different observable behavior to `m = {}`, after multiple iterations of setting keys and clearing (fix #22145) (#22146) - builtin: fix bug in .clear() caused by sizeof(u32) being 4, not 2 (fix #22148) - flag: add support for parsing `flag.FlagParser` style flags in `to_struct[T]` (#22152) - flag: fix parse_bool_value() (#22160) - flag: correct bool logic, add test (#22162) - flag: fix parsing `flag.FlagParser` style short flags in `to_struct[T]` (#22172) - gg: change the type of PenConfig.thickness to f32 - builtin: remove remaining references to v_calloc in function comments (#22179) - builtin: remove string interpolation from panic/1, to be able to use tools like cbmc in more cases (#22182) - flag: add a relaxed parsing mode, that turn flag match errors into `no_match` entries instead ( #22191) - encoding.binary: add `u16`/`u32`/`u64` -> `[]u8` conversion functions (#22193) - crypto.sha1, crypto.sha256, crypto.sha3, crypto.sha512: improve performance for non prod builds, by tagging the block_generic functions with `@[direct_array_access]` - builtin: fix string.trim() (fix #13021) (#22205) - crypto.bcrypt: reduce runtime cost for running bcrypt_test.v, by reducing the iteration count - crypto.scrypt: add a new `scrypt` module to vlib/crypto (#22216) - sync.stdatomic: add OpenSUSE paths for libatomic - crypto.scrypt: add missing comment of source for test vector (#22222) - json: allow passing an anon struct as a decode type (#22228) - flag: fix parse_bool_value() with different order short args (fix #22176) (#22242) - builtin: drop C in int.v (#22245) - strconv: fix format_fl()/format_es() (fix #13210) (#22244) - json: fix decoding of structs with embeds (#22264) - crypto.rand: add support for convenient generation of a random big integer in the interval `[0, n)` (#22266) - json: fix json encode/decode with embed support (#22277) - io: add a BufferedWriter and supporting methods (#22265) - vlib: add a go like `x.benchmark` module, that estimates automatically how many iterations are needed, to get a statistically significant result (#22215) - math: document q_rsqrt - io: make buffered_writer_test.v more robust - builtin: enable GC lib on rv64 build (#22319) - json: support null sum types in decode() - crypto: ecdsa module (on top of openssl) - bench: crypto/ecdsa.v - math.big: fix `a + b` and `a - b`, when the signs are different, add more test cases (#22330) #### Web - Check for using comptime $veb.html()/$vweb.html(), without importing veb or vweb (#21957) - net: add net.Dialer and net.Connection interfaces, abstracting the different types of connections, already supported by the V network stack (#21657) - net.mbedtls: support Server Name Indication (SNI) (#22012) - veb: extract constants into consts.v (#22132) - vweb: mark vweb as deprecated in its README, recommending using veb instead (#22131) - veb: fix `vweb_livereload` reference to `veb_livereload` (#22171) - veb: fix a few minor errors in the README.md (#22177) - net.mbedtls: store the client ip (for ipv4), shutdown on handshake failure, in .accept() (#22184) - veb: implicit context - veb: make implicit context work with custom user types - net.websocket: use retrying on EINTR in Client.listen() (#22279) - net: allow ipv6 address with brackets (fix #22313) (#22316) #### Database drivers - db.sqlite: add instructions for installing SQLite's amalgamation or development package, if it is missing #### C backend - Fix struct ref field with no ref structinit (#21932) - Define a flexible vint_t type (32 bit int on 32 bit systems, 64 bit otherwise) - Fix generic sumtype with repeated concrete type (#21948) - Fix array.map with closure var fn (#22002) - Fix generation of closures from methods on aliases (#22004) - Reduce indentation level for generated defer statements - Fix selector with interface var (#22006) - Fix free method generation for option struct (#22060) - Fix fixed array with default init (#22059) - Fix for loop with array fixed returned from fn (#22069) - Fix free method for option fields (#22070) - Fix auto free method for option map (fix #22081) (#22094) - Return early from autofree related functions, when -autofree is not used - Fix shared object method call (fix #22121) (#22125) - Fix array fixed initialization from map indexing (fix #22133) (#22149) - Fix generic options with reserved ident (#22164) - Fix struct field with default optional value (fix #11119) (#22167) - Fix array of fns index call with embeded array index (fix #17381) (#22198) - Fix match with mut cond variable (#22207) - Fix code generated for indexexpr with complex assigning (#22203) - Fix interface type generation for generic struct (fix #22186) (#22189) - Fix wrong type of vint_t and const riscv64 (#22251) - Fix code for C ident when ptr is expected (#22259) - Fix C name mangling with inherited closure vars (fix #22262) (#22263) - Fix codegen for alias to charptr passed as ptr (fix #9679) (#22271) - Fix codegen for option fntype used in a match (fix #22278) (#22280) - Fix option cast from fntype (fix #22283, #22284) (#22285) - Fix codegen for method call on rangeexpr (fix #12610) (#22291) - Fix operation overload for type aliases of fixed arrays (fix #22297) (#22304) - Fix codegen for assign from unsafeexpr resulting fixed array (fix #22301) (#22309) - Fix variadic arg var passed to another call which expects variadic (fix #22315) (#22317) - Fix aliases of array insert(...)/prepend(...) (fix #22323) (#22324) - Fix codegen for interface method call which returns a fixed array (fix #22326) (#22331) - Add `asm` to c_reserved, fixes compilation of `struct Abc { @asm int }` (#22340) - Fix interface method call after smartcast (fix #17056) (#22335) - Fix codegen for address of range (fix #18528) (#22336) #### vfmt - Allow align threshold to be parametrized in calls to add_new_info (#21942) - Fix and simplify align of struct fields (#21995) - Fix alignment of enumeration types (#21999) - Fix enum fields with one empty line (#22007) - Fix fmt of enum fields with empty line (#22015) - Fix alignment of struct init fields (#22025) - Keep empty newlines in between interface fields/methods (#22040) - Fix interface fields or methods with empty newlines (#22046) - Fix enum/struct_decl/struct_init fields with empty newlines (#22051) - Fix interface fields/methods alignment (#22055) - Remove the prefixed module name of const names, that are in the same module (related #22183) ( #22185) - Fix import selective with interface implements (fix formatting part of #22200) (#22209) - Add a test for fn with c binding type args (#22212) - Fix formating a file in an oscillating manner (fix #22223, fix #22026) (#22232) #### Tools - Implement a `-repeats/-R N` option to `v repeat`, to eliminate another need for platform dependent scripting - ci: add hub_docker_ci.yml, for building docker images (triggered manually for now) (#22302) - ci: use `docker compose` instead of `docker-compose` ( see https://github.com/orgs/community/discussions/116610) (#21992) - vrepl: suppress the welcome message, if VQUIET is set (#21941) - Make `v where` ignore .git/ folders (they contain binary files); let `-dir .` work recursively, so that `-dir vlib` works - Sort the match results in the vwhere test, to make it less flaky (#22033) - Add an amalgamate tool and description of usage (#22034) - Add a few missing v command entries and their flags in `v complete` (#22041) - Colorise the output of cmd/tools/show_ancient_deprecations.v, reduce false positives (#22048) - docs: clarify the .precision specification section for string interpolation of floats (#22061) - docs: add a copy code function (top/right copy icon) on doc examples (#22114) - Allow passing parameters to fuzz_v_parser_with_radamsa.sh, so that it could be run in several processes from the same folder - Use separate .autofuzz.log files too for the separate invocations of fuzz_v_parser_with_radamsa.sh - Extract .github/workflows/run_sanitizers.sh to ease local testing with different options - parser,ast: protect against more overflows/panics, by forcing early returns on deeply nested expressions and scopes (#22098) - Improve the output of `v repeat command`, by coloring the `faster/slower` label - Add diagnostic in `v repeat` for invalid combinations of -r, -i and -a flags - Fix `v doc` truncating code blocks, that lack a specific language (fix #22017) - v.util: add get_build_time/0, supporting https://reproducible-builds.org/docs/source-date-epoch/ - Fix `v doc` not converting `` in plain code blocks into encoded html entities in its .html output - ci: run `npx prettier --write **.yml`; ensure it is run on all .yml files, not just the ones in the .github/workflows/ folder - docs: add implements keyword for explicit interface implementations (#22214) - Make fast_job.v more robust (setup a custom PATH) and informative on fast.v failures (compile it with -g) - Make fast.v and fast_job.v more self sufficient - ci: add cache and trigger for pushes, in the Hub docker action (#22314) #### Operating System support - docs: streamline the installation instructions and notes for Windows and Ubuntu - v.builder: fix errors in cstrict mode on OpenBSD with clang (#22154) - thirdparty: fix compilation of programs using miniz.h on macos - crypto.rand: fix compilation on macos with `-cc tcc -no-retry-compilation -gc none` - thirdparty: fix compilation of thirdparty/mbedtls with tcc on macos m1 - v.pkgconfig: fix parser, when `includedir=` lines, had trailing spaces (fix `-d use_openssl` for openssl 3.3.2 installed through brew on macos) - builtin: fix compilation with tcc on OpenBSD using libgc (#22234) - docs: add FreeBSD in cross compilation section (#22249) - v.builder: enable LTO for clang on OpenBSD (#22247) - thirdparty: fix compilation of programs using miniz.h on OpenBSD (#22254) - net: fix compilation on windows (use casts to int for net.error_eintr etc) - net: use explicit int casts for net.error_eintr etc in the unix implementation too for consistency with the windows one #### Examples - Remove drag_n_drop.v from the list of examples, that are checked for visual differences with vgret, since it now uses the default gg font - docs: add more C interop notes and examples (#21965) - cleanup obsolete unsafe{} usages in examples/sokol/sounds - cleanup & fix the sound produced by melody.v - add a simplified bytebeat player to show how to use sokol.audio, and that does not depend on gg - make `rotating_textured_quad.v` compile and run on Android (#21987) - veb: change example description, to avoid repetitive wording (ease debugging of issue#22017) - eval: fix `./v interpret examples/hanoi.v` - add examples/ttf_font/draw_static_text.v, to make it easier to test x.ttf with different fonts, and texts - make draw_static_text.v show the font name too, for easier comparisons - prevent cliping of long font names in draw_static_text.v - docs: add an example on how to use Options/Results, when returning multiple values from a function (#22099) - add examples/gg/draw_unicode_text_with_gg.v, for easy comparison of how different fonts and unicode texts will look, when rendered by gg - add examples/veb/websocket, to show how to use http connection upgrade to a websocket, from a `veb` route (#22128) - migrate vweb examples to veb - fix type in veb_example.v - add `gc_is_enabled()` check to `2048` to prevent crash in Android emulator (#22274) - make `gg/rectangles.v` Android friendly (#22275) - make `gg/stars.v` run on android (#22276) - examples,os: add an os.asset module, use it to simplify code in examples/, by removing `$if android {` checks (#22281) - add a consistent background to flappylearning, shown when the height of the view is very high (on Android) ## V 0.4.7 *26 Jul 2024* #### Improvements in the language - Add support for `-d ident=value` and retrieval in code via `$d('ident', )` - `-warn-about-allocs` for debugging allocations when using manual memory management - `@[freed]` attribute for assign statements (for the above mode) - Implement `&&=` and `||=` operators (#21678) - Improve C var args interop, allow for `fn f(some int, ...) {` (#21812) - A new flag `-n` for skipping notes (similar to `-w` for skipping warnings) - Cross compilation to FreeBSD #### Breaking changes **none** #### Checker improvements/fixes - Fix unknown fixed array size for `const n = int(sizeof(u64)); _ = [n]int{}` (fix #21544) (#21548) - Fix checking of default field initialisations, that are part of unions of structs tagged with `@[noinit]` (#21587) - Disallow sum type with `Result` variants (#21620) - Add error for `field map` (i.e. a plain untyped map), used inside a struct (#21625) - Fix missing concrete type checking on a generic type specifier (#21614) - Fix missing option and result wrong type return type definition (#21626) - Turn warnings for private fields into errors (#21296) - Support nested labeled for statements (#21658) - Fix the return type of overloaded operators, defined on aliases of primitive types (fix #21654) ( #21663) - Fix match expr with auto promote number (#21696) - Fix sorting compare fn with mut reference parameter (fix #21662) (#21706) - Fix `$if x {` condition, using `const x = $d('ident', false)` (fix #21709) (#21713) - Fix generic variable resolution on generic func return assignment (#21712) - Fix result call or_block with multi-statements (fix #21504) (#21717) - Allow `\uxxxxx` in raw strings (#21724) - Limit recursion in Checker.ensure_type_exists/2 to 40 levels (it is usually 4 or less) (#21734) - Add error for `field [$d('x', 2)]int = [1, 2]!` (#21741) - Fix nested if expr method call (#21773) - Fix generic inference in if expressions used in assignments (#21781) - Disallow nil in non-nil arrays and vice versa (#21786) - Check expr evaluated but not used (fix #21436) (#21816) - Fix wrong receiver generic resolution with embed types (#21833) - Check mismatch of fn call mut argument (fix #21857) (#21873) - Fix global fixed array key resolution when it is a constant ident (#21900) - Improve checks for embed in anon struct (#21877) - Fix builtin fn var resolving (#21899) - Fix spawn when calling undefined function (#21906) - Require enum values to be declared, before using them in other enum values (#21913) - Check enum field value duplicate (#21920) - Allow embed of type alias anon struct (#21928) #### Parser improvements - Register selective import aliases as used (#21613) - Allow multiple flag values in enum.from() for flag enums (fix #21569) (#21615) - Disallow duplicate operator overload (#21675) - Support `[$d('s', 4)]int{}`, move resolving to method on `ComptimeCall` (#21701) - Support `$d()` in fixed size array `struct` fields (#21731) - Suggest using type alias when defining methods on non-local types (#21803) - Sugggest map initialization with the correct syntax (#21817) - Fix parameter collision for generated `@[flag]` enum methods, with modules named `flag` (#21844) - Fix high order generic fn resolution (#21871) - Fix recognition of `mod.Enum.val` inside fn args (#21908) #### Compiler internals - tools,cgen,pref: add `-coverage` support + `vcover` tool (#21154) - v.utils: allow to set the names of the compared items, when diffing strings (#21650) - v.pref: fix regression of command flags not working, when there is a subfolder, named after the command, in the current working folder (#21647) - transformer: handle `enum_variant = some_const + 10` (fix #21777) (#21779) - v.builder: print the suggestion for using `v xyz` instead of `v xyz.v` just once (#21801) - v.builder: improve the C compilation output on cgen errors (#21885) - v.scanner: use table lookups for very frequently done character checks (#21931) - markused: mark explicitly all used array and map methods with `-skip-unused` (fix #21907) (#21914) #### Standard library - builtin,v: reduce overhead and memory usage for very frequently called methods (#21540) - builtin: reduce allocations in s.index_kmp/1 and s.replace/2 (#21561) - os: remove mut declarions for unchanged vars in `os_nix.c.v` (#21564) - os: make minior improvement to C function semantics and related code (#21565) - builtin: simplify splint_nth methods (#21563) - toml: fix `@[toml: ]`, support `@[skip]` (#21571) - builtin: update `last_index_u8`, deprecate `index_u8_last` string methods, make consistent with `last_index` (#21604) - builtin: implement a JS version of `string.split_any` (#21612) - crypto: add a `crypto.sha3` hash and extended output functions (#21664) - crypto.sha3: remove unnecessary return at the end of the write function (#21669) - builtin: fix string.find_between(), when not found end string return '' (#21670) - builtin: add string.camel_to_snake/0 and string.snake_to_camel/0 methods (#21679) - cgen,x.json2: fix generic map decoding (#21704) - encoding.base32: fix warning of implicit clone of array, by using an explicit unsafe block ( #21728) - vlib: simplify byte character conditions by using methods like is_capital, is_lower, is_letter etc (#21725) - gg: add Context.draw_cubic_bezier_recursive/2 and Context.draw_cubic_bezier_recursive_scalar/9 ( #21749) - ci: fix deprecations_consts.out (the warning for math.max_i8 is now an error; it was deprecated since 2023-12-31) - math: add divide_truncated/2, divide_euclid/2, divide_floored/2 and modulo_truncated/2, modulo_euclid/2, modulo_floored/2 (#21759) - math: avoid unused calculations for math.modulo_floored/2 and math.modulo_euclid/2 - crypto.blowfish: apply `@[direct_array_access]` to very commonly used functions (#21771) - encoding.binary: little_endian_f32_at - arrays: add arrays.chunk_while/2, where `arrays.chunk_while([0,9,2,2,3,2],fn(x int,y int)bool{return x<=y})==[[0,9],[2,2,3],[2]]` - sokol: reduce _SGL_DEFAULT_MAX_VERTICES back to 1<<17 (1<<22 in 811ac12, leads to ~140MB of memory usage for gg/minimal.v, instead of just ~38MB) - vrepl: fix os.input() (#21811) - Improve consistency and behavior regarding explicit mutability (#21566) - builtin: add `pub fn arguments() []string {`; make `os.args` use it, remove edge case in cgen ( #21852) - builtin: support `-d use_bundled_libgc` to make it easier to debug/upgrade reliably libgc cloned from ivmai/bdwgc (#21869) - time: increase http_header_string performance (#21894) - builtin: add s.trim_space_left/0 and s.trim_space_right/0 methods (#21903) - strconv,math.bits: eliminate bounds checking in commonly used routines - arrays: fix arrays.fold, when the `init` value in the call, is an array (#21921) - string: fix leak in replace_once #### Web - net.http: change default http.Server listening address to :9009, to avoid conflicts with tools, that start their own http servers on 8080 like bytehound (#21570) - net.urllib: update parse host to allow for better error handling (#21602) - net.html: quick workaround for a cgen problem for `const x = int(0x80000000)` - net.http: implement http.download_file_with_progress/2, saving each chunk, as it is received, without growing the memory usage (#21633) - veb: update import name in docs (#21668) - Add `m3u8` MIME type `application/vnd.apple.mpegurl` for multimedia playlists (#21688) - veb.auth: use constant time comparison in compare_password_with_hash (#21693) - net.http: correct `Response.status()` method comment, to indicate returning of a `Status` enum field, instead of struct (#21735) - net: fix TcpConn.peer_ip/0 to only return the ip address, without the port number (#21831) - Add mime type `text/x-vlang`, for `.v` and `.vsh` file extensions (#21851) - net.conv: add conv.reverse_bytes_u64/u32/u16 (#21917) #### ORM - orm: fix subquery without where expr (#21598) - orm: ilike for case insensitive text search - orm: update readme with more specifics (#21697) #### Database drivers #### Native backend #### C backend - Fix printing of floating point values in asserts (#21538) - Fix array fixed initialization on struct from call (#21568) - Put the `Interface(unsafe{nil})` change for now behind -experimental (#21593) - Fix indexexpr with orexpr (fix #21591) (#21592) - Fix generic struct init when it is a reference &T (fix #21594) (#21596) - Fix generated code for handling fn call with result/option return on match conditional (#21608) - Fix missing call to a function returning option, when called inside a print (fix #21616) (#21623) - Support a `-d no_bool` option, for cgen compatibility with the C23 language standard (since `bool` is a builtin type and a keyword in it) (#21637) - Fix or expr with non option fn call return (fix #21660) (#21661) - Generate pragmas for gcc-14, to make it more relaxed by default. Support `-no-relaxed-gcc14` for turning them off. (#21680) - Fix spawn code generated when calling conditional function (fix #19352) (#21681) - Fix comptime generic arg resolution (allow several different struct fields in generic functions using comptime) (fix #18110) (#21682) - Fix dumping array of reference (#21694) - Implement g.trace_last_lines/2 to help debugging cgen problems - Support inc cond for c style for loop with alias types (#21708) - Fix fn call with mut reference args (fix #21265) (#21719) - Fix auto dereference mut variable in if expr (fix #21309) (#21720) - Fix smartcasting a reference to a sumtype value (#21730) - Fix assert checking fn option ret with `none` (#21726) - Fix generics map with the reference argument (#21737) - Fix shortcircuiting of infix and/or expressions (#21740) - Simplify in infix_expr_and_or_op() (#21745) - Fix reference variable str() method call (#21753) - Fix scope command when `$dbg` breakpoint is on or-expr (fix #21772) (#21747) - Fix array fixed empty struct code generated on clang (fix #21761) (#21764) - Allow alias to array fixed to be initialized like `[n]int{}` (#21785) - Fix comptime call argument auto conversion for indexexpr (fix #15232) (#21796) - Fix const name without main prefix in `-translated` mode (#21789) - Fix closure variable with optional reference params (fix #21827) (#21829) - Fix auto str for fn struct member (#21825) - Fix option string struct member init with autofree (#21859) - Fix fn mut argument of sumtype reference (#21874) - Fix generic type init syntax for primitive types (#21872) - Fix missing `&` in string representation of `map[X]&Y` (#21890) - Fix optional closure direct call (#21892) - Fix wrong missing unsafe block checking when calling generic functions with @[unsafe] attr ( #21898) - Fix typeof(var.typ) with comptime $for variables (#21901) - Fix enum with const value (#21919) - Fix generic option/result reference return (#21922) #### vfmt - Allow single line `defer {}`, just like `or {}` - Don't break `it` variable name in match expression function calls (#21600) - Exit with error code if encountering diffs with `-diff` flag (#21603) - Add fn_with_mut_ref_params_keep.vv (#21711) - Implement wrapping function's super long arguments (fix #15545, fix #21643) (#21782) - Keep manual newlines after fn parameters in fn declarations, do not auto wrap (#21795) #### Tools - Fix spurious ending quote in the output of show_manual_release_cmd.vsh - Dockerfile.alpine: update to alpine:3.20, add more tools like gdb, libunwind, gc, to ease producing and debugging static executable in more situations (#21583) - Add `v download URL` for downloading single files, to avoid curl/wget etc, which are not available uniformly. (#21597) - ci: use shebang with better portability in shell scripts, format shell scripts (#21605) - Don't write vpm logfiles in CI runs (#21649) - ci: make vmodules_overrides_test.v failures more informative - Fix measurements for `./v repeat "./vold -o x project/" "./vnew -o x project/"` - Make the summary output of `v repeat` more informative - Disallow self referencing function alias types like `type FnType = fn(string) FnType` and `type FnType = fn (FnType) string` (#21733) - vrepl: fix method call (fix #21788) (#21792) - ci: restore v_apps_and_modules_compile_ci.yml (#21791) - vrepl: fix output of the fn call (related #21792) (#21800) - vrepl: fix variable name starts with print (#21806) - v.pref: make pref_test.v be less sensitive on the specific C compiler used as a backend (#21813) - vrepl: fix arbitrary script execute (#21818) - ci: disable c2v_ci.yml temporarily, until it is fixed - vrepl: lots of fixes in REPL - Add a TOTAL line, to the output of -show-timings, to minimise the need for external tools on windows (#21847) #### Operating System support - veb: support sendfile() syscall on FreeBSD (#21541) - os: use 1 instead of C.SW_SHOWNORMAL to workaround a cross compilation issue from linux to windows - v.builder: minimise the amount of linked libs for cross compilation to FreeBSD - v.builder: support downloading the FreeBSD cross compilation files on first use - Add a test for crosscompiling hw, on linux and macos, to FreeBSD (#21553) - vlib: make `./v -Wimpure-v -W test vlib/` pass on Linux (#21554) - os: fix debugger_present() for non Windows OSes (#21573) - ci: extend coverage, move app test from macos_ci to v_apps_and_modules_ci (#21584) - gc: fix tcc on macos - os.font: return the "segoeui.ttf" font, if its file exists on Windows (#21655) - readline: fix s := read_line('Message\nName:') on unix/linux (#21930) ## V 0.4.6 *20 May 2024* #### Improvements in the language - Experimental `x.vweb` is now `veb`, the official and recommended way to build web apps in V. Built on top of pico.v. - autofree: -print_autofree_vars command line flag for printing variables autofree couldn't free - Add `@VMODHASH` comptime variable to store the commit sha of a V module (#21091) - Fix sumtype support for option variant types (#21101) - Utilize new diff functions in errors (expected/found) (#21431) - Add @[_linker_section] for global variables #### Breaking changes - checker: disallow initializing private struct fields outside structs module (#21183) #### Checker improvements/fixes - Ambiguous expression notice for `& << >>`, similar to `&& ||` - Disallow using aliases of ?Type as !Type (#21128) - Fix option checker arg validation for ptr passing on non expected ptr (#21087) - Optimize option and result type check, add more typinfo to error details (#21105) - Move error handling for `any` type to the checker to resolve parsing issues (#21146) - Move error handling for user defined type duplicates to the checker to resolve parsing issues ( #21147) - Detect redundant ref when assigning call expr with ref return (#21141) - Fix multi return using nil and voidptrfix (fix #17343) (#21144) - Fix C struct embedded init fields checking (#21137) - Remove resolved vfmt workaround and TODO (#21175) - Move more match validation from the parser into the checker, add error for match without branches (#21181) - Improve the error message for an unknown type (#21207) - Allow passing `none` to `fn f(arg ?&Type) {` (fix #21213) (#21231) - Fix -parallel-cc regression (part 1, workaround .filter(fn[c]) used in checker/orm.v) (#21238) - Detect and error on unreachable code in loops, after `continue` and `break` statements (#21294) - Disallow `Result` callbacks functions like `map/filter/all/any` (#21055) - Fix missing check for or expr on string interpolation (#17566) - Allow pass array as mut param to spawn fn (#21283) - Turn array assign warning into error (#21341) - Ignore last semicolon on or-expr (#21361) - Disallow structs with `@[params]` attribute as mutable function parameters (#21206) - Set auto Return pos correctly; cgen: autofree fix for optional returns - Disallow invalid ptr operations (#21515) - Fix wrong checking for heap struct (#21511) - Allow alias enum flagged to have bit operations (#21532) - Simplify, utilize pref.vroot (#21096) - Fix option interface member checking when `none` is passed (#21509) #### Parser improvements - Fix option as possible match case for sumtype (#21079) - orm: disallow invalid infix for where clause in `delete` and `update` (#21113) - Fix case of falsely registering imports as used, remove unused imports (#21156) - Remove redundant comments_mode field (#21198) - Update file path fields; use more expressive name for file path, remove obsolete `file_name_dir` field (#21202) - Add missing docstrings for vlib/v/ast/comptime_const_values.v functions (#21219) - Allow struct init on `for in Iterator{} {` (fix #21179) (#21282) - Fix `for x in Iterator{} {`, when there are no field initialisations (#21333) - Add check for result type on chan init (#21363) - Fix comptime panic for `$tmpl("x.html")`, when the template file contained % at the end (#21402) - Parse string and array typ idx of `ScopeVar` and `Ident` (#21523) #### Compiler internals - v.util: use tmp instead of cache dir for temporary diff files (#21075) - v.util: fix module lookup if module import parts end with the word `modules` (#21083) - v.util: update `githash` to be able to get the githash of every passed project (#21178) - v.util: improve detection for opendiff when automatically searching difftools (#21241) - v.util: improve color_compare_files (#21247) - v.util: improve find_diff_cmd: don't add spaces to result without env opts (#21242) - v.util: fix diff coloring, add test (#21260) - v.util: polish off diff utils after recent updates and fixes, add doc comments to pub fns (#21275) - v.builder: suggest using `v wipe-cache`, when the object files are not recognized - pref: be more conservative when generating code using `-cross`, allow for `$if cross ? {` - builder: use cc enum in CcompilerOptions, fix cc detection, enable cc guessing without prod flag ( #21370) - pref: fix version flag handling (#21377) - pref: make minor performance related changes / simplify (#21379) - builder: simplify generic cc detection (#21380) - pref: extract architecture related code into `arch.c.v`; rename `pref.c.v` to `pref.v` (#21387) - pref: update `os_from_string`, add missing `qnx`, remove deprecated wasm options that used `-` instead of `_` (#21390) - v.util: rewrite diff module, deprecate old functions (#21403) - v.util: fix color when auto tool is `diff` (#21435) - v.util: make diff_test.v more robust to the color settings for the chosen local diff tool - v.util: fix performance with `v test-cleancode`, when a slower diff tool is installed (#21447) - v.util: remove fast path in `diff.compare_text` (#21458) - v.pref: error for `v file.v --unknown-option` (#21391) #### Standard library - builtin,dlmalloc: fixes for `v vlib/v/gen/c/coutput_test.v` for gcc14.1, which is stricter - Min window width and height - builtin: str.last_index(); pref: hide-auto-str; - toml: update the alexcrichton and BurntSushi repos to their successors toml-rs, and toml-test, record new exceptions (#21152) - breaking,vlib: update handling of imports whose symbols are not directly used in imported file, remove `pub const is_used = 1` workarounds (#21160) - json: allow `i32` decoding and encoding (#21162) - json2: add ability to decode arrays (#21163) - json2,checker,toml: allow field.typ compile-time checking with MatchExpr and add array of option checking (#21171) - gg: draw_text with custom fonts - x.json2: add a way to decode an array (#21186) - os: clarify some doc comments (#21209) - os: fix double free in os.get_raw_line() (used by os.input), with `-autofree` (#21204) - time: extract Duration related code into duration.v (#21229) - builtin: implement an `at_exit(cb)` wrapper for C.atexit (part 1) (#21254) - os: format readme, fix markdown inside html (#21286) - time: update unix time acces, fix issues related to deviating unix times (#21293) - vlib: refactor empty string checks to use `s == ''` or `s != ''`, instead of `s.len == 0` (#21300) - cli: update `command_test.v` (#21307) - cli: extend control over defaults (#21308) - thirdparty/sokol: bump _SGL_DEFAULT_MAX_VERTICES and _SGL_DEFAULT_MAX_COMMANDS again; mark them with `__v_ start` and `__v_ end` - sync: add Gentoo paths for libatomic - sync.stdatomic: add flag lines for gcc 14 too - gg: make `PenConfig` fields public (#21353) - builtin: fix undefined read s[0], from ''.is_lower() and ''.is_upper() in c7af2c2 - builtin: fix empty string lower / upper assert (#21358) - cli: simplify flag parsing (#21392) - os,runtime: workaround for v.c generation instability - datatypes: fix for set `-` operator, union and intersection, now they no longer change the receiver (fix #21315) (#21362) - sync.stdatomic: add paths for compilation with musl on Gentoo (#21400) - os: fix os.execute stderr redirection (fix #20986) (#21404) - time: fix the string representation of a negative Duration (#21407) - cli: make program outputs using the cli module testable in `cli/testdata` (#21456) - math.unsigned: permit _ separators in Uint128 decimal strings passed to uint128_from_dec_str ( #21461) - cli: fix default flags when their command equivalents are disabled (#21469) - toml: simplify `decode_quoted_escapes` (#21472) - os: fix join-path (#21425) - builtin: simplify MessageError.msg() (#21524) - all: replace usages of C.atexit(cb) with `at_exit(cb) or {}` (part 2) (#21263) - math.unsigned: fix some Uint256 bugs and add tests (#21528) #### Web - Update `mbedtls` to latest compatible version v3.3.0 (#21118) - veb.auth: a minor find_token fix - Improve descriptions (#21155) - ci: change listen ports in vweb_should_listen_on_both_ipv4_and_ipv6_by_default_test.v for both vweb and x.vweb, to reduce probability of network errors - ci: mark both vweb and x.vweb versions of vweb_should_listen_on_both_ipv4_and_ipv6_by_default_test.v as flaky - breaking,net.ftp: allow to choose a different port than port 21 (change FTP.connect to accept `host:port`, not just a `host` address) (#21185) - x.vweb: accept query params as method arguments (#21201) - net.http.file: support index_file (`index.html` by default), and auto_index (true by default) parameters to file.serve() - veb: copy x.vweb to veb, and make it work with comptime - ci: fix the ubuntu-docker-musl job by skipping veb_app_test.v - pref: support a shortcut: `v -http` for `v -e "import net.http.file; file.serve()"` . - net: add a .port()! method for net.Addr (#21412) - net: improve error message in .port() - picoev: handle `EAGAIN` or `EWOULDBLOCK` quietly (#21480) - net.unix: remove debug/trace eprintln (#21517) #### ORM - Add error for unchecked option multi return types, fix undefined behavior (#21106) #### Database drivers - db.mysql: fix invalid memory access in exec_one for returned rows with NULL fields (#21317) #### C backend - Enable autofree for option (#21051) - Force C struct types which does not implement str() to be passed as ptr (#21054) - Improve diagnostic information for ORM queries with invalid types - Allow static call on generic type (#21071) - Fix code generation for a struct field, having a type of fixed array of options `field [5]?Type` ( #21082) - Add the `_M_ARM64` macro to endianness check (#21109) - Fix return code when returning interface result type (fix #21115) (#21130) - Fix const initialized with array (#21131) - Fix infix array heap comparison (#21145) - Fix C struct sumtype support (#21129) - Add `autofree` comptime check (#21197) - Fix comptime `$if !autofree {` (#21218) - Allow `for mut v in [12, 13, 14] { v+= 2 }` (#21237) - Allow op overload for type with generic parent (#21262) - Optimize .map(), .any(), .filter() and .all() when using closure (#21256) - Fix `none` passed to a generic option cast expression (fix #21215) (#21276) - Fix `-fsanitize=undefined` used with `[]int{}.sort()` (#21331) - Fix `myarr [1]C.mytype` fixed array fields, for `pub type C.mytype = voidptr` (#21266) - Fix comptime ref argument passing (#21335) - Use the real C line number instead of `#line 1000000 ...` in the C footer with `-g` (#21388) - Fine tune the line count reset for the C footer (fix off by 1 error in 00dd0bf) - Fix array.delete_last call generation (#21439) - Fix option ptr unwrapping (#21415) - Fix C struct option alias printing (#21496) - Handle auto deref var for index when the array element is an interface or a sumtype (#21491) - Fix C struct init when it has default expr (#21510) - Fix sumtype field naming (when they are the same as a C keyword) (#21527) #### vfmt - Update determining of struct field comments (#21066) - Inform about invalid interop function bodies instead of removing them (#21070) - Parse methods on JS interfaces, write JS method bodies (#21088) - Improve module detection when formatting imports (#21134) - Don't change paths when formatting imports (#21148) - Use fixed size array for max_len const (#21140) - Simplify const name formatting (#21143) - Improve import processing, add test (#21172) - Fix duplicates remove import comments (#21177) - Extend import import alias reference map for submodules (#21200) #### Tools - doc: fix vup/vself replacement scripts (#21092) - Prevent module updates during `v build-tools`, when VTEST_SANDBOXED_PACKAGING is set (#21094) - ci: update the reference to the v-analyzer repo - ci: retry all setup commands that need network access, till they succeed (so the CI jobs have less false positives) (#21103) - changelog: escape `@NAME` entries, to avoid mentioning unrelated github accounts - Add `v retry apt update`, intended to replace the retry.sh script, for more robust CI jobs ( #21104) - vpm: show the final path where a module is installed, improve color contrast for white on black terminal sessions - vet: print help when passing no files or `--help`/`-help` flag after vet command (#21108) - Fix `v build-tools` (it skipped all tools in subfolders of cmd/tools/ after 6a4f293) (#21120) - .gitignore: ignore generated .NET files in bench/vectors (#21136) - vet: optimize performance for path detection, when vetting files (#21139) - vet: allow to overwrite excluded dirs (#21142) - ci: increase wait time for the xvfb check, to reduce the chance of false positives - Fix `v run cmd/tools/measure/parser_speed.v file.v` - Add `v run cmd/tools/measure/fmt_speed.v file.v` - ci: move build step for VPM site, into apps and modules ci, add concurrency config (#21191) - tools.vpm: debug-log to `$VMODULES/cache/vpm.log` if not running in debug mode (#21192) - vpm: optimize performance by adding filter when cloning (#21216) - vdoc: don't add _docs directory when an out path is specified (#21233) - ci: prefer dedicated tiggers for platform workflows, so sporadic fails can be retried quicker ( #21251) - v.util: improve code related to diff tool specified via environment, add check if the diff tool exists (#21240) - vpm: check for git version before adding `--also-filter-submodules` flag (#21259) - ci: add logging to .github/workflows/retry.sh - Revise `vtest-self.v`: remove dead paths, fix json2 essential test path (#21267) - Add check for unavailable files in vtest (#21272) - ci: reactive app prod builds (#21295) - ci: add a m1 runner for testing the prebuilt zips too - ci: add workflow_run: event in prebuilt.yml - ci: simplify prebuilt.yml, make it usable for manual runs too - vpm: fix regression, so `v install sdl && v run ~/.vmodules/sdl/setup.vsh` works again - ci: fix outdated_test.v (--unshallow is not needed now) - ci: continue testing independent V apps, even if one fails, to get feedback for breaking changes faster (#21302) - ci: optimize apps and modules (#21303) - ci: test `v ~/.vmodules/sdl/setup.vsh`, to prevent future vpm regressions (#21306) - ci: prevent unintended deployment workflow steps (#21313) - Add a 2024.html page to https://fast.vlang.io/ - vdoc: rewrite and extend vdocignore (#21314) - ci: fix the commit labels for the vc repo - Support `v run cmd/tools/oldv.v --show_VC_commit weekly.2024.03` - ci: use latest upstream `discord.v` in apps and modules test (#21322) - vdoc: remove obsolete entries from `.vdocignore` (#21320) - v: update linguist languages, add .vdocignore (#21321) - ci: update deployment workflow (#21323) - Allow for selectively running `v test-self vlib/` and `v test-self cmd/` (#21326) - Rewrite test-self arg handling (#21327) - ci: restore `v install elliotchance.vsql` in v_apps_and_modules_compile_ci.yml - ci: use `v retry -- cmd` to replace `.github/workflows/retry.sh cmd`, where possible in `v_apps_and_modules_compile_ci.yml` (#21336) - ci: update workflow conditions (#21338) - Improve `v symlink -githubci` diagnostic message, when used outside CIs or with sudo (#21340) - ci: update detection of workflow cancellation scenarios (#21342) - Fix compiling vwhere with `-cc gcc -cstrict` (#21347) - ci: remove the separate `-gc boehm` job (since `-gc boehm` is the default now) (#21352) - ci: add a separate cmd/tools testing job (#21344) - Update fast.v and fast_job.v to update docs.vlang.io and fast.vlang.io on each commit to master. - Make fast.v more robust to independent remote changes in vlang/docs - Utilize environment specific files for vsymlink (#21360) - ci: update `binary_artifact.yml` (#21364) - ci: add docker to tools workflow, update ignore paths (#21368) - ci: split up vsl / vtl run, reducing the tool change CI time from ~19min to ~10min (#21372) - ci: fix binary_artifact.yml (#21373) - Refine `check_os_api_parity.v` (#21371) - ci: update native backend ci matrix (#21375) - ci: update symlink ci, add matrix (#21376) - ci: workaround defer codegen failing with nested if blocks and -cstrict in vdoc_file_test.v - ci: update detection of accidentally added gpl licenses (#21384) - ci: set cancel-in-progress to false in bootstrapping_ci.yml to avoid false positives - ci: do trigger bootstrapping_ci.yml periodically, but just on changes - ci: speed up bootstrapping_ci.yml, by using the default tcc when possible - ci: update `bootstrapping_ci.yml` trigger paths (#21394) - ci: pass a good commit to oldv.v in `bootstrapping_ci.yml` (#21393) - Be more verbose when doing `v up` in V folder produced by extracting a .zip release file - Exclude thirdparty/tcc from the git clean operation, that vup does in case of a missing .git folder - Protect from cleaning during `v up`, only ./v , not any matching folder - Use proper ignore/exclude patterns in the git clean, that `v up` does - Use more meaningful names in vup.v - Be verbose, when a git commands that `v up` executes fails - ci: add a v-up-works-ubuntu job, to ensure more robust `v up` runs (#21401) - ci: ensure v master is available when trying to check out its commits to build oldv (#21414) - Rewrite vet error handling (improve parser performance extend vvet) p1 (#21417) - Move dynamic const array check from parser into vet (#21423) - v.help: update help for `fmt` (#21430) - Move array_init_one_val checks from parser into vet (#21422) - Remove `vet_errors` and `vet_notices` from parser (#21424) - ci: temporary fix for gitly compilation - Remove vetting for spaces after / before parens (#21437) - Add `.github/workflows/show_manual_release_cmd.vsh`, to make cross platform testing of the release process easier - ci: merge docker_alpine and docker_ubuntu workflows in `docker_ci.yml` (#21446) - Move now obsolete vlib vet module to cmd vet (#21445) - Use `parse_file`, remove `parse_vet_file` (#21444) - ci: update binary artifact workflow, add matrix (#21378) - ci: add workflow_dispatch: to gen_vc_ci.yml - ci: fix vinix_ci.yml by using `./v symlink -githubci` in vinix_ci.yml - ci: port changes from Vinix's check.yml at 8231e569 to vinix_ci.yml - tools.vet: move error methods to `vvet/errors.v` (#21449) - ci: reduce false negatives for tcp_test.v, retry it 3 times before failing - Improve performance of `v test-cleancode` and `v fmt -inprocess -verify .` (#21450) - Make `./v symlink` work platform independent in CI (part 1) (#21453) - ci: replace .github/workflows/retry.sh usages in the CI with the shorter `v retry --`, move `v test-cleancode` upwards to save time for unformatted PRs (#21452) - Capitalize information output of `v up` (#21464) - ci: use `v symlink` without `-githubci` for regular symlinking (#21455) - ci: add a linter for the .yml workflow files (#21459) - ci: update symlink ci, extend tested cases (#21466) - tools.vet: update diff comparison in `vet_test.v` (#21457) - Call mkdir_all before set_output_path to avoid a vpm panic when ~/.vmodules/cache does not exist ( #21463) - ci: make issue template title consistent, fix linter error regarding labels (#21460) - tools.vet: reduce nesting in `vet_fn_documentation`, skip vetting empty lines (#21465) - Print info to use v symlink instead of `v symlink -githubci` (#21471) - Move _test.v files for vdoc at the same level (#21473) - ci: update the helper script, for getting the most recent sqlite-amalgamation-3380200.zip (#21474) - vdoc: fix handling of .vdocignore files in subdirectories (#21514) - ci: run build-module-docs, when changes to the source of the `v doc` tool happen too - ci: use g++ not g++-11 in misc-tooling (g++-11 can not be found and installed on the CI runner anymore for some reason) - ci: update g++ to g++-10 in other_ci.yml, add workflow_dispatch: trigger for easier local future diagnostic - vdoc: improve vdocignore file handling by walking all .vdocignore sub-paths in IgnoreRules.get, add test (#21521) - ci: run `v fmt -w cmd/tools/vdoc/vdoc_test.v` - ci: make sure that unformatted code in just cmd/ is not allowed - ci: mark again tcp_test.v as flaky (it had 3 unrelated failures on the CI over the last week) - v: vet for empty string conditions (#21529) - tools.vet: add notice for empty strings conditions (#21421) #### Operating System support - ci: improve test robustness on windows (#21116) - v.pkgconfig: add pkgconfig path `/usr/libdata/pkgconfig` for FreeBSD base packages (#21151) - v.util: add diff tool color support detection (tested on linux and freebsd) (#21244) - v.util.diff: return diff options with the diff command for FreeBSD/OpenBSD (#21271) - v.pkgconfig: fix load_paths with `;` split char on windows (#21291) - Fix vpm on macos, when using the bundled git executable (#21292) - ci: fix the bundled tcc for macos arm64 (#21299) - ci: update the runner for build-macos-arm64 to `macos-14` too, so it runs on M1 - Fix hot code reloading on windows (#21351) - Fix building vpm on the FreeBSD instance, that runs fast.v - Fix `v install` for the FreeBSD instance that updates docs.vlang.io . - ci: use macos-13 for cross_ci.yml to force the old non m1 runner - v.builder: update macos->linux cross compile message (~22MB -> ~77MB) - v.pref: fix new pref test on FreeBSD (#21385) - ci: stop earlier on vc/v.c files, that may break on systems != linux (#21397) - Fix compilation on macos-arm with `-cstrict`; run macos ci also on the arm runner (#21408) - ci: use `v` instead of `./v` in the platform linux/macos/windows/_ci.yml files (#21454) - ci: add a retry to vcreate_init_test.v (it is sporadically flaky on macos) - sync,os,thirdparty: fix cross compilation from macos to windows (#21484) - os: rename os_structs_stat_windows.v to os_structs_stat_windows.c.v to fix `v -Wimpure-v -os windows vlib/os/os_stat_test.v` - Default to `-cc clang` on FreeBSD in `cmd/tools/vtest_test.v` (#21534) ## V 0.4.5 *20 March 2024* #### Improvements in the language - Add map update-init syntax: `new_map := {...old_map, 'k1': 1, 'k2': 5}` (#20561) - Improve coroutines, Photon vcpu creation, coroutines + GC fixes (#20549) - Update Boehm GC libs/headers to the latest version 8.3.0 (#20772) - $dbg statement - native V debugger REPL (#20533) - Implement `@[_linker_section]` attribute (#20629) - Enable `@[export]` for global variables too (#20649) - Add callstack support on v.debug (#20680) #### Breaking changes - sokol: the sokol wrapper was updated, to match its upstream version at commit 058a4c5, several of its APIs no longer exist - templating.dtm: compile_template_file is no longer public - v.trace_calls: `pub fn on_c_main() {`, is now `pub fn on_c_main(should_trace_c_main bool) {` - v.transformer: Transformer.fn_decl is now Transformer.fn_decl_trace_calls - x.vweb: Context.redirect(url string, redirect_type RedirectType) is now Context.redirect(url string, params RedirectParams) #### Checker improvements/fixes - Check invalid lambda expr (#20461) - Fix comptime if with comptime smartcast (#20466) - Fix anon struct init with const fields (fix #20452) (#20463) - Disallow `option` or `result` return type, for infix operator overloading (#20494) - Cleanup the const variable evaluate for fixed array fields of structs (#20503) - Fix missing check for struct initialization with `@[noinit]` attribute, through using `T{}` ( #20516) - Fix mark methods into used-list, when generics as receivers (fix #20509) (#20527) - Modify comments on generic receiver type storage (#20539) - Fix checking give const map as default or init value to struct fields (fix #20512) (#20546) - Fix return map index with or_block (#20544) - Cleanup the generic tests (#20553) - Fix `@[deprecated]` attribute for consts (fix #20523) (#20550) - Cleanup in method_call() (#20554) - Disallow `non_opt_array << optvalue` (#20573) - Fix non dereferenced enum in match statements (fixes #10045) (#20591) - Fix .variant smartcast on non-comptime variables (#20575) - Disallow static maps: `mut static x := map[string]int{}` (#20596) - Allow `#define X` and `asm riscv64 {}` blocks in .v files, with `-freestanding` (make embedded usecases easier) - Add cast overflow checks (#20641) - Disallow assigning none to _ (#20646) - Fix checking for option matching with non-option (#20673) - Disallow `(x) := 10` (#20695) - Disallow `none` as match cond (#20688) - Fix comptime ident checking on defer stmt (fix #20719) (#20723) - Add error for `x as Y.field`, suggesting using `(x as Y).field` instead for clarity (#20725) - Disallow sum type holding alias ptrs (#20786) - Optimise out calls to `arg_typ_sym.embed_name()` when there are no errors (#20820) - Fix if branch option type mismatch (fix #20809) (#20830) - Fix auto deref arg when fn expects ref (#20846) - Fix struct field init with generic fn variable (fix #20847) (#20878) - Cleanup in assign_stmt() (#20880) - Check assigning immutable reference struct field (fix #20814) (#20883) - Fix struct field init with generic anon fn (add the test from #18294) (#20888) - Fix checking match branch call expr twice (#20910) - Support `Flags.bit ^ Flags.bit1` and `~Flags.bit` (flagged enums) (fix #20925) (#20929) - Fix some specific interface generic inference within generics struct and method (#20932) - Remove notice when shifting signed int for `@[translated]` (#20935) - Silence "assigning 0 to a reference field" and "uninitialized fn struct fields" notices for `@[translated]\nmodule ...` files (#20938) - Fix missing check for interface cast of option type (#20961) - Silence more warnings for `@[translated]` files (#20964) - Fix comptimeselector passing to generic argument (#20985) - Remove unnecessary string interpolation in deprecation method calls (#21007) - Disallow void return value lambdas in array.map method calls (#21011) - Cleanup and simplify `check_ref_fields_initialized` methods (#21016) - Cleanup and simplify struct processing p1 (#21009) - Add support for deprecation messages for structs and struct fields (#21017) - Cleanup and simplify struct processing p2, extend test (#21025) - Fix undefined reference to interface struct field regression (after #21025) (#21030) - Add test for interface embedding and interface with erroneous implementation (test related to #21030) (#21033) - Disallow `Optional` and `Result` high val in a `for x in low..high {` loop (#21043) - Fix missing incompatible pushval type for chan <- operator (#21040) #### Parser improvements - Fix close_scope() missing, when field.name is `sort` or `sorted` (fix#20436) (#20485) - Check non-generic interface defining generic method (#20545) - vast,ast: output map init update expression (#20574) - Implement `MyEnum.from(1)!` generic static method (#20411) - Fix `MyEnum.from(0)!`, implement `MyFlaggedEnum.zero()` (#20623) - vfmt,parser: keep the original import name in ast.Import, and use it without modifications for paths unders ~/.vmodules - Allow double quotes in `@include` template directives (#20628) - Fn type declaration does not check already registered name (#20732) - Fix global const ordering with string inter literal (fix #20760) (#20770) - Disallow option alias with option parent type (#20769) - Make Scope.find methods more robust, when called on default initialised `scope &Scope = unsafe { nil }` fields (#20774) - Fix parsing of cgen.v, in normal mode, when the table is empty (no files in `builtin` are preparsed) (fix #20606) (#20611) - Fix infinite loop in Parser.sql stmt in `-silent -print-watched-files` mode (used by `v watch`) ( #20873) - Disallow defining map key more than once (#20905) - Fix formatting comptime if expr, after inc expr (fix #20927) (#20931) - Fix for comptime with fully type name (fix #20948) (#20988) - Allow lock prefix instructions and numbered reg in inline asm blocks (#21022) - Add better error for mut variadic fn argument (#21063) #### Compiler internals - v.util: make launch_tool failures more detailed (for the `Text file busy; code: 26` case), bump tool_recompile_retry_max_count from 3 to 7 - v.util: make launch_tool more robust, when multiple `v -b js file.v` commands are run at the same time (all trying to recompile the JS backend program) (#20631) - builder: allow for `./v -freestanding -cc riscv64-elf-gcc -d no_main -no-builtin -no-preludes -showcc -keepc x.v` - pref: support file_notd_freestanding.v + file_d_freestanding.v, remove dependency to `os`, of $ embed_file(), when compiling with -freestanding (#20712) - v.builder: reduce the default noise from successfully rebuilding cached thirdparty object files - pref: allow fetching the photonwrapper .so (for the coroutines) with curl too, or print details for manual download (#20855) - scanner: disallow a shebang line, that is not at the top of a file (#21029) - strings.textscanner: fix off-by-one error in skip method (#21045) #### Standard library - x.crypto.chacha20: speed up the core functionality of the ChaCha20 stream cipher (#20470) - log: enhance log time format setting (#20484) - encoding.csv: add a new utility fn `new_reader_from_file/2` (#20530) - readline: add completion support (#20559) - builtin: add `is_hex()`, `is_int()`, `is_bin()`, and `is_oct()` methods to the string type ( #20540) - builtin: add empty string verification for the new string .is_oct() etc methods, suggested on PR #20540 (#20564) - json: fix struct with option enum field (fix #20597) #20597 - x.json2: fix panic on calling json2.decode of an optional enum (fix #20593) (#20603) - vlib: add a compress.zstd module (#20616) - io: ensure BufferedReader.read_line() returns `io.Eof`, instead of `error('none')` (#20619) - log: add support for l.set_short_tag/1 (#20652) - Update error checking for new error io.Eof (#20656) - io: allow BufferedReader.read_line() to accept custom line delimiters (#20655) - builtin: implement unbuffer_stdout/0 (#20662) - x.crypto: add sm4 module (#20651) - crypto.aes: optimise performance (#20674) - os: add proper process termination with p.signal_term() (#20671) - os: simplify and unify os.join_path and os.join_path_single, and add more tests (#21494) - bitfield: enhance operation with multiple flags (#20683) - os: fix File.read() in JS backends (fix #20501) (#20633) - os: add error_posix() and error_win32() for explicit platform error handling and default behavior (#20694) - log: implement set_always_flush/1 for log.Log, log.ThreadSafeLog and log.Logger (#20698) - x.vweb: error() and simpler redirect(); comptime: a clearer error - builtin: add a string.u8_array() method (#20736) - os: add os.stat() and helpers (#20739) - os: make os.SystemError struct public so the os.error_* functions can be used by other modules ( #20754) - os: refactor to use os.stat and os.lstat instead of unsafe C calls (#20759) - os: make os_stat_test.v more robust to reporting false positives - x.crypto: add poly1305 message authentication code (mac) in pure v (#20752) - encoding.binary: add _fixed variants for the conversion fns, that accept fixed arrays (#20766) - x.crypto.sm4: make sm4 use the encoding.binary _fixed fns (#20773) - builtin: add gc_collect/0, gc_get_warn_proc/0, gc_set_warn_proc/1. Use them to turn off GC warnings by default. (#20788) - builtin: support `-d gc_warn_on_stderr`, to show the GC warnings, without installing a custom warn fn callback - x.crypto: add AEAD ChaCha20Poly1305 algorithm in pure v (#20817) - x.crypto.chacha20: remove deprecated `math.max_u32` in favour of builtin `max_u32`, remove unneceseary bits, reorder (#20838) - json: fix decode struct ptr (#20828) - time: add a .http_header_string() method on Time (#20861) - json2: reorganize encode string (#20862) - vlib: add `encoding.txtar` (port of Go's txtar module) (#20874) - gg: handle dpi change, when moving window to another monitor (#20886) - time: add a tm_gmtoff field to `C.tm` (a BSD and GNU extension) (#20907) - x.json2: add skippable field attr `@[json: '-']` (improve backwards compatibility with the `json` module) (#20892) - time: rename identifiers and parameter names (#20913) - io: add a `string_reader` submodule (#20893) - toml: return an error from toml.parse_file(), when the passed file path does not exist (#20912) - x.json2: fix encoder commas (#20916) - time: microoptimise the Time formatting methods (use custom number->string conversion, instead of string interpolation) (#20917) - x.json2: improve performance of string encoding for unicode special characters and emojis (#20867) - x.json2: minor performance improvement, update benchmark recommendations (#20954) - os: workaround a `-prod -cc gcc` bug, affecting os.open_file (fix #20923) (related to #20872) ( #20960) - cli: add pluralization to err msg, if required number of args is not met (#20971) - os: remove repetitive words in comments (#20981) - gg: fix empty circle in native; http: post_form_with_cookies; veb: print veb action in html errors - io.reader: make read_all constants public (#20997) - builtin: expose gc_disable(), gc_enable(), gc_is_enabled(), in addition to the existing gc_collect() (#21002) - x.json2: improve error message upon missing comma (#20602) - builtin: fix a few grammar errors in builtin.string comments (#21010) - io.string_reader: fix needs_fill_until check (#21005) - builtin: add missing return type to fn signature for C.GC_get_stack_base - x.json2: predefine buffer capacity for encoding to avoid reallocations (#20920) - rand: add PRNG.fill_buffer_from_set/2 (#21037) - sokol.gfx: update the PixelFormat V enum, to exactly match the C sg_pixel_format from thirdparty/sokol/sokol_gfx.h #### Web - net: fix vlib/net/tcp_test.v (since .listen_tcp with af .unix, is now expected to return an error) (#20472) - net: remove unused import in tcp_test.v - x.vweb: add error, when static directory does not exist (#20455) - net.urllib: fix parsing url error, when querypath is '//' (fix #20476) (#20504) - vweb: unify listen address from tcp and print (#20448) - net.unix: make the error messages in unix_test.v more specific (#20537) - vweb: add an optional Context.before_accept_loop/0 method, to make testing easier and more robust (#20538) - vweb: fix routes without results in vweb_app_test.v (#20548) - vweb: make vweb_test.v more robust and faster, by embedding its server as a module - Small fixes and backport changes from vweb (#20584) - net.smtp: implement mail attachment support (fix #19920) (#20640) - vweb: fix quickstart docs in the module's README.md on how to create a new vweb project (#20644) - net.http: add a temporary fix for the intermittent segfault with http.get_ text/1 and `-prod -cc gcc` 13.2.0 (fix #20506) (#20660) - x.vweb: support HTTP 1.1 persistent connections (#20658) - x.vweb: use `$if debug_ev_callback ? {` for the `[vweb] error: write event on connection should be closed` message - x.vweb: add cors middleware (#20713) - x.vweb: add new sessions module (#20642) - net: fix non-blocking read/write (#20438) - net: reduce flakiness of tcp test (#20761) - picoev: renaming, doc (#20567) - x.vweb: add full static host support, for urls ending with /folder/ , where the folder backing it, has `index.html` inside (#20784) - x.sessions: change session Store interface to use results instead of options (#20796) - net: fix function name in split_address doc comment (#20794) - doc: x.vweb static website capabilities (#20808) - thirdparty: update picohttpparser (#20843) - picohttpparser: restore formatting for g_digits_lut, after f09826e (#20844) - x.vweb: fix handling of static URL paths like `/sub.folder/a_folder` (#20863) - veb: a new module veb.auth for authentication logic (tokens, hashed passwords) - veb.auth: make work with any db - net: workaround a `-prod -cc gcc` bug (#20872) - picoev: add more logging of errors (#20558) - picoev: remove fmt off tags (#20569) #### ORM - orm: fix checking invalid recursive structs (fix #20285) (#20491) - orm: fix checking invalid recursive structs in sql stmts (fix #20278) (#20505) - orm: fix orm insert issue if table missing [Issue : #20017] (#20580) - orm: fix orm_option_time_test.v after 2d0ed2c made insert in parent tables with child ones missing fail - orm: insert expressions returning id #### Database drivers - db.sqlite: fix exec_param_many bug (#21008) #### C backend - Fix multidimensional fixed array size expression evaluation (fix #20311) (#20458) - Fix fixed array handling with operator overloading call (fix #20467) (#20469) - Fix C code, generated for generic option fixed array return type (fix #20465) (#20479) - Fix fixed array handling, on generic result return, and on or block (#20492) - Fix generated code for fixed array cast (fix #20454) (#20480) - Change `x.filter(cond).len > 0` to `x.any(cond)`, and `x.filter(cond) == 0` to `x.all(!cond)` ( #20513) - Fix code generation wrong, when '?foo.array or {}' as a 'for-in' condition (fix #20528) (#20542) - Add a necessary clone, when the closure param is string/array with -autofree (fix #20498) (#20557) - Fix wrong cgen, when auto_heap var, is used as a closed over arg in a closure (fix #20208) ( #20566) - Initialize closures in shared library mode (#20630) - Fix interface generic smartcast (#20609) - Support inter-dependent function types (#20638) - Write the profile file out, even upon CTRL-C or kill (#20677) - Fix as cast as selector (fix #20710) (#20718) - Fix method call checking against `none` (fix #20711) (#20717) - Fix interface on multi return func (fix #20720) (#20721) - Fix premature variable release by autofree (#20731) - Fix return with option on orexpr (#20728) - Fix auto str for map with ptr str (#20741) - Remove `ull` suffix, which looks like the cause for the first scanner error in PR#20726 (#20750) - Fix comptime smartcast as receiver on method call (#20749) - Fix unwrap on or-expr, when calling f() ?Type (fix #20756) (#20758) - Builtin,coroutines,cgen: fix using coroutines with boehm GC, by using a stack pointer corrector ( #20771) - Fix interface casting (#20789) - Fix auto_eq for option eq operator overload (#20795) - Fix from_string fn generation missing mod name (#20807) - Fix const fixed array initialization handling (#20812) - Fix unwrapped option selector assigning (#20816) - Fix map methods call with generic types (fix #20827) (#20829) - Fix codegen for a.index/1, where a is []Fn (#20849) - Fix thread return type generation (fix #20836) (#20850) - Fix code generated for anon struct default value (fix #20839) (#20851) - Fix comptime selector of interface (#20876) - Fix multiple fixed array variable init (fix #20895) (#20902) - Ast,checker,cgen: fix generics function with embedded structs, ensure correct link generation in cgen (#20900) - Fix returning option call in non-option fn (#20943) - Fix global initializer of fixed array on gcc (#20934) - Fix comptime `is` condition when using interface (#20952) - Fix const fixed array init with index (#20950) - Fix generic map inferring key and value types (#20959) - Fix missing scope enclosing for const init which needs temp variables (#20973) - Fix fixed array return on fn with option generic return (#20974) - Fix code generated to comptime passed to generic arg (#20994) - Fix match for alias (#21028) - Add ability to mark a global as `@[hidden]` (#21035) - Fix _str name generated for C struct which define str() method (#21042) - Fix for/in codegen when iterating over C structs (#21052) #### JavaScript backend - Fix javascript backend treating u32 as i32 (fix #20499) (#20618) - Fix u16 cast handling in the JS backend (#20620) - Make program_test.v not flaky anymore, so that it is more sensitive to early errors. Fix compilation error for u16.v . Make u32.out match the current reality (the bug will be filed separately) - Fix inconsistent output (u32) in JS backend (#20691) #### vfmt - v.fmt: drop newline in end comments for const (#20672) - Fix alias array no cast init (#20898) - Fix removal of used selective and alias imports in modules in `$VMODULES` dirs (#20977) - Improve submodule type alias lookup; fix formatting of modules in `$VMODULES` (#20989) - Fix type names for casts (#21036) - Insert auto imports after shebang (#21038) - Fix autoimport with shebang and comments above other imports (#21050) - Fix formatting for imports of submodule from module `src` dir (#21060) - tools.fmt: extend exit codes to allow spotting unformatted files next to internal errors (#21058) - Fix parsing of interface with comment above `mut:` keyword (#21062) #### Tools - repl: support executing shell commands on the REPL with `!sh [COMMAND]` (#20496) - repl: fix an issue with `print` and println after the execution of `for` or `if` (fix #20524) ( #20525) - tools: bump too_long_line_length_table to 160, to avoid warnings for just `v check-md doc/docs.md` (most common) - tools: bump too_long_line_length_link to 250, to avoid warnings for very common long links - ci: simplify time_ci.yml, use more descriptive CI job names, for easier judging of CI failures - debug: fix variable dereferencing (#20594) - tools: support setting another SCANNER_MODE=parse_comments in parser_speed.v and scanner_speed.v - testing: fix warning for compiling `./v cmd/tools/vtest.v` - docs: add a section about modules specifics (#20653) - github: add dependabot.yml (#20800) - vtest,pref: add ability to have platform specific _test.v files (#20810) - ci: change spaceface777/cancel-workflow-action to styfle/cancel-workflow-action (#20806) - tools: use the same same skipping logic for the platform specific _test.v files in `v test-self` too (#20815) - tools: make the output of `v check-md .` more informative (#20819) - v.debug: implement tracing hook feature (#20818) - ci: mark db_store_test.v as flaky - ci: add a vtcc step (check that vtcc, continues to be able to compile with v, and v itself can be compiled with vtcc) (#21000) - v.util: simplify vtest (#21013) - vtest-self: add sandboxed packaging case (#21059) #### Operating System support - v.builder: allow for `v -shared -os windows file.v` on Linux/macos (fix #20445) (#20453) - Add windows dll support, fix (#20447) (#20459) - sync: add mutex.try*lock functions for FreeBSD too (#20482) - sync: fix FreeBSD implementation of sync functions (#20483) - os: make os.cache_dir() and os.vtmp_dir() more robust to parallel test executions on windows ( #20495) - builder: replace "-rdynamic" for clang on macos with "-Wl,-export_dynamic" (fix #20510) (#20511) - builder: restore ability to use tcc, without fallback to cc on macos - v.builder: use a more uniq prefix for the generated temporary file names, to further reduce the chances of collision and sporadic CI failures on windows (#20551) - encoding.csv: fix bug in RandomAccessReader, spotted on windows with mingw32 (#20571) - builtin: use `#pkgconfig bdw-gc-threaded` where available, instead of `#pkgconfig bdw-gc` (on FreeBSD) - db.pg: add include and lib paths for PostgreSQL on FreeBSD (#20582) - thirdparty: fix `v cmd/tools/vcompress.v` on FreeBSD - os: fix an error in Process.win_spawn_process, not using stdout pipe in a cmd environment on 32bit Windows (#20613) - testing: retry 1 additional time sporadic silent test run failures on macos - builder: add '-lelf' to linker flags on freebsd (fix #20481) (#20643) - GNUmakefile: use standard default RM make variable to fix MSYS2 env on windows (#20701) - x.vweb: add the missing include for C.sendfile to sendfile_linux.c.v - clipboard: fix notice in clipboard_windows.c.v (#20733) - ci: update macos runners to macos-14, to make use of the much faster m1 instances (#20747) - builder: support musl-gcc on macos - builtin: link to user32 to fix boehm GC compilation on Windows with clang released from the LLVM project (fix #20724) (#20767) - pref: download correct photonwrapper.so for linux (#20783) - ci: improve repo CI robustness, by marking dynamic_template_manager_cache_system_test.v as flaky, and only failing db_store_test.v on !windows - tools.vpm: fix remove command on Windows, add test (#20852) - os: don't check rdev equality on FreeBSD, inside vlib/os/os_stat_test.v (#20885) - sync: support more gcc version specific search locations on linux with tcc ## V 0.4.4 *9 January 2024* #### Improvements in the language - Implement `@[aligned]` and `@[aligned:8]` attributes for structs and unions (#19915) - Update attributes to use new syntax - Update remaining deprecated attr syntax (#19908) - Support `$if T is $array_dynamic {` and `$if T is $array_fixed {` in addition to `$if T is $array {` (#19882) - Prepare for making `-W impure-v` the default (#19940) - Assigning `0` to reference fields now requires unsafe blocks (fix #14911) (#19955) - Unwrap const() blocks - Implement $for comptime T.variants (#20193) - Add `r` and `R` switches for repeating in string interpolation, `'${"abc":3r}'` == 'abcabcabc' ( #20197) - Comptime refactor and cleanup (#20196) - Allow comptime-for to iterate over comptime variables, add `$string` comptime type, cleanup ( #20233) - Unwrap an option value automatically, inside `if o != none {` (#20275) - Complete support for smartcasting to a comptime variable type (#20270) - Improve comptime var checking with `is` operator and smartcasting (#20315) #### Breaking changes *none* #### Checker improvements/fixes - Disallow `$for i in struct.values` and `$for i in enum.fields` (#19845) - Parser, checker: fix var scope in lambda(fix #19860) (#19871) - Change the warning `more than 1000 possibilities in match range` to a notice (#19862) - Fix inability to use multiple `import some modname as _` in the same .v file (fix #19899) (#19900) - Disallow casting strings to pointers outside `unsafe` (#19977) - Disallow directly indexing sumtype and interface, when using as parameters(fix #19811) (#19982) - Fix loop on aggregates of arrays (in match branches) of sumtypes (fix #18548) (#19988) - Disallow indexing mut struct, passed as a fn parameter (#19992) - Enhance err msg for unknown types for comptime `$for` (#20057) - Fix .clone()/.move() with shared maps (#20083) - Fix generics method call with struct short syntax args(fix #20030) (#20100) - Fix unwrap, when generic structs are used as arguments, in uncalled methods (fix #20132) (#20135) - Fix generic fn with generic fn call returning generic map (fix #20106) (#20150) - Cast sumtype to its variant generic type (#20166) - Refactor `string` to `enum` error check, handle `EnumName(string_variable)` too (#20210) - Fix generic array method call with multi-types (#20237) - Remove unnecessary struct ref field initialization checks and notifications at map initializing( fix #20245) (#20251) - Add a notice, for accessing by key, map values, that contain pointers (to use unsafe or an `or {}` block) (#20266) - Fix mismatch checking when a function returns sumtype as an argument (fix #19325) (#20264) - Fix and cleanup uninitialized checks for array initialisers with `len:` (fix #20272) (#20279) - Give an error for `.free()` method calls, when used on fixed arrays (#20320) - Fix type mismatch checking for assignments with generics (fix #20298) (#20327) - Fix too strict checking with generics in assignment type mismatch (fix #20335) (#20346) - Disallow `string` to `voidptr` cast entirely (#20351) - Fix generic method calls with multi generic types (fix #20330) (#20360) #### Parser improvements - parser: fix parsing comments after new attribute syntax - parser: fix failures found with fuzzing (#19873) - parser: deprecate old attribute syntax & update remaining (missed) attributes (#19879) - parser: fix infix expr handling with cast on left side of << operator (#19985) - ast: fix generic structs with multiple levels of generic embedding (#20042) - parser: implement thread returns result and multi_returns (fix #19281) (#20194) - parser: fix formatting struct decl with comments (#20207) - parser: fix formatting enum and interface decl with comments (#20216) - parser: fix fn call with newline opening brace (fix #20258) (#20267) - parser: fix parse_vet_file() with vfmt off/on flag (#20273) #### Compiler internals - scanner: implement support for UTF-32 escape codes in string literals (#19911) - scanner: add new_silent_scanner/0, Scanner.prepare_for_new_text/1, make .ident_char/0, .ident_string/0 and .text_scan/0 public (#20045) - pref: support VNORUN=1, to enable running of tests, vsh files etc (i.e. just compile them, for debugging later) - scanner: fix backslashes followed directly by newline in string literals (fix #20291) (#20296) - scanner: fix escape character handling in character/rune literals (fix #20301) (#20304) - pref: disable the -macosx_version_min clang flag by default (#20297) - builder: remove passing `-fno-strict-aliasing`, for `-prod` to gcc/icc (#20368) - markused: add `-skip-unused` for programs that `import x.vweb` too (do not skip unused routing methods) #### Standard library - json: fix recursive pointer encoding (#19840) - os,picohttpparser,sokol,strconv: prepare for making `-W impure-v` the default (#19846) - os: add fast path to mkdir_all, when the given folder already exists (#19869) - os: ignore empty path segments in `join_path` (#19877) - os: fix bootstrapping for OpenBSD - x.json2: replace deprecated type byte with u8 in the tests (#19909) - vlib: change byte to u8 (#19930) - sync: add a FreeBSD specific version of vlib/sync/sync_default.c.v (#19962) - datatypes: add push_many for doubly and singly linked list + add insert_many for heap (#19975) - datatypes: make `Direction` pub and fix and add tests for `push_many` (#19983) - gg: fn (data voidptr, e &Event) for events, allows methods - vlib: add a `compress.szip` module, deprecate the `szip` one after 2023-12-31 (#20003) - os: create the folder described by `XDG_CACHE_HOME`, *if it is non empty, and it does not exist yet*, when calling `os.cache_dir()` (#20046) - vlib: use the builtin flush functions, instead of the C. ones (#20108) - crypto: add blake2s and blake2b hashes (#20149) - os: fix `mv_by_cp` for directories (#20154) - os: update mv fns, improve performance, add params struct to control overwrite behavior (#20156) - gg: fix overlapping slices in `draw_slice_filled()` (#20182) - json: fix option sumtype handling (#20186) - builtin: add `@[direct_array_access]` to js string trim_right method (#20222) - json2: add encoder support for `time.Time` (#20228) - json2: fix encoding of 💀🐈 etc emojis (fix #20243) (#20247) - json2: make public the generic function `map_from/1` (#20294) - json2: optimise encoding to be faster than cJSON with -prod (#20052) - json2: support sumtype encoding in a more robust way (#20093) - json2: strict module (#17927) - crypto: fix notices/errors for `v -N test vlib/crypto` - crypto: add blake3 hash (#20319) - sokol: fix compiling gg and other graphical examples on OpenBSD (#20333) - csv: Add a sequential reader too (suitable for very large .csv files, it does not read everything at once) (#20140) #### Web - net.mbedtls: use `char` and `usize` types for describing more precisely the C API of mbedtls ( #19837) - vweb: add the mime type for .toml files (#19875) - net.openssl: use actual C values for the SSLError enum (#19945) - vweb: .html('custom_template.html') - vweb: add an optional parameter to the .redirect/2 method, to be able to set the http code for the redirects (#20082) - x.vweb: fix large payload (#20155) - x.vweb: reimplement csrf module (#20160) - net: make net.fionbio and net.msg_nosignal constants public in net_windows.c.v (#20183) - net.http: remove unused `read_set_cookies` function (#20187) - os, net.http.file: add a folder listing to the http static file server, started by file.serve/1 ( #20192) - websocket: enable using an already existing connection (from vweb or another http server) (#20103) - x.vweb: fix fsanitize-address test for SSE, improve documentation on the usage of `takeover_conn` (#20249) - net.http: support `-d no_vschannel` on windows, to fix long waits, while connecting on some systems (#20265) - x.vweb: fix `$vweb.html()` integration in cgen for the newer `x.vweb` module (fix #20204) - net: support only ip and ip6 in net.tcp_listener (#20336) - x.vweb.assets: reimplement assets module for x.vweb (#20280) - x.vweb.sse: reimplement SSE module for x.vweb (#20203) - js.dom: add querySelector[All] and NodeList (#20240) #### ORM - orm: fix code generation for an option time.Time field (#20031) - orm: fix the generated SQL for the "not equal" operator (#20321) #### Database drivers - db.mysql: add support for the FreeBSD name of the mariadb client library (#20039) - db.pg: fix using postgresql on windows, improve instructions for installing it (#20053) - db.mysql: add ability to prepare and execute statements separately (#20146) - db.pg: fix compilation error with the msvc compiler on windows, and add readme (#20326) #### Native backend #### C backend - Fix generic fn returning fixed array (#19885) - Fix arrays alias built-in methods call(fix #19896) (#19910) - Fix generic array initialization (fix #19903) (#19916) - Fix option sumtype auto deref (#19919) - Ast, checker, cgen: fix interface embedded methods call(fix #16496) (#19936) - Fix ref and deref when an interface is used as a function parameter (fix #19947) (#19966) - Fix auto str for interface struct member which implements str method (#19970) - Fix generics call with interface arg (fix #19976) (#20002) - Fix lambda initialization on option struct field (fix #19474) (#19995) - Fix live mode on windows (#20041) - Fix the static from_string method of Enum across mods(fix #20050) (#20068) - Fix `@[if xyz?] fn init() {}`, add tests (#20096) - Fix assignment to the elements of an array of fixed arrays (#20133) - Fix mutable comptimeselector usage (fix #20027) (#20134) - Fix generics chans select (#20159) - Fix string interp with zero characters (fix #20199) (#20200) - Fix interface eq method with option and ref (fix #19441) (#20201) - Fix infix expr in method of mut receiver variable (#20225) - Fix cgen for thread wrappers, when spawning fns with with anon-fn array args and mut interfaces ( fix #19425) (#20241) - Fix fixed array return when returning fixed array initialization (#20262) - Fix function generated code, when returning from match (#20263) - Fix in expression with mut and ref (fix #20268) (#20271) - Fix initialization of const string arrays on msvc (fix #20287) (#20289) - Fix code generation when 'in array init' is used as an if condition (fix #20300) (#20302) - Escape table names (fix #20313) (#20322) - Add missing clear method for generic maps (#20340) - Fix auto unwrapping option fn type (#20332) - Fix option initialization with default struct initialization to not be `none` (#20349) - Fix auto str for arr options with possible circular reference (#20354) - Fix code generation when the function returns mut fixed array (fix #20366) (#20367) #### vfmt - vfmt: automate transition from the old `[attribute]` to the new `@[attribute]` syntax (#19912) - vfmt: remove empty `__global()` (#20004) #### Tools - tools: fix already installed detection when running v install --once without args (#19838) - compress.gzip: change the endianness for validation to conform to the gzip file specification (fix #19839) (#19849) - tools: support `v doc -run-examples math`, to ensure that all `// Example: code` doc comments are working (#19852) - Fix `v help` in the prebuilt v executables from the zips in the releases - ci,tools: remove skips for the wasm backend, since binaryen is not required anymore (#19883) - tools.vpm: support again `http` installs, when installing from an url (workaround) (#19914) - tools.vpm: improve version detection of installed modules (#19933) - tools: fix `v up`, by not deleting `./v` when missing a `.git` folder (#19965) - tools.vpm: fix installing of modules with conflicting names, extend tests (#19961) - tools.vpm: evaluate dependencies earlier to fix potential recursive install loop (#19987) - tools.vpm: add support for ssh and hg version installations (#20125) - tools: simplify and remove redundancies in vshader.v (#20161) - ci: add new workflow, for doing the slower tests in vpm specifically with `-d network` (#20177) - tools.vpm: improve detection of already parsed modules (#20223) - scanner: change `-d debugscanner` to `-d trace_scanner` for uniformity with the other tracing options, described in CONTRIBUTING.md - v.pref: support a `-n` option, silencing only notices (#20331) - ci: add vsql to v_apps_and_modules_compile_ci.yml too (#20341) - ci: fix the workflow for Vinix, using the rules in its own .yml file (#20371) - Support -? as alias to -help (implement #20355) (#20358) - vdoc: filter testdata and tests folders by default, reduce filesystem stats calls #### Operating System support - os: small cleanup in the FreeBSD branch of os.executable/0: use fixed array for the sysctl params, instead of allocating a dynamic one (#20353) - os: improve os.executable() on OpenBSD (#20356) - v.util.diff: support OpenBSD's default `diff` tool (#20369) - os: fix os.open_file/3 `wb` mode creation of text files containing crlf on Windows (#20101) - os: fix File.tell for files > 2GB on windows, by using C._telli64(f.fd) (#20072) #### Examples - encoding.xml: make functions public, add documentation, tests, fix attribute parsing for self-closing tags (#19901) - examples: show how to turn on CORS in a vweb server app - examples: serve the wasm mandelbrot project using a v web server (#19937) - examples: increase the resolution of the generated image in examples/wasm/mandelbrot - docs: update null convention in ORM example, since `@[nonull]` is no longer needed (#20286) - docs: add an example of a nullable ORM field (#20292) - example: add a path finding algorithm visualizer using gg (#20060) - examples: add an even smaller gg usage example, demonstrating how to always show the builtin fps counter, and how to avoid importing gx ## V 0.4.3 *11 November 2023* #### Improvements in the language - A new `encoding.xml` module with parser, validation, entity encoding, unit tests (#19708) - Better couroutines support (IO, networking) - Allocations in vweb apps reduced by 80% - Implement `@VCURRENTHASH` to replace `C.V_CURRENT_COMMIT_HASH` (#19514) - int => i64 on 64 bit, i32 on 32 bit (start of the transition) - Fix new int type promotion rules and cleanup native gen() (#19535) #### Breaking changes - `Request.cookies` map has been deprecated. Replaced with `Request.cookie()` and `Request.add_cookie()`. - Stricter rules for C types (they always have to be declared now) #### Checker improvements/fixes - Turn the option/result split warning into an error - Turn propagation warning into an error (finishes the option/result split) - Fix fn call with option call argument in autofree mode (#19515) - Bring back pascal case check for aliases - C.xx = C.yy aliases - Allow casted integral types in match ranges (#19572) - Warn about byte deprecation, when used as a fn parameter (#19629) - Allow size of fixed array to be integral casts (#19663) - Fix generic array append (#19658) - Check error of implementing other module private interface (fix #19620) (#19688) - Extend byte deprecation warning to array init types (#19671) - Extend byte deprecation warnings to return types (#19668) - Fix negative cap, len checks in array init (#19694) - Turn warning for var and param module name duplicates into error (#19645) - Fix closure in if guard, including with multi_return (#19765) - Fix comptime enumdata value property access (#19768) - Fix `field ?&Type` without default value (#19786) - Avoid nil assign to option var (#19746) - Allow for a shared variable to be whole reassigned (keeping the same mutex state) (fix #15649) ( #19751) #### Parser improvements - Fix assigning static method to anon fn (#19499) - ast: fix formatting a struct declaration with a nested struct (#19592) - Add `set_all` + `clear_all` methods to `[flag]` enum bitfields (#19717) - ast: reduce cost of frequently called functions by using constants (#19733) - Warn on unused imports, even when they are declared via `import math { sin, cos }` (#19738) - ast: add missing docstrings for the public fns in vlib/v/ast/types.v (#19752) - Give a friendly error when misusing if over $if (#19810) - Add multiple struct attributes error for new attribute syntax #### Compiler internals - checker, builder, pref: support `-dump-defines -` to help explore all the available user and system defines for a given program (#19576) - pref,builder: add support for `-macosx-version-min 10.2` and `-macosx-version-min 0` (with default of 10.7) (#19626) - pref: fix unintended file extensions in default output names, allow for `v run file.c.v` (#19745) - transformer: fix using a constant, instead of a fn parameter with the same name (fix #19766) ( #19773) - maps: add maps.merge() and maps.merge_in_place() generic utility functions (#19776) - coroutines: only attempt to add/remove roots when GC is on. - markused: cleanup in mark_used(), use robust index names, instead of the much more brittle integer values (#19543) #### Standard library - builtin: add an `unsafe { a.reset() }` method, for quickly setting all bytes in an array to 0 - math.fractions: use operator overloading and deprecate old functions (#19547) - gg: fix the alignment of the bottom border of draw_rounded_rect_empty on macos and linux - crypto.bcrypt: fix bcrypt failure for valid pass and hash (fix #19558) (#19569) - sokol: update sokol to the latest version - builtin: fix sizeof(C.BOOL) (windows specific) (#19589) - math.big: fix incorrect division with negative numbers (fix #19585) (#19587) - os: add a convenient way to ignore certain system signals (#19632) - os: fix os.ls(folder) on windows, when a protected folder can not be opened (#19647) - os: add a convenient way to ignore certain system signals (#19639) - crypto.sha: fix calculating the same hash values when .sum() is called several times for sha1/256/512 (fix #19696) (#19697) - crypto.md5: fix calculating the same hash values, when .sum() is called several times (#19703) - os: add a new function `execute_opt` (#19723) - os: add os.page_size() (#19770) - os: implement os.fd_is_pending/1, os.Process.pipe_read/1, os.Process.is_pending/1 (#19787) - builtin: copy min/max integer values consts from `math` to builtin so that the entire math module doesn't have to be imported(#19809) - json2: add support for nested structs (#19579) #### Web - vweb: add mime type support for static .md files - net.conv: add varinttou64 and u64tovarint functions, for the variable unsigned integer encoding, described in rfc9000 (for QUIC) (#19568) - net.http: support passing on_running, on_stopped, on_closed callback functions to http.Server{}, as well as show_startup_message: false. (#19591) - net: fix handling of spurious wake-up signals, lost when calling select() in mbedtls and openssl ( continue on C.EINTR) (#19600) - net: use conv.hton* consistently, instead of `$if tinyc { conv.hton16(port) } $else { u16(C.htons(port)) }` - net.http: support passing an HTTP proxy server in http.fetch (#19606) - net.http: add a retry mechanism to http.fetch(), when the socket inevitably errors (#19660) - wasm: implement inline assembly (#19686) - net.http: increase max_redirects to 16 (#19743) - picoev: implement raw mode (#19771) - flag,json,net: handle C calls in .v files (part of enabling `-W impure-v` as default) (#19779) - net.http: add socks5|http(s) proxy support [Linux] (#19676) #### ORM - orm: add null handling and option fields (#19379) - orm: make is_null/is_not_null unary ops; don't bind null in where (#19635) #### Database drivers - pg: handle C calls, move to .c.v files (#19739) #### Native backend - native: support `-no-builtin` (generate executables < 1KB Linux with `v -no-builtin -b native examples/hello_world.v`) - native: use i32 instead of int #### C backend - Fix printing fixed array of options (#19479) - Fix struct field of fixed array init (fix #19483) (#19487) - Fix struct init with multi option fn type (#19491) - Ast, native, cgen: add support for `$if native {}` (#19500) - Fix maps with i32 keys - Fix for c stmt with option or result calls (#19641) - Fix infix op when handling comptime selector (#19691) - Fix array contains method with interface(fix #19670) (#19675) - Reduce expense in repetitively called functions by using consts (#19732) - Fix closure parameter judgment when var cross assign inside anon fn(fix #19734) (#19736) - Only generate free in wrapper for spawn and not go (#19780) - Fix g.obf_table data missing(fix #19695) (#19778) - Fix closure variable in smartcast (#19796) #### vfmt - Remove additional line breaks after call_expr before params struct args (#19795) - Fix map value alignment when using keys with uft8 symbols (#19689) - Align ternary expressions in const blocks (#19721) - Respect range index expressions in match branches (#19684) - Respect raw strings in `$embed_file(r'/some/path')` expressions (#19753) - Fix formatting of struct field with default value and new attr syntax (#19683) - Recognize or blocks in call args (#19690) #### Tools - all: add support for `@LOCATION`, for more convenient logging/tracing, without needing to combine `@FILE`, `@LINE` at runtime (#19488) - benchmark: add new methods b.record_measure/1 and b.all_recorded_measures/0 (#19561) - ci: update c2v workflow, translate doom on macOS (#19562) - strings: add Bulder.write_decimal/1 method (write a decimal number, without additional allocations) (#19625) - testing: add temporary file hash to prevent accidental collisions with test file binaries (#19710) - ci: compile VTL and VSL in their own CI job, with `VFLAGS=-no-parallel` - tools: fix windows install of an already existing module with vpm (#19761) - tools: use `VPM_NO_INCREMENT` env var to skip dl count increment when testing vpm (#19756) - tools.vpm: improve handling of urls that end with .git (#19758) - tools: fix resolving external dependencies in vpm, add test (#19772) - tools: cleanup and simplify vcreate, for upcoming fixes and features (#19794) - tools: improve error messages, add color coding and debug logging (#19781) - tools: fix `v build-tools`, make `v test` more robust (#19803) - tools: add parse_query to vpm (#19814) - ci: add macos arm64 binary release (#19823) - Require the presence of a `v.mod` file, to install external urls via vpm (#19825) - vcreate: fix `v init` with project names containing dashes (#19619) #### Operating System support #### Examples - tests: workaround name conflict, causing false positives with msvc on windows, when both tests were executed at the same time (locked executable) ## V 0.4.2 *30 September 2023* #### Improvements in the language - Short lambda expressions like `a.sorted(|x,y| x > y)` (#19390) - Support `-os plan9`, `$if plan9 {`, and `_plan9.c.v` (stage 1 for plan9) (#19389) - fmt: simplify the processing logic for removing inline comments (#19297) - Align the custom values of the enum fields (#19331) - Do not warn/error for `import flag as _` - Keep anon struct decl fields in interfaces (#19461) - Support -N, turning all notices into errors, to ease the process of finding places that may need attention/correction #### Breaking changes - Remove inline comments (#19263) #### Checker improvements/fixes - Disallow module name duplicates in local names (#18118) - Check enum fields with duplicate value (fix #19309) (#19310) - Disallow alias ptr cast of a map value (#19336) - Require `else` branch in `[flag]` enum match (#19375) - Disallow assigning pointer values to option struct fields (#19380) - Fix generic comparison for conditional assignment (#19401) - Allow using ! and ~ on aliased bool and integral types (#19403) - Warn -> error for uninitialized ref fields - Parser, checker: allow lambdas anywhere anonymous functions are expected (#19436) - Allow for `each(a, |x| println(x))`, i.e. using lambda expressions, when expecting `fn (x int)` - Check fixed array init with default expression (#19472) - Allow for `const source = $embed_file(@FILE).to_string()` - Fix C.type in imported modules #### Parser improvements - parser: fix fixed array with eval const size (#19269) - parser: disallow using `sql` as name (#19298) - parser: fix `;` support for `module x;` - parser: fix fixed array of option values (`_ := [10]?int{}`) (#19392) - parser: fix assigning with in another module sumtypes 2 (#19415) - Support `;` statements, allowing for oneliners like `./v -e 'import os; println( os.ls(os.args[1])!.sorted(a > b) )' vlib/math` (#19345) - v.ast: improve Stmt.str(), showing more details about ast.Block, ast.DeferStmt, ast.ForInStmt, ast.GlobalDecl #### Compiler internals - pref: support `-fast-math`, passing either -ffast-math or /fp:fast (for msvc) to the C backend, and `$if fast_math {` to detect it at comptime - parser, transformer: fix transformer.infix_expr() and cleanup parse_types.v (related #19269) ( #19276) - pref,builder: support -use-os-system-to-run to workaround segfaults using not fully updated xcode command line tools - v.builder: fix compiling code, that imports modules from both `src/modules` and `modules` (#19437) - os, v.builder: show more details, when a program ran by `v run file.v`, exits by a signal (fix #19412) (#19471) #### Standard library - math: speedup the pure V math.pow implementation for non-fractional powers (#19270) - math: add more C. fn overrides, for the default C backend (speed up examples/path_tracing.v) ( #19271) - time: add `MMM` support for parse_format() (#19284) - os: include sys/sysctl.h on FreeBSD to avoid implicit definition of sysctl function (#19293) - crypto.md5: change the Digest.write return type, from `?int` to `!int` (#19311) - v.help: use os.executable() instead of `@VEXE` as an anchor, so `v help` will work more robustly. - toml: fix custom `to_toml` for complex structs (#19338) - vlib: add net.http.file, allowing for `v -e "import net.http.file; file.serve()"` (#19348) - vlib: remove functions and fields, deprecated before 2023-03-20 - toml: fix toml encoding of complex types (#19408) - arrays: add a partition function, that splits a given array, based on a criteria, passed as a callback fn (#19417) - toml: add decoding for struct fields of type map[string]T (#19447) - arrays: add arrays.each, arrays.each_indexed, and tests for them - encoding.html: implement `unescape()` (#19267) #### Web - net.http: fix http.fetch(), without explicit method (default again to .get, not to .acl) - net.http: default explicitly to Method.get for http.Request and http.FetchConfig too - examples: add examples/fetch_ip.v, showing how to contact http://ifconfig.co/json and parse the result - net.http: fix post error with https on windows (#19334) - net.ssl: implement SSLConn.peer_addr() (#19333) #### ORM - orm: add `references` attribute to allow foreign key declarations on fields (#19349) - orm: support different foreign key types, not just an integer id (#19337) - orm: add support for V enum struct fields (#19374) - orm: quote table and field name in `[references]` (#19387) #### Database drivers - db.pg: allow postgres connection using service definitions (#19288) #### Native backend - native: make native tests pass on windows; refactor PE file generation (#19140) - native: parse dll files to resolve extern symbols (#19433) #### C backend - Fix printing struct with thread field (#19320) - Fix the logic around the definition of VNORETURN and VUNREACHABLE (less warnings on FreeBSD) ( #19316) - Add support for `-d trace_cgen_stmt`, document it in CONTRIBUTING.md - Fix printing smartcast interface variable (fix #18886) (#19372) - Fix interface with multiple embedded fields (#19377) - Fix channel of interface (fix #19382) (#19383) - Fix fixed array of option type default (#19397) - Fix interface with option field (#19434) - Fix promoting an alias typed value, to a sumtype of the alias's base type (fix #19407) (#19423) - Remove the special plan9 support code, treat it instead as a posix system in cheaders.v (#19445) - Fix printing slice of fn call string (#19450) - Fix `type VType = &C.CType` (#19452) - Fix array of fns index call with direct_array_access mode (#19460) #### Tools - bench: a new bench/ directory for language benchmarks - ci: test the pure V math versions without .c.v overrides on the CI too (#19292) - github: add automatically info about voting to all new issues (#19351) - tools: add -E flag to `v test-parser`, that will show the partial source that caused the parser to fail with `-no-builtin -check-syntax file.v` - ci: bring back gitly - github: improve the voting message for issues (#19448) - vcreate: update templates, add `lib` (#19444) #### Operating System support - builtin: use `libgc-threaded` on FreeBSD, to get the threaded version of libgc (#19294) #### Examples - examples: add more .obj files for 06_obj_viewer (#19406) ## V 0.4.1 *3 September 2023* #### Improvements in the language - Pure `array.sorted()` and `array.sorted_with_compare()` methods, that do not modify their receivers (#19251) - UB overflow has been removed - Implement `Enum.from_string(name string)` for converting strings to enum values (#19156) - Disallow casting string to enum, suggest using Enum.from_string() instead (#19260) - Use autocasting in complex conditions (#18839) - Allow alias as fixed array on return (#18817) - Do not allow uninitialized function pointers - Fix compiling V programs with latest clang 16 on windows (clang 16 is stricter than clang 14) ( #19095) - Fix anonymous struct with default expr (#19257) - Allow using consts as enum values (#19193) - `@[attr]` syntax to replace `[attr]` (`[]` is used for too many things). Most likely to be replaced with `@attr()` in the future. - Allow `none` for not first values on map initialization (#18821) - Make all .trace() methods generic on the type of the passed expression #### Breaking changes - `arr[1..4]` now requires `unsafe` if the slice can modify the original immutable array. #### Checker improvements/fixes - Disallow assigning `nil` to struct fields (#18725) - Use autocasting in complex if conditions (#18753) - Disallow invalid prefix on left side of assign stmt (#18750) - Allow no return in compile_error else block (#18758) - Fix interface param resolution (#18780) - Add an error for `$tmpl` function type mismatches (#18826) - Disallow voidptr cast to struct (#18845) - Fix type checker on auto deref var (#18842) - Check generic sumtype declaration (fix #18741) (#18865) - Fix closure with inherited sumtype variable (#18894) - "v -line-info" for a quick run to fetch info about objects on one line - Make sure vweb actions return vweb.Result - Do not allow modifying immutable vars via arrays with refs - Support `@STRUCT` in static methods - Fix generic struct field init recursively (related #19014) (#19025) - Fix struct field fntype value call (#19067) - Explicitly disallow creating type aliases of `none`, i.e. `type Abc = none` (#19078) - Fix assigning an array slice (fix #19120) (#19137) - Fix assigning array slice in struct init (#19150) - Check enum static from_string arguments errors (#19163) - Disallow taking the address of consts with int literal values (#19160) - Check struct embed with wrong position (#19245) - Optimize out needless string interpolations from the most common case in `Checker.expr_or_block_err` - Check error for or_expr inside infix expression (#19213) - Disallow `thread` as var name (#19174) - Check error for sumtype in array (#19183) - Disallow an empty `chan` type (#19167) #### Parser improvements - Change warn to error, for const names with upper letter (fix #18838) (#18840) - Disallow declaring static functions as method receivers (#19007) - Disallow having builtin type as type names for `enum`, `sum type` and `alias` (#19043) - Support `const x := 123`, to make extracting locals as constants less annoying while prototyping - Fix struct field fn type with default value (fix #19099) (#19106) - Fix `for i++; i<10; i++ {` (fix #18445) (#19035) - Fix fn return alias of fixed array (#19116) - Fix generic struct init (Stack[&Person]{}) (fix #19119) (#19122) #### Compiler internals - pref: make -autofree work without -gc none - builder,pref: allow thirdparty objects compilation with CPP compiler (#19124) - scanner: fix string interpolation with nested string interpolation in inner quotes p. 3 (#19121) - scanner: error early on an unsupported escape sequence in a string, like `\_` (fix #19131) ( #19134) - v.token: add inline next_to() and cleanup related calls (#19226) #### Standard library - eventbus: add generic support for event name (#18805) - readline: add support for ctlr+w and ctrl+u shortcuts (#18921) - strconv.atoi: fix string.int() returning numbers for non number characters (fix #18875) (#18925) - builtin: reduce the number of array allocations for consts in all V programs (#18889) - builtin: move array.data to the top of the struct - os.notify: implement the kqueue backend for notify.FdNotifier (#19057) - vlib: add a new module `builtin.wchar`, to ease dealing with C APIs that accept `wchar_t*` ( #18794) - arrays: add more util functions and tests for them - find_first, find_last, join_to_string ( #18784) - vlib: use sync.new_mutex() consistently for initialising all vlib structures containing mutex fields - crypto.pem: add a static method `Block.new`, to replace `new` (#18846) - crypto.pem: add decode_only and general improvements to decoding (#18908) - log: improve the most common use case, it's no longer necessary to create a `Log` instance ( #19242) - crypto.sha512: make the new384/0, new512_256/0, new512_224/0 functions public - json: fix option alias support (#18801) - time: fix `parse_format` with `YY` (#18887) - math.big: allow bitwise ops on negative signum (#18912) - math.big: make is_odd public and add test cases (#18916) - math.big: add checked division methods (#18924) - math.big: add `isqrt_checked` and standardize error format (#18939) - sokol: use GLCORE33 on linux - os,term.termios: add termios.set_state/2, state.disable_echo/0, use them in os.input_password, to fix `v -os wasm32_emscripten examples/2048/` - gg: implement Android specific APK asset loading for the `create_image` function (#19015) - sync: make sync.Direction public (#19047) - time: store time with nanosecond resolution in time.Time, deprecate Time.microsecond, add utility methods and tests (#19062) - time: add a format_rfc3339_nano() method to time.Time - time: add 'i', 'ii' in custom_format() for 12-hours clock(0-12-1-11) (#19083) - gg: expand the `-d show_fps` background, so fps>100 will not overflow it - Math.big: restore gdc_euclid, use it for smaller numbers, fix bench_euclid.v . - Add new generic `arrays.uniq`, `arrays.uniq_only`, `arrays.uniq_only_repeated`, `arrays.uniq_all_repeated`, `arrays.distinct` - builtin: add support for `-d builtin_writeln_should_write_at_once` and `-d builtin_write_buf_to_fd_should_use_c_write` (#19243) - builtin: always show the assert message, if it was defined in the source, in non test programs too (fix #19240) - time: check if a day is a valid day of its month (#19232) - toml: Add generic automatic decoding and encoding of simple structs, when they don't implement custom methods (#17970) #### Web - http: Request.host - net.ftp: fix dir() for file names, which contain spaces (fix #18800) (#18804) - net.http: make listener public, and add addr in Server struct (#18871) - net.http.chunked: return `!string` on decode (#18928) - net.conv: rename functions to match other langs, making them easier t… (#18937) - wasm: remove dependency on thirdparty/binaryen, webassembly backend rewrite (#18120) - wasm: add a -wasm-stack-top flag to compiler (#19157) - net.mbedtls: add SSLListener to allow creating SSL servers (#19022) - picoev, picohttparser: reimplement in V (#18506) - vweb: fix parsing of form fields, send with multipart/form-data (by JS fetch) - vweb: make vweb route paths case sensitive (#18973) - net.mbedtls: have shutdown close accepted connections too (#19164) - http: add support for stream connections, and custom .on_redirect, .on_progress, .on_finish callbacks to http.fetch() (#19184) - vweb: add a user_agent utility method to the vweb context (#19204) - vweb: avoid the controllers having to be defined in specific order (#19182) #### ORM - orm: fix inserting sequential values (id=0), in tables with an i64 primary field (#18791) - Add OR in where on update and delete (#19172) #### Database drivers - vlib: remove deprecated `pg`, `mysql`, `sqlite`, `mssql` modules. Leave only the `db.` prefixed `db.pg`, `db.mysql` etc - db.mysql: add the exec family of methods (#19132) - db.sqlite: add exec_param_many and exec_param methods (#19071) - db.sqlite: make functions return results, breaking change (#19093) #### Native backend - native: move functions out of amd64.v (#18857) #### C backend - Fix selector code to use interface method table on closure when needed (#18736) - Fix nested or expr call (fix #18803) (#18807) - Ensure that `<<` and `>>` has higher precedence in the generated C code, than arithmetic operations (diff between C and V precedences) (#18814) - Fix cross assign with aliased array (#18830) - Fix generated code for returning generic result/option to comptime var (#18834) - Fix option map with fn type value (#18849) - Fix returning an option tuple - `fn f() ?(int,int) { return g() }` (#18851) - Fix printing multiple fixed array (fix #18866) (#18879) - Fix infix expr with number overflow (fix #18905) (#18936) - Remove \r for consistency (#18962) - Allow dump(unsafe{nil}) and dump(voidptr(123)) in the same program - Implement fixed array of threads wait() (#19032) - Fix an error with ptr interpolation (fix #19048) (#19049) - Fix spawn call fn struct field(fix #18862) (#19096) - Fix bootstrapping on older macOS Catalina - Fix alias of array method call(fix #19125) (#19129) - Simplifications and clean up. - Fix mixed fixed array and array initializing (#19246) - Fix array sort with fn call parameter (fix #19220) (#19221) - Fix generic struct with option fn field (#19218) - Fix comptime assign with generic result return type (#19192) - Fix match with comptime if expr in branch (#19189) #### Tools - ci: add v-analyzer builds (#18835) - ci: cleanup more the contents of the generated v_linux.zip, v_macos.zip, and v_windows.zip, use -skip-unused - tools: fix vcomplete for zsh (#18950) - tools: support a toc for projects, with single exposing module, in `v doc` (#19001) - Add support for `v should-compile-all -c examples/`, which will delete all the produced executables at the end - vgret: add install commands for ubuntu and arch to doc string (#19247) - fast.v: add favicon to the html produced by fast.v - vpm: implement multithreading (#19208) - Make performance_compare.v more robust and easier to use, by allowing `v run cmd/tools/performance_compare.v` too - Improve oldv windows support, make it use -municode for windows builds, make it support cmd.exe - Make repeated runs of `oldv SAME_COMMIT -c "./v file.v"`, not use the network at all - Help: add link to the TESTS.md at the bottom of `v help test`, run CI checks on help markdown files as well - v.builder: show the number of files, types, modules, when a program is compiled with -stats - Improve the output of parser_speed.v and scanner_speed.v ## V 0.4 *1 July 2023* This release has a combined changelog from 0.3.1 to 0.3.5. You can read it here: https://github.com/vlang/v/blob/master/changelogs0.x/0.4.md ## V 0.3.5 *29 June 2023* #### Improvements in the language - **Coroutines with a scheduler**. Only Linux/macOS for now, requires `-use-coroutines` and `coroutines.sleep()` instead of `time.sleep()`. They work with IO and net, but not with GC for now. - `spawn` now spawns system threads, `go` spawns coroutines. - Static type methods: `Foo.new()` to replace factory functions like `new_foo()`. - Smartcasting with complex conditions: `if sum_type is Foo && !sum_type.is_info && get_name(sum_type.info.name) == 'foo' `. - Functions can now return fixed size arrays. - Enum values now can have attributes. - Generic functions as function parameters are now supported: `fn f[T](x T, i int, f_ Fn[T]) T { `. - Anonymous structs can no longer have attributes. #### Breaking changes - `byte` deprecated in favor of `u8` (`byte` is automatically converted to `u8` by vfmt). #### Checker improvements/fixes - Disallow `Result` type aliases (`type Foo = !Bar`) and `Result` in maps (`map[key]!Type`). - Add a missing check for taking address of literal value member. - Fixed map initialization for maps with option values. - Allow `a << none`, where `a` is `[]?&int`. - Disallow multiple `else` branches in a match. - Fix index expression with sumtype of array types. - Remove hardcoded check for function calls for `C.stat`, `C.sigaction`, etc. - Fix multiple embedded external module interface. - Fix missing check for diff type on map value declaration. - Simplify error handling in the checker (#18507). - Option alias fixes. - Fix alias to struct ptr on struct init. - Sumtypes can no longer hold references. - Fix a bug checking generic closures. - A hard to reach limit of 1 million iterations for resolving all generics. - Fix missing check for unwrapped shift operation. - Fix enum max value validation. - Add a missing mutability check for `array.delete` calls. - Disallow `_ = <- quit`. - Disallow type matching with primitive vars. - Warning instead of error for unnecessary brackets in if/match. - Include import aliases when checking for import duplicates. - Fix inferring generic array type in nested call. - Allow casted `enum val` and `const` as fixed array size. - Disallow multiple return values in const declarations. - Fix contains() with array of interfaces. - Disallow mut for blank idents. #### Standard library - json: Enum value string serialization supports `[json:'alias']` to change its string values. - Struct fields can now be skipped during JSON/ORM serialization via `[json:'-']` and `[sql:'-']`, in addition to `[skip]`. This allows having custom behavior for different serialization methods. - builtin: heap usage API (gc_memory_use() and gc_heap_usage()) - math.big: refactoring, gcd fixes/improvements, overflow fixes, `mod_inverse`. - flag: fix finalize with multiple shortargs. - runtime: add new functions total_memory/0 and free_memory/0. - time: small cleanup of parse_iso8601 comments, make the C.strftime declaration forwards compatible - stbi: allow customization of number of channels in `stbi.load()`. - stbi: add a `resize_uint8` function for resizing images in memory. - time, x.json2: improve iso8601 time decoding. - builtin: zero out internal map/array pointers on m.free(), to reduce the work for the GC mark phase for non escaping maps/arrays, used in hot loops. - time: add more detailed error descriptions, add custom format parsing with time.parse_format. - sync: add Mutex.destroy and RwMutex.destroy methods. - datatypes: add Bloom filter. - rand: add missing rand.u16(), update doc comments, add test. - builtin: speed up string methods with vmemcpy instead of `for` loop for copying data. #### Web - The builtin websocket library is now thread safe. - Enhanced builtin csrf protection in vweb. - vweb: ability to set and get values on vweb.Context. - vweb: support for host specific static files. - vweb: host option added to controller, and a new host attribute. - vweb: middleware docs improved; same with docs for `[vweb_global]` and `shared`. - vweb: return 404 on file not found. - net.http: copy IANA's list of methods to the http.Method enum. - net.conv: use a pure V implementation instead of C.hton etc. - net.html: `get_tag()` methods to find first tag occurrence. - net.html: fixed text parsing for inline tags. - net.html: fix parsing of nested quoted strings in code tags. - picoev: FreeBSD support. #### ORM - Fixed a foreign key bug that could result in an extra insert. - Comptime bug with `[skip]` and `[sql:'-']` fixed. - Checker error for unsupported field types. - Allow structs without the id field, more flexible primary keys. - Improved docs and examples. - Uninitialized structs are no longer inserted into related tables. #### Database drivers - mysql: TIMESTAMP support. - mysql: allocate memory for each string and blob dynamically depending on its value length. - mysql: add the ability to commit transactions. #### Native backend - Refactoring, splitting large files into multiple. #### C backend - Fix code generation for generic unions. - Fix `[N]chan` (fixed arrays of channels). - Fix nested fixed array instantiation. - Fix fixed array of map. - Fix stringification of usize struct fields (before, they were treated as 32 bit *signed* numbers). #### Comptime - A new `$res` comptime function to get returned value in defer block (#18382). - Fix comptimeselector option propagation. - A mutability check for comptime assignments. - Fix comptime assigning to sumtype or indexexpr. - Make comptime calls work with or-block. #### Tools - A new VPM site: vpm.vlang.io. A better design, discoverability of packages, descriptions, most downloaded packages etc. - vpm: installation of mixed modules. - `v ls --install -p D:\path\vls.exe` to install a local vls executable. - vdoc: highlight comments with gray color. - vet: allow vetting files with global variables. - Make util.launch_tool/3 more robust, by recompiling V tools always in a known current working folder. ## V 0.3.4 *30 Apr 2023* #### Breaking Changes The following changes may break compilation of existing code or change behavior at runtime: - `json`: enums are serialized as strings by default, `[json_as_number]` attribute can be used for the old behavior. If you are serializing enums to JSON in your application, then you will need to add the `[json_as_number]` attribute to keep the old behavior! - Variable shadowing has been completely banned (previously variable names could conflict with module names). #### Web - vweb now supports live page reloading. The web app is instantly updated in the browser (no need to refresh the page) every time a **.v** or a **.html** file is changed. - vweb is now significantly faster and more stable under load, due to a new multithreaded worker pool, which is much more efficient at spreading the workload among all threads equally. - vweb now supports middleware. - vweb now supports controllers. It's now possible to have multiple app structs to better separate logic. - vweb now supports overridable `.not_found()` method for custom 404 pages in vweb. - vweb now uses database pool. - Fixed multipart form parsing in vweb. #### Backends - A new pure WASM backend, based on binaryen, a WASM `builtin` module, and a pure V WASM serialization library. - Lots of fixes and new features in the native backend, including making codegen logic platform independent. - Now code generated by the С backend, can be compiled by a C++20 compiler. - C backend does not generate unused interface functions now. #### Compiler CLI - `v share file.v` for sharing code via the playground. - `v up` speed up for when it hasn't been run for a long time (**vc/** bootstrapping has been optimized). - `v init` no longer overwrites existing `src/main.v`. - `v self` now uses a faster TCC backend on macOS (Intel/Apple Silicon), just like on Windows/Linux. - A new command line flag `-e` for running short V programs on command line: `v -e "println(2+5)"` ( works just like in Perl). - A new `-ldflags` option, in addition to `-cflags`. Works just like LDFLAGS in C. #### ORM - All ORM queries now return `![]` (`Result` of an array). This allows handling/propagating DB errors and simplifies working with ORM (one way). - Many ORM improvements: type checks for `limit/offset/order by/where`; support of reference objects in `insert`; struct fields can be used with `limit/offset`; `Connection` interface. - ORM now supports the `like` operator: ```v syntax-ok users := sql db { select from User where name like 'Bob%' } ``` - A new `-d trace_orm` option to see all SQL queries generated and used by V ORM and `-d trace_pg_error` to trace PG errors. #### Standard Library - Added new `termios` module. - `net.ssl`: types using ssl contexts can now be converted to strings via `.str()`/printed via `println()`. - `v.reflection`: added type symbol info metadata. - `crypto` and `math` modules have been updated to use `Result` instead of `Option`. - `datatypes.LinkedList[map]` now works correctly. - `urllib.Values.get()` now returns an Option. - `strconv`: `v_printf()` was made private, `v_sprintf()` was deprecated. String interpolation should be used instead. - `net.http`: mime types have been updated to include all official types. - `gg`: `create_image()` now returns `!Image` instead of `Image`, allowing to handle errors. - `sokol`: errors during image creation no longer result in a panic, but can be handled by the programmer. - `sokol`: macOS apps can now be quit using **Cmd+Q**. - `os.hostname()` and `os.loginname()` now return `Result`. - `strconv.atoi` optimizations. - `println()` now supports arrays with recursive references. - `termux`: support for cross-compilation from termux to other platforms. - `readline` module now works much better on macOS: key navigation, history, etc (now on par with Linux). - `os`: fixed a memleak in `getline()`. - `os.Process` now has a `create_no_window` option (Windows only). - `os.Process` now has a `set_work_folder()` method to set the initial working folder of the new child process. #### Option as a first class type Final steps in making the Option type a first class type: - If guards now work with struct fields which are `Option` functions. Such fields can now also be assigned to other fields/variables. - Option receivers can no longer have methods. - `none` can now be cast to all `Option` types, including aliases. - Option references are now supported: `?&Type`. - Arrays of `Option`s are now allowed. - Allow `foo := Foo{}`, when `Foo` has an Option field, that is a struct, that has a `[required]` tag on its fields. #### Compile-time Reflection - Compile-time interface fields evaluation. - Compile-time enum evaluation: ```v syntax-ok $for item in MyEnum.fields { println(item.value) println(item.name) } ``` - Added `$option` as a compile-time reflection type representing an any Option type. - All special compile-time reflection types are now lowercase (`$int`, `$enum`, `$option`, etc). #### Checker Improvements/Fixes - Enums can no longer be initialized like structs. - Capture variables can no longer shadow anonymous function params. - Mixing multi-return results with other types in return statements is no longer allowed. - Assigning anonymous structs to named structs is no longer allowed. - `[required]` fields are now checked for embedded structs. - Fixed a bug with closures with fixed array variables. - Builtin methods `first/last/repeat` can now be used in custom user types (previously they only worked in builtin arrays). - Generic struct initialization no longer needs explicit types to be provided: ```v syntax-ok struct Foo[T, U] { a T b U } foo := Foo{ a: 2 b: 'x' } println(foo) ``` - unsafe: dereferencing nil references is no longer allowed in the following case: ```v syntax-ok a := unsafe { nil } println(*a) ``` #### OSes - Added basic QNX support. #### Other changes - Lots of documentation/readme improvements. - Lots of playground improvements: [play.vlang.io](https://play.vlang.io), including a really cool feature: "Show generated C code". - A new `[spawn_stack: 131072]` function attribute for controlling the max size of the stack of the spawned threads. - Channel pop now works with an `or` block: `ch := <-self.item or { return none }` - `it` has been renamed to `index` in array inits. - "Is V still fast?" web-page has been sped up by splitting the result table into multiple years. #### Development - GitHub Copilot summaries in PRs. ## V 0.3.3 *30 Jan 2023* #### Improvements in the language - String interpolation simplified to just '${name}', enforced by vfmt, and updated in the entire code base. - `go foo()` has been replaced with `spawn foo()` (launches an OS thread, `go` will be used for upcoming coroutines instead). - vfmt now supports `// vfmt off` and `// vfmt on` for turning off the formatting locally for short snippets of code. Useful for keeping your carefully arranged matrices intact. - Match branch range expressions with consts: `match x { const1...const2 {} }` - Hot code reloading via `[live]` is now supported in imported modules, not just the main module. - Syntax sugar for map inits without needing explicit casts for interfaces: `all.children := { "abc": rect, "def": ui.rectangle()}`. - `$embed_file()` fixes, including variable args support. - `none` fixes: no longer allowed to be used as a separate type, `dump()` support, not allowed inside `unsafe`. - Const functions: `const y = term.yellow`, then `println(y('abc'))`. - Builtin type names can no longer be used as identifiers. - Generic `typeof[T]()`, `sizeof[T]()`, `isreftype[T]()` functions. - Deprecated `-error-limit` in favour of the documented `-message-limit` option. - Maps now support aliased keys. - Operator overloading now works with reference types. - Generic struct inits with nested generic structs and generic optional types are now allowed. - During array creation, `len:` is required when using default values for the array. - Optimized one byte `[]u8` arrays creation. - Recursive aliasing is no longer allowed (e.g. `type Alias = map[string]Alias`). #### Breaking changes - `[]` is now used for generics instead of `<>`. - Accessing a pointer map value requires an `or {}` block outside `unsafe`. #### Checker improvements/fixes - Lots of fixes in the type checker. - Int signedness mismatch is now checked: `cannot use literal signed integer as u8`. #### Standard library - `math.vec` module for generic vector math including 2D, 3D, and 4D vector operations. - Builtin stb_image.h used by gg has been updated to the latest v2.28. - All of vlib has been updated to use separate Option/Result types. - To avoid confusion, all references in the code and documentation to `Optional` have been replaced with `Option`. - `gg.Context` pipeline has more effects, including the `additive` effect. - Much cleaner eof checks in `os`: refactor `err == IError(os.Eof{})` to `err is os.Eof`. - Lots of work on `x.json2`, the pure V json encoder, soon to become official. - New `v.reflection` module for runtime reflection. - Improved `os.mv()`, which now works consistently even across different windows drives/mount points. - `string.trim_indent()`, useful with multi line strings, that start/end with new lines and indentation. - Reduced memory consumption in the `crypto` modules. - Official V UI library is now licensed under MIT. - Deprecated `math.util` and `math.mathutil` have been removed. - New time format support: `time.format_rfc3339()`. - `encoding.html.escape()`. - All public functions in the `hash` and `encoding.base32` modules have been documented. - New `crypto.pem` module. - New `map.reserve()` method. #### Web - Improved vweb stability under load. #### ORM - Various ORM fixes and improvements, including string interpolation support, type checks, fn calls in `where`. #### Database drivers - VFS support in the builtin `sqlite` module; `sqlite.get_affected_rows_count()`. - Improved `pg` compatibility with older PostgreSQL versions before 2014. - `sqlite`, `pg`, `mysql` have been moved to `db.sqlite`, `db.pg`, `db.mysql`. #### Native backend - Operator support for floats, multi return. #### Comptime - Improved compile time checks, like `$if x is Type {`; `$if T in [$Array, $Struct, $Alias, $Function] {`. - `$for in` works with alias types. - New comptime features for fields: `field.is_`, `field.is_alias`, `field.is_enum`. #### OS support - Installation instructions for using V on NixOS. - Better `make` support for OpenBSD. - Much improved experience for `v install pcre` on Windows (it now bundles its own .c files, so it compiles cleanly, even if the platform does not have another pcre package installed). - V can now be compiled with tcc on latest macOS and Apple Silicon. #### Tools - fast.vlang.io fixes & improvements, new server. - New official IntelliJ plugin: https://intellij-v.github.io. - Lots of new language documentation, a nicer table of contents. - Improved documentation for most of the vlib modules - `make.bat` & `v up` improvements on Windows. - TeamCity test runner support via `v -test-runner teamcity foo_test.v`. - CI optimizations for faster runs. - New official AdventOfCode repo with AOC solutions, also added to CI. - More detailed timings in `v -show-timings`. - `v new web` for quickly scaffolding new web projects. ## V 0.3.2 *31 Oct 2022* #### Improvements in the language - New simplified string interpolation: `println("Hello, {name}!")`. It will be the only way, old syntax (`${name}` and `$name`) will be deprecated. - Easier custom error creation: `return MyCustomErr{}` instead of `return IError(MyCustomErr)`. - All floats outputs now have `.0` conditionally appended to them to improve clarity. - Custom integer enum types: `enum Xyz as u64 {`. - AST transformer fixes and optimizations. - Stylistic improvements and bug fixes in vfmt. - Casting integers to enums now requires `unsafe{}`. - Improved error and warning messages. - Parallel compilation now uses `sync.Pool`. - `-skip-unused` fixes, soon to be made the default. #### Breaking changes *No breaking changes* #### Checker improvements/fixes - Improved type checker: lots of new type checks and fixed checker bugs. - Unused last expression in `if` is now checked. - Anonymous structs visibility issues fixed. #### Standard library - `net.ssl` has been migrated from a dynamically linked OpenSSL to a statically linked Mbed TLS. This means that V binaries will no longer have an OpenSSL dependency. OpenSSL can still be enabled via `-d use_openssl`. - msgpack module for decoding/encoding msgpack. (`v install msgpack`) - Most of vlib has been updated to use the new Option/Result types. - net, net.http, vweb bugs and fixes. - QuadTree and RingBuffer types in `datatypes`. - Forward iterator for `datatypes.LinkedList`, forward and backward iterators for `datatypes.DoublyLinkedList`. - A new `maps` module, similar to existing `arrays`. It has generic `filter`, `flatten`, `invert`, `to_map`, `to_array`, `from_array` functions. - `utf8.is_number()`, `utf8.is_space()` functions. - New `encoding.base32` module. - `gg.TouchPoint` to differentiate between different types of touch input. - `str.int()` conversion speedup (without -prod). #### Web - `vweb.csrf` module. #### ORM - Support parenthesized expressions like `select from User where (name == 'Sam' && is_customer == true) || id == 1`. #### Native backend - Lots of native backend improvements, including library calls, comptime conditionals, enums, method definitions/calls, structs. #### V interpreter - Some further interpreter work. #### C backend - cgen cleanups. #### OS support - Removed the need for the `[console]` attribute in Windows GUI apps. - More precise WINAPI declarations for easier integration on Windows. - More CI tests on FreeBSD. #### Tools - New stunning playground with an improved look and feel, a much better and more responsive editor, code sharing by link, more convenient keyboard control, reusability for potential embedding: https://play.vlang.io. - Improved call tracing via `-trace-calls`. - Lots of documentation improvements, including a better documentation of the recent Option/Result split. - V REPL: Home/End keys support. Lots of clean up. ## V 0.3.1 *31 Aug 2022* #### Improvements in the language - Anonymous structs. - Lots of bug fixes: 90% of all bugs ever submitted are closed. - New keyword/type: `nil`. Only to be used inside `unsafe`. Replaces `voidptr(0)`. - V can now find code in the `src/` directory. This allows making V repos much cleaner. - Support `assert condition, extra_message`, where the `extra_message` will be evaluated and shown if the assertion fails. - Operator overloading now works with aliases and generics. - Scanner optimizations. - Using C's #define is no longer allowed in normal V code, only in `.c.v` files. #### Breaking changes - Anonymous sumtypes have been removed (deprecated for now) due to complicating the language and the compiler too much. #### Checker improvements/fixes - More type checks. - Lots of fixes in `shared` types. #### Standard library - `os.mkdir()` now has an optional `mode` parameter. - `encoding.csv` is now generic, supports bools, accepts a custom delimiter, and is compatible with io.Reader/io.Writer. - `datatypes` module now uses operator overloading. - All `datatypes` types can be converted to V arrays. - `smtp` improvements including multiple recipients and base64/utf8 support. - `arrays.carray_to_varray()` for converting C arrays to V arrays. - `strconv.v_sprintf()` has been deprecated in favor of string interpolation. - TOML module now supports `[toml:...]` attributes, just like the JSON module. - `os.walk()` is no longer recursive (still works the same). - `io` has been migrated to `Result`. - Third party window control in Sokol. - `string.replace_char()`, `math.round_sig()`. - Improved multiplication performance in `math.big`. #### Web - `net.urllib` ipv6 support. - `net.Http.Response.text` renamed to `body`. - `net.websocket` timeout is now configurable. #### ORM - ORM functions now return `Result`, so the errors can be handled. #### Database drivers #### Native backend - Major improvements to the fast native backend including linking support on Linux. The goal is to be able to self host V soon. #### V interpreter - V interpreter improvements. #### C backend - Parallelized cc step. Speeds up -prod and clang/gcc compilation by 300-500% (depending on the number of cores). Experimental and hidden behind a -parallel-cc flag, soon to be the default. - Intel C compiler support. - Go backend fixes. - `#preinclude` for low level C interop. #### OS support - Full termux support via `$if termux {`, more predictable logging on Android. - Older macOS support (<10.12). - Windows code has been removed from `v.c` distributed on non-Windows systems. (`v_windows.c` is used on Windows.) #### Tools - DOOM is now translated/compiled and launched on CI servers. A screenshot of the running game is made via `vgret` and is compared to the expected result. - VLS performance improvements, especially on Windows. - `v ls` tool for installing, for updating, and for launching VLS (V Language Server). - `v doc` now has syntax highlighting. ## V 0.3 *30 Jun 2022* - C to V translation via C2V: `v translate file.c`. (Demo video: [Translating DOOM from C to V, building it in under a second and running it!](https://www.youtube.com/watch?v=6oXrz3oRoEg)) - Lots of bug fixes in V, cgen, and C interop to allow running translated DOOM.v. - Programs built with the V compiler no longer leak memory by default. - Closures. All operating systems are supported. ([Demo](https://x.com/v_language/status/1528710491882852352)) - `Option` and `Result` are now separate types: `?Foo` and `!Foo` respectively. Old code will continue working for 1 year and will result in a warning/hint. - Hundreds of new checks in the type checker. - All V's backends have been split up into separate processes. As the result, building V got 26% faster. - Maps and arrays can now return options: `m[bad_key] or { ... }`, `if x := arr[key] { ... }`. - `ustring` has been replaced with `[]rune` (works just like in Go). - Maps can now have non-string keys. - A new compiler pass for transforming the AST (doesn't slow the compiler too much, adds about 25ms to `v self`). It eliminates unreachable branches and performs other simple optimizations and transformations. - C backend is now parallel (just the cgen part for now). - Lots of compiler source code clean up and minor optimizations. The compiler got ~30% faster according to fast.vlang.io. - Better compiler source code organization (absolutely necessary as it's surpassed 100k loc). - The naming of V's integer types is now more consistent: `byte` has been renamed to `u8`. Old code will continue working for 1 year and will result in a warning/hint. - The typo detector now highlights the suggested name so that it's more visible. - `datatypes` module now has `Heap, Queue, Stack, BSTree, LinkedList`. - Interfaces can now be embedded (like structs). - vlib now has a TOML parser, fully compatible with TOML 1.0. - Lots of work done on the V.js backend, including the graphics library, which has been ported to V.js. - JS promises, await (V.js). - It's now possible to do more complex array initialization by using each individual element of the array (`[]int{init: it}`). - Unsigned right shift operators `>>>` and `>>>=` have been added to V. (They work exactly like in Java.) - `-nofloat` option, which is useful for writing kernels and for embedded systems without an FPU ( used in Vinix). - Generic interfaces. - TCC is now bundled with the language, this allows building V programs without an external C compiler dependency. - Null can be used in `unsafe` only (for example, for C interop). - Pointer arithmetic and comparing pointers to numbers is now also only allowed in `unsafe`. - Inline sumtypes. - New module `compress.gzip`. - Lots of `net`/`net.http`/`vweb` fixes (also used for the upcoming Gitly launch). - IPv6 support. - `net.http` headers are now enum fields instead of strings. This allows to avoid typos and offers autocomplete. - Struct field deprecation. - Static GC (no longer a dynamic lib dependency). - New various algorithms for random number generation: MT19937RNG, etc (module `rand`). - Fix immutability bugs that allowed to bypass compiler immutability checks and modify const/immutable values. - Lots of fixes in the JSON serializer. - Heap allocated only structs marked with `[heap]`. - Significantly improve lots of error messages, make them more clear, suggest hints. - Bug fixes and new features in the pure V `regex` module. - Lots of new drawing functions in the graphics module (like `gg.draw_polygon_filled(), gg.draw_arc_empty()` etc) - Builtin FPS display in `gg`. - Latest Sokol backend in `gg`. - Advanced CI tests for the graphics module. Graphical apps are run on GitHub Actions instances, their output is saved to an image, uploaded, and compared to the expected result. - More bug fixes in generics. - Bug fixes in aliases. They can now fully replace the types they alias. - `[minify]` struct attribute for struct minification. - `for in` now works with fixed arrays. - The parser was made a bit faster by skipping `vfmt` code when not in `vfmt` mode (by using `-d vfmt`). - Lots of vfmt improvements, especially with comments. - Experimental `#[index]` syntax for negative indexing (like in Python, but needs special syntax instead of being used by default). - Visibility bug fixes in modules (`pub`). - Error propagation in complex expressions (e.g. `foo(bar()?)`). - Optionals can now by used in consts (`const x := opt() or {}`). - Lots of new documentation, including vlib modules documentation and the official V Documentation. - vpm improvements (including a new vpm mirror). - `sync` improvements including `sync.thread_id()`, `sync.Once`.. - V can now be used to generate object files (`foo.o`) that can be used in existing C projects. - `-usecache` and `-skip-unused` fixes, they are close to being on by default. - Lots of Windows issues fixed. - Amazon Linux support. - Fixes in shared maps and arrays. - `term.ui` improvements, including multi byte/UTF-8 events. - New `crypto` modules, including `crypto.des, crypto.cipher, crypto.blowfish`. - Comptime fixes. - 4 byte bool option (`-d 4bytebool`) for compatibility with some C software. - `strconv` (pure V formatting module used in string interpolation) fixes and performance improvements. - ORM fixes (pg, mysql, sqlite). Tables are now created automatically based on the V structs, no more need in sql files to create tables for apps. - `volatile` keyword. - `"stringliteral".len` optimization (replaced by the actual number by the new `transform` pass). - Lots of inline assembler improvements (it's used a lot in Vinix). - Many new functions in the `math` module. - Separators in number literals: `1_000_000`. - `strings.Builder` optimizations and new methods. - Autofree fixes (still not production ready, hidden behind the `-autofree` flag). - Lots of Android fixes in V and in vab. - Lots of commits to the native backend (amd64/arm64). - V interpreter fixes. (Still at an early stage.) - Go2V translator has been started by the community, and can already translate simple programs. - An early version of the Go backend (`v -b go -o file.go file.v`). ## V 0.2.4 *30 Aug 2021* - Introduce `isize` and `usize` types, deprecate `size_t` in favor of `usize`. - Add `datatypes` and `datatypes.fsm` modules. - Add `compile_error` and `compile_warn` comptime functions. - Bare metal support. Vinix OS kernel is now being developed in V. - Builtin web framework vweb is now multithreaded, all CPU cores are used. - String interpolation and struct stringers are now implemented in pure V with a much cleaner and faster implementation. Previously libc's `sprintf` was used. - Improved `unused variable` warning. Assigning to a variable no longer marks it as used. *... lots of missing changelog for this version, sorry (will update a bit later)* ## V 0.2.2 - 0.2.3 *22 Jan 2021* - Allow interfaces to define fields, not just methods. - `vweb` now uses struct embedding: `app.vweb.text('hello') => app.text('hello')`. - Consts can now be declared outside of `const()` blocks: `const x = 0`. - Overloading of `>`, `<`, `!=`, `==`, `<=` and `>=` operators. - New struct updating syntax: `User{ ...u, name: 'new' }` to replace `{ u | name: 'new' }`. - `byte.str()` has been fixed and works like all other numbers. `byte.ascii_str()` has been added. - Smart cast in for loops: `for mut x is string {}`. - `[noinit]` struct attribute to disallow direct struct initialization with `Foo{}`. - Array decompose: `[1, 2, 3]...` is now `...[1, 2, 3]` - Treating `enum` as `int` and operations on `enum` except `==` and `!=` are removed for strict type checking. - Support `[manualfree] fn f1(){}` and `[manualfree] module m1`, for functions doing their own memory management. - Allow usage of `<` and `>` operators for struct in `.sort` method for arrays, i.e. `arr.sort(a < b)`. - Auto generate assignment operators like `+=`, `-=`, `*=`, `/=` and `%=` if the operators are defined. - Colorize and improve failing tests output. - Fix `go` with a generic function: `go test(c, 'abcd')`. - Add comptime `x := $embed_file('v.png') println(x.len) println(ptr_str(x.data()))`, for embedding files into binaries. - Advanced vdoc search on mobile layout. - string's `left()`/`right` were removed in favor of slicing syntax: `str[..pos]`. - gg: native graphics mode on macOS/iOS (using Cocoa Drawing API). - Full path to consts must be specified everywhere. This makes it easy to distinguish them from local variables. - `__offsetof` for low level needs (works like `offsetof` in C). - vfmt now preserves empty lines, like gofmt. - Support for compile time environment variables via `$env('ENV_VAR')`. - Allow method declaration of `==` and `<` operators and auto generate `!=`, `>`, `<=` and `>=`. - support `dump(expr)`, i.e. tracing of both the location, name and value of an expression - deprecate os.exec in favour of os.executable() which does *NOT* return an option, when the command was not found ## V 0.2.1 *30 Dec 2020* - Hashmap bootstrapping fixes. - Array decomposition to varargs: `fn sum(i ...int) int` => `a := [2,3,4] println(sum(a...))` - HTML module docs generated by vdoc now have global search. ## V 0.2 *22 Dec 2020* - Compile-time memory management via `-autofree` (not production ready yet). [Video demonstration](https://www.youtube.com/watch?v=gmB8ea8uLsM). - Channels and locks. - Thread safe typed arrays via keyword `shared`. - Struct embedding. - IO streams (`io.Reader`, `io.Writer` etc). - A powerful websocket module that conforms to RFC 6455 and passes the Autobahn test suite (498 client tests and 249 server tests). - The `net` module is now non blocking and is more feature complete providing similar API to Go. - V's graphics module now uses Metal/DirectX/OpenGL instead of just OpenGL. - V can now run in the browser via WASM and execute V code by translating it to JavaScript: https://v-wasm.now.sh - V binaries for Linux/Windows/macOS are now built and deployed automatically via GitHub Actions. - Smart casting for sumtypes and interfaces, including complex expressions: `if x.expr is int { println(x.expr + 1) }`. - Clean and easy way to sort arrays: `users.sort(a.name > b.name)`. - A huge amount of `vfmt` fixes and improvements. It has now reached a point where it can be safely used on any V source file. - A new CI job that runs `v fmt -verify` on the entire code base, a new command that makes sure the file/directory has been vfmt'ed. This ensures that all code submitted to the V project is formatted. - A new tool `v vet` for analyzing the project and finding potential bugs and errors. - A new `term.ui` module for building dynamic terminal UIs with an example editor written in it. - Early iOS and Android support. - All missing ORM features from the old backend were brought back. - Magic `it` variable has been replaced with smart casts (the change is completely handled by vfmt). - Cross-compiling to Windows and Linux brought back. - C2V can now generate wrappers. Example: https://github.com/medvednikov/libsodium. (C2V will be released by 0.3) - C++ compiler support: code, generated by the C backend can now by compiled by C++ compilers. - Short generics syntax: `foo(5)` instead of `foo(5)`. - Cached modules via `-usecache`. Faster compilation due to not needing to rebuild the entire vlib for each program. Will be enabled by default in 0.2.1. - New improved sum types implementation. - Lots of errors that happen often during the development cycle were turned into warnings to increase development speed. They are still errors in production builds. - Labeled `break` and `continue`. - Lots of documentation. The official language documentation grew 3 times in size. - `modules.vlang.io` is now generated automatically on every commit. - Builtin compile-time JSON serializer now supports `time.Time`. - Fixes in type aliases, to make them behave just like the types they alias. - `array.contains(element)` is now generic. - Lots of improvements in the JS backend and its type system. - Simpler and more constinent function arg syntax: `foo(a int, b int, c string)` instead of `foo(a, b int, c string)` - Lots of fixes and optimizations in the hashmap. - Lots of missing checks in the type checker were added (for example, checking the correct usage of public struct fields). - Mutability bug fixes - Taking the address of a map value is no longer allowed, like in Go. - Matrix multiplication. - A new `#pkgconfig` flag to provide platform independent way to get compilation flags for C libraries/packages. - Explicit parentheses requirement in complex boolean expressions. - `println` was made even smarter, and can now handle complex types. - Precompiled text templates can now be used outside of vweb via `$tmpl()`. - Gitly, a big web application written in vweb has been released: https://github.com/vlang/gitly - `['/:arg1/:arg2/action']` vweb action attribute for easily getting query parameters assigned to method arguments. - Improved performance of text rendering, `gg.text_width()`. - Webview module in V UI. - Binary enum flags. - `[export]` attribute to change exported function name (for example for calling from a C library). - `unsafe` fixes and improvements. - Improvements to rand: `rand.ulid()`, `rand.uuid()`, a unified customizable PRNG API. - Hundreds of other fixes, features, and tests (from now on the changelog will be updated right away as the feature/bug fix lands). ## V 0.1.27 *5 May 2020* - vfmt has been re-written from scratch using the new AST parser. It's much faster, cleaner, and can format files with compilation errors. - `strconv`, `sprintf`, and `printf` in native V, without any libc calls. - Interfaces are now a lot more stable and have all expected features. - Lots of x64 backend improvements: function calls, if expressions, for loops, local variables. - `map()` and `filter()` methods can now be chained. - New `[]int{cap:cap, len:len}` syntax for initializing array length and capacity. - New `is` keyword for checking the type of sum types and interfaces. - `as` can now be used to cast interfaces and sum types. - Profiling with `-profile`. Prints a nice table with details about every single function call: number of calls, average time per call, total time per function - `import(xxx)` syntax has been removed in favor of `import xxx` for simplicity and greppability. - Lots of fixes and improvements in the type checker. - `time.StopWatch` - `dl` module for dynamic loading. - Automatic `str()` method generation for every single type, including all arrays. - Short struct initialization syntax for imitating named function args: `foo(bar:0, baz:1)`. - New operator `!in`. - Performance improvements in critical parts of the builtin data structures (array, map). - High order functions improvements (functions can now be returned etc). - Anonymous functions that can be defined inside other functions. - Built-in JSON module is back. - Lots and lots of new tests added, including output tests that test error messages. - Multiple errors are now printed, the compiler no longer stops after the first error. - The new JS backend using the AST parser (almost complete). - Variadic functions. - `net.websocket` module (early stage). - `vlib` is now memory leak free, lots of `autofree` improvements. - Simplified and cleaned up `cmd/v`, `v.builder`. - V UI was updated to work with the new backend. ## V 0.1.25 *1 Apr 2020* - The entire compiler has been re-written with an AST parser. The code is now a lot cleaner and more maintainable. ~15k lines of old compiler code were removed. ## V 0.1.24 *31 Dec 2019* - A new parser/generator built on top of an AST that simplifies code greatly and allows to implement new backends much faster. - Sum types (`type Expr = IfExpr | MatchExpr | IntegerLiteral`). - B-tree map (sped up the V compiler by ~10%). - `v fmt -w`. - The entire code base has been formatted with vfmt. - Generic structs. - SDL module. - Arrays of pointers. - os: `is_link()`, `is_dir()`, `exists()`. - Ranging through fixed size arrays. - Lots of fixes in ORM and vweb. - The first tutorial: [building a simple web application with vweb](https://github.com/vlang/v/blob/master/tutorials/building_a_simple_web_blog_with_vweb/README.md) - Match expressions now must be exhaustive. - freestanding: `malloc()`/`free()`. - `++` is now required instead of `+= 1` for consistency. - Interpolated strings now allow function calls: `println('val = $get_val()')`. - `string.replace_each([])` for an efficient replacement of multiple values. - More utf8 helper functions. - `-prealloc` option for block allocations. - `type` aliases. - Running `v` with an unknown command will result in an error. - `atof` implementation in pure V. - Enums can now have negative values. - New `filepath` module. - `math.factorial`. - `ftp` module. - New syntax for casting: `val as Type`. - Fewer libc functions used (soon V will have no dependency on libc). ## V 0.1.23 *30 Nov 2019* - [Direct x64 machine code generation](https://github.com/vlang/v/issues/2849). Hello world being built in 3 milliseconds. - Bare metal support via the `-freestanding` flag, to build programs without linking to libc. - Prebuilt V packages for Linux, macOS, and Windows. - `string.index()` now returns `?int` instead of `int/-1`. - Lots of fixes in Generics. - vweb framework for developing web applications is back. - Vorum, the forum/blogging software written in vweb, can now be compiled and has been added to CI. - REPL, `v up` have been split up into separate applications to keep the core V compiler small. - V now enforces short enum syntax (`.green` instead of `Color.green`) when it's enough. - V UI for macOS. - Interfaces have been rewritten. `[]interface` support. - `os.cp()` for copying files and directories. - Additional compile-time flags: `$if clang, msvc, mingw, x32, x64, big_endian, little_endian {`. - All C functions now have to be declared, all missing C functions have been defined. - Global variables (only with the `-enable-globals` flag) for low level applications like kernels and drivers. - Nothing can be cast to bool (previously code like `if bool(1) {` worked). - `<<` and `>>` now work with all integer types. - V detects Cygwin and shows an error (V supports Windows natively). - Improved type checking of some operators (`%, |, &` etc). - Windows 7 support. - `println(true)` now prints `true` instead of `1`. - `os.exec()` now uses `CreateProcess` on Windows. - fast.vlang.io website for monitoring the performance of V after every commit. - On Windows Visual Studio is now used automatically if GCC is not installed. - vfmt! - Lots of cleaning up in the compiler code. - Multi-level pointers in unsafe code (`****int`). - MSVC backtrace. - `$if os {` blocks are now skipped on a different OS. - C string literals (`c'hello'`). - AlpineLinux/musl fixes + added to CI. - Inline assembly. - Clipboard module (Windows, macOS, X). - `foo()?` syntax for error propagation. - Docs have been migrated from HTML to `doc/docs.md`. - `eventbus` module. - Haiku OS support. - `malloc/free` on bare metal. - `utf8` helper functions (`to_lower()`, `to_upper()`, etc). - Optimization of `for c in str {`. - `string/array.left/right/slice/substr` were removed (use `[a..b]` slicing syntax instead). ## V 0.1.22 *28 Oct 2019* - Generic functions (`fn foo(bar T) T {`) with varargs support. - `array[start..end]` and `string[start..end]` slicing syntax. - Optimized `array.filter()` and `array.map()`. - `sqlite` module. - Cached modules for faster compilation. - Dramatic compilation optimizations: [V now compiles itself in 0.10 - 0.30 seconds](https://github.com/vlang/v/wiki/The-V-language-now-compiles-itself-in-0.09-seconds) - V scripts (simpler and cross-platform alternative to Bash). - Infinite multi-dimensional arrays (`[][][]int`). - `unsafe`. - `[deprecated]` attribute. - `[if]` function attributes for compile time function exclusion for performance. - `switch` has been completely removed from the language and replaced by `match` everywhere. - `pub struct` and `pub const`, previously all structs and consts were public by default. - `musl` support (V can now run on, for example, Alpine Linux). - Module header generation. V now supports closed source modules, which are still used in some industries. - Constants were added to typo suggestions. - `color in [.green, .red, .blue]` now works without specifying `Color.green`. - V compiler is now a module that can be used by other programs. - Backtraces now have source lines on Linux. - `runtime.nr_cpus()`. - `fn init()` for module initialization. - `a in [1, 2, 3]` optimization: no array gets allocated. - Raw strings: `s := r'hello\nworld'`. - `if a := func() { }` syntax for handling options. - f32/f64 comparison now uses machine epsilon by default. ## V 0.1.21 *30 Sep 2019* - `none` keyword for options. - Solaris support. - All table lookup functions now use `none`. - varargs: `fn foo(bar int, params ...string) {`. - Double quotes (`"`) can now also be used to denote strings. - GitHub Actions CI in addition to Travis. - `-compress` option. The V binary built with `-compress` is only ~90 KB! - More memory management. - Unused modules result in an error. - "Unused variable/module" errors are now warnings in non-production builds. - Duplicate methods with the same name can no longer be defined. - Struct names must be capitalized, variable/function names must use snake_case. - Error messages are now even nicer! - Lots of fixes in automatic `.str()` method generation for structs and arrays. - ~30% faster parser (files are no longer parsed separately for each pass). - `_` is no longer a variable, but an actual syntax construct to skip unused values, like in Go. - Multiple returns (`fn foo() (int, string) {`). - `!` can now only be used with booleans. ## V 0.1.20 *17 Sep 2019* - JavaScript backend! - Hundreds of C warnings were fixed. `gcc v.c` now builds without any warnings. - The mutability check now applies to function args (mutable receivers that are not modified result in a compilation error). - V tests now show how long each test took. - Official Android support (only console applications via Termux for now). - Typo check. If a variable/function/module etc is misspelled, V will suggest the correct name. - Lots of Microsoft C fixes, and a separate Travis instance for this backend. - Bitwise operators `|`, `^`, `&` no longer work with booleans. ## V 0.1.19 *12 Sep 2019* - Lots of refactoring, simplifications, and optimizations in the compiler. - Experimental memory management at compilation (only for the V compiler itself for now). - Lots of ORM fixes. - Functions can now be inlined via the `[inline]` attribute. - New `mysql` module. - Better error format that is supported by all major editors (go to error). - Error messages now point to the actual place where the error happened. - Custom json field names: `struct User { last_name string [json:lastName] }`. - Raw json fields via the `[raw]` attribute. - All C code was removed from the `freetype` module. - `gg` module can now render all Unicode characters. - `[typedef]` attribute for imported C struct typedefs. - Support of Objective C interfaces (primarily for using Cocoa). - REPL: clear command and custom functions. - REPL tests (which are also used for testing certain compiler errors). - Syntax bug fixed: `foo[0] += 10` is now possible. - http: support plain HTTP protocol and follow redirects. - http: header data is now processed correctly. - net: basic UDP support. - `import const` was removed from the language. - `array.contains()` was removed from the language (`in` should be used instead). - `[0; len]` syntax was removed (replaced with a simpler `[0].repeat(len)`) - Primitive aliases were removed to simplify the language. - GitHub supports V now! - Backtraces are now printed on panics. - A new awesome `readline` module. - V.c is now regenerated automatically after every commit. - A bug with struct ordering was fixed, now structs can be declared in any order. - V modules can now be built with `v build module`. - `@FILE, @LINE, @FN, @COLUMN` for debugging. ## V 0.1.18 *16 Aug 2019* - Built-in ORM (`uk_customers = db.select from Customer where country == 'uk' && nr_orders > 0`). - Map initialization syntax: `m := { ‘foo’: ‘bar’, ‘baz’: ‘foo’ }`. - `map.delete(key)`. - `libcurl` dependency was removed from the `http` module. - All function arguments are now immutable by default (previously they could be modified inside the function). - `http` functions now return options. - `sync.WaitGroup`. - `vweb` static files serving. - `crypto.rand` module. - `v up` to update V. - SChannel support on Windows. - `net.urllib` module. - vpm package manager, `v install`. - `()` are now required in complex bool expressions: `(a && b) || c` instead of `a && b || c`. - All arrays now have a default `.str()` method. - Bootstrapping V with MSVC. - Experimental `≠` etc support. - `encoding.csv` module. - `$if debug {` for running code in debug mode only. - Map struct fields are now initialized automatically, just like arrays. - Maps now support array values. - `json` functions can no longer be used if the `json` module is not imported. ## V 0.1.17 *29 Jul 2019* - `vweb` module for developing web apps in V. - vtalk, open source V forum software. - Generics (very limited right now, but they will be gradually improved). - Comptime codegen (`foo.$method()` where `method` is a string). - `@` for escaping keywords (e.g. `struct Foo { @type string }`). - Windows Unicode fixes (V can now work with non-ASCII paths etc on Windows). - Fix mutable args bugs + don't allow primitive arguments to be modified. - Declaring a mutable variable and never modifying it results in a compilation error. - Interactive debugging support. - `sync` module for Windows. - `#!` support on Unix systems (V scripts). - Lots of Visual Studio fixes. - `crypto.aes` and `crypto.rc4` modules. - Internal modules. ## V 0.1.16 *23 Jul 2019* - V can now be used with Visual Studio! - Hot code reloading now works with graphical applications (e.g. graph.v, bounce.v). - Compile time memory management for arrays. - High order functions. - `match` expression (replacing `switch`). - Import cycle detection. - `crypto/md5`, `crypto/sha256`, and `crypro/sha512` modules. - `os.executable()` - a cross platform function that returns full path to current executable. - `~/.vlang` and `VROOT` were removed entirely. The installation is a lot cleaner now. - V can now be packaged for all Linux distros. - Arch Linux package. - `string(bytes_buffer, len)`, `string(bytes_array)` casts. - Multiple `defer`s. - `key in map` syntax (replacing `map.exists(key)`). ## V 0.1.15 *15 Jul 2019* - FreeBSD, OpenBSD, NetBSD, DragonFly support. - Hot reloading now works with graphical applications: [bounce.v](examples/hot_reload/bounce.v) - VROOT was removed, the installation process is now much simpler. - `defer` statement. - map.v was re-written. It's now much faster. - `for key, val in map` syntax. - `flag` module for parsing command line arguments. - `zip` module. - `crypto/sha1` module. - Submodules and module aliases (`import encoding.base64 as b64`). ## V 0.1.14 *12 Jul 2019* - `gg` module Windows support, V Tetris runs on Windows. - Compile `glad` and `cJSON` only once. Programs using `gg` or `json` compile a bit faster. - `v.c` has been cleaned up and minimized (~16k => ~10k lines of code). - `type` aliases can now have methods. - Const overflow check during compilation (`byte(1000)` will no longer compile). ## V 0.1.13 *10 Jul 2019* - New enum syntax (`token == .name`), enum values are no longer global consts. - Submodules (`import encoding.base64`). - Hot code reloading. - Special `err` variable for getting error values. - Complex numbers. - `<<` can now append arrays (`numbers << [1, 2, 3]`). - Lots of Windows fixes (Windows still needs some work). - Lots of REPL improvements (e.g. `>> 2 + 3` works now, no `println` required). - The website was made easily translatable, it's now partially available in several languages. ## V 0.1.12 *4 Jul 2019* - V can finally compile itself on Windows (https://github.com/vlang/v#mingw-w64). - `os` module now uses options in all functions that return `File`. - Lots of bugs with options were fixed. - `println` was optimized. It no longer results in allocations. Now it also works correctly with all integer types. - Lots of `vfmt` fixes, it will be enabled tomorrow. - New `strings` module. - Lots of other fixes and improvements, thanks to all the contributors. ## V 0.1.11 *1 Jul 2019* - Cross compilation for Windows! - Lots of Windows fixes. - socket.v. - maps fixed. ## V 0.1.9 - 0.1.10 *29 Jun 2019* - Windows support via MinGW-w64. Pre-built Windows binary. - File structure has been simplified: all vlib modules were moved to the vlib/ directory, makefile was moved to the root. - One single archive with pre-built binaries for all operating systems. - `mut var := val` was fixed (previously `mut var = val` was allowed as well). ## V 0.1.8 *28 Jun 2019* - Single file programs without `fn main` now work as expected. - REPL has been fixed: it now supports imports, consts, function definitions, etc. ## V 0.1.7 *27 Jun 2019* - All C code in the compiler and vlib has been replaced with V. - `#` syntax for embedding C code has been removed. - Exported functions now need to be marked with `pub`, all public vlib functions have been updated. - CI has been set up (Travis + Azure). On every commit and PR it is made sure that V can compile itself, all tests pass, and all examples compile. - More tests have been uploaded. - Cleaner bytes to string conversion: `tos2(bytes)` => `string(bytes)`. - The home page has 3 more examples next to 'hello world' that show the features of the language. - Lots of bugs and issues fixed. ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Code of Conduct Be nice and respectful. ================================================ FILE: CONTRIBUTING.md ================================================ ## How to help and contribute to the V project The tasks in the lists below are ordered in terms of easiness/time/nerves investment. ### Starting tasks 0. Run `v quest` once (or several times a day) to gain XP. 1. Read the [language documentation](https://docs.vlang.io/introduction.html) and [standard module documentation](https://modules.vlang.io/). 2. Fix doc errors and places you found unclear, and make [PRs](https://github.com/vlang/v/pulls) about it. 3. Make V programs, in the areas that you are interested in, or help others make V programs. If the programs/libraries are public, post them to the channel `#showcase-discussion` on [Discord](https://discord.gg/vlang) and/or to [awesome-v](https://github.com/vlang/awesome-v). You can also answer other people's questions in Discord channels `#help` or `#v-chat`, or in [github's discussions page](https://github.com/vlang/v/discussions). 4. Read the new issues in the tracker. 5. Try to reproduce them on your system, and comment in the issues, with the results. 6. Read the PRs, try to spot errors in them, and comment about them. ### Medium tasks (after gathering experience with 1..6) 7. Make PRs, with bug fixes to existing issues (found doing 1..6). 8. Suggest new features, tools, or modifications to the existing ones here, based on the experience, that you gathered doing 1..7. 9. Make PRs with implementations of your suggestions, or based on other people's suggestions, based on 1..7 and the feedback from 8. ### Advanced tasks (after doing 1..9 for a while) 10. Work on [V RFCs](https://github.com/vlang/rfcs/) (submitting new ones, providing feedback to existing ones, implementing them). ## Code Structure I tried to make the code of the compiler and vlib as simple and readable as possible. One of V's goals is to be open to developers with different levels of experience in compiler development. Compilers don't need to be black boxes full of magic that only few people understand. The V compiler is modular, and can be used by other applications. It is located in `cmd/v/` and `vlib/v/`. The most important and useful command to remember when working on the V compiler is `v self`. It rebuilds the V compiler. Be careful, if you introduce a breaking change and rebuild V, you will no longer be able to use V to build itself. So it's a good idea to make a backup copy of a working compiler executable. But don't worry, you can always simply run `make` (or `make.bat`), it will download the C version of the compiler and rebuild it from scratch. The architecture of the compiler is very simple and has three distinct steps: Parse/generate AST (`v.parser`) => Check types (`v.checker`) => Generate C/JavaScript/machine code (`v.gen`) The main files are: 1. `cmd/v/v.v` The entry point. - V figures out the build mode. - Constructs the compiler object (`struct V`). - Creates a list of .v files that need to be parsed. - Creates a parser object for each file and runs `parse()` on them. - The correct backend is called (C, JS, native), and a binary is compiled. 2. `vlib/v/scanner` The scanner's job is to parse a list of characters and convert them to tokens. 3. `vlib/v/token` This is simply a list of all tokens, their string values, and a couple of helper functions. 4. `vlib/v/parser` The parser. It converts a list of tokens into an AST. In V, objects can be used before declaration, so unknown types are marked as unresolved. They are resolved later in the type checker. 5. `vlib/v/table` V creates one table object that is shared by all parsers. It contains all types, consts, and functions, as well as several helpers to search for objects by name, register new objects, modify types' fields, etc. 6. `vlib/v/checker` Type checker and resolver. It processes the AST and makes sure the types are correct. Unresolved types are resolved, type information is added to the AST. 7. `vlib/v/gen/c` C backend. It simply walks the AST and generates C code that can be compiled with Clang, GCC, Visual Studio, and TCC. 8. `vlib/v/gen/js` JavaScript backend. It simply walks the AST and generates JS code that can be executed on the browser or in NodeJS/Deno. 9. `vlib/v/gen/c/json.v` defines the json code generation. This file will be removed once V supports comptime code generation, and it will be possible to do this using the language's tools. 10. `vlib/v/gen/native` is the directory with all the machine code generation logic. It defines a set of functions that translate assembly instructions to machine code and build the binary from scratch byte by byte. It manually builds all headers, segments, sections, symtable, relocations, etc. Right now it only has basic support of the native platform (ELF, MACHO format). The rest of the directories are vlib modules: `builtin/` (strings, arrays, maps), `time/`, `os/`, etc. Their documentation is pretty clear. ## Example Workflow for Contributing (provided by [@spytheman](https://github.com/spytheman)) (If you don't already have a GitHub account, please create one. Your GitHub username will be referred to later as 'YOUR_GITHUB_USERNAME'. Change it accordingly in the steps below.) 1. Fork https://github.com/vlang/v using GitHub's interface to your own account. Let's say that the forked repository is at `https://github.com/YOUR_GITHUB_USERNAME/v` . 2. Clone the main v repository https://github.com/vlang/v to a local folder on your computer, say named nv/ (`git clone --depth=1 https://github.com/vlang/v nv`) 3. `cd nv` 3.1 (optional) Run these commands, which ensure that all your code will be automatically formatted, before committing: ``` cp cmd/tools/git_pre_commit_hook.vsh .git/hooks/pre-commit chmod 755 .git/hooks/pre-commit ``` It has to be done in a shell where you have done cd /root/of/your/V_repo once. Step 3 above does it with `cd nv`. I.e. you have to be in the top level folder, that contains the .git folder for the V repository. 4. `git remote add pullrequest https://github.com/YOUR_GITHUB_USERNAME/v` Note: The remote named `pullrequest` should point to YOUR own forked repo, not the main v repository! After this, your local cloned repository is prepared for making pull requests, and you can just do normal git operations such as: `git pull` `git status` and so on. 5. When finished with a feature/bugfix/change, you can: `git checkout -b fix_alabala` - Don't forget to keep formatting standards, run `v fmt -w YOUR_MODIFIED_FILES` before committing (if you have not run the commands from 3.1) - If you changed Markdown (`.md`) files, check them `v check-md YOUR_MODIFIED_FILES` before committing. 6. `git push pullrequest` Note: The `pullrequest` remote was setup on step 4 7. On GitHub's web interface, go to: https://github.com/vlang/v/pulls Here the UI shows a dialog with a button to make a new pull request based on the new pushed branch. (Example dialog: https://url4e.com/gyazo/images/364edc04.png) 8. After making your pull request (aka, PR), you can continue to work on the branch `fix_alabala` ... just do again `git push pullrequest` when you have more commits. 9. If there are merge conflicts, or a branch lags too much behind V's master, you can do the following: 1. `git pull --rebase origin master` # solve conflicts and do `git rebase --continue` 2. `git push pullrequest -f` # this will overwrite your current remote branch with the updated version of your changes. The point of doing the above steps, is to never directly push to the main V repository, *only to your own fork*. Since your local `master` branch tracks the main V repository's master, then `git checkout master`, as well as `git pull --rebase origin master` will continue to work as expected (these are actually used by `v up`) and git can always do it cleanly. Git is very flexible, so there are other ways to accomplish the same thing. See the [GitHub flow](https://guides.github.com/introduction/git-handbook/#github), for more information. ## Finding issues to contribute to If you're willing to contribute to V but don't know which issue to resolve - you can go to [Issues](https://github.com/vlang/v/issues) tab in this repository. There you can see things logged by both users and developers that need to be discussed and/or resolved. It's recommended to filter issues by likes and labels to find an issue you are interested in. ### Filtering by likes (recommended) Filtering by likes helps you identify high-impact issues. More likes mean more community interest. To quickly use this filter, click [there](https://github.com/vlang/v/issues?q=is%3Aopen+is%3Aissue+sort%3Areactions-%2B1-desc). To manually apply this filter, navigate to [Issues](https://github.com/vlang/v/issues) tab, then paste the following in the "Filter" field: ``` is:open is:issue sort:reactions-+1-desc ``` This filter will return all open issues sorted by likes in descending order. ### Filtering by labels The V repo has various labels to help navigate the extensive list of issues and help you find issues you're both interested in and capable of resolving. You can examine the list of labels [here](https://github.com/vlang/v/labels). The most common labels are: By issue type: - `Bug` - `Feature Request` By OS: - `OS: Linux` - `OS: Windows` - `OS: Mac` By status: - `Status: Confirmed` To apply this filter, navigate to [Issues](https://github.com/vlang/v/issues) tab, then paste the following in the "Filter" field: ``` is:open is:issue label:Bug label:"OS: Windows" label:"Status: Confirmed" ``` This filter will return all open issues with the labels `Bug`, `OS: Windows`, and `Status: Confirmed`. ## Using Github's hub CLI tool You can download the `hub` tool from https://hub.github.com/ . Using `hub`, you will not need to go through the (sometimes) slow website to make PRs. Most remote operations can be done through the `hub` CLI command. > [!NOTE] > You still need to have a GitHub account. ### Preparation: (steps 1..3 need to be done just *once*): 1. `hub clone vlang/v my_v` 2. `cd my_v` 2.1 (optional) Run these commands, which ensure that all your code will be automatically formatted, before committing: ``` cp cmd/tools/git_pre_commit_hook.vsh .git/hooks/pre-commit chmod 755 .git/hooks/pre-commit ``` 3. `hub fork --remote-name pullrequest` 4. `git checkout -b my_cool_feature` # Step 4 is better done *once per each new feature/bugfix* that you make. ### Improve V by making commits: 5. `git commit -am "math: add a new function copysign"` ### Testing your commits locally: You can test locally whether your changes have not broken something by running: `v test-all`. See `TESTS.md` for more details. ### Publishing your commits to GitHub: 6. `git push pullrequest` ### Making a PR with `hub`: (so that your changes can be merged to the main V repository) 7. `hub pull-request` Optionally, you can track the status of your PR CI tests with: 8. `hub ci-status --verbose` ### Fixing failing tests: If everything is OK, after 5-10 minutes, the CI tests should pass for all platforms. If not, visit the URLs for the failing CI jobs, see which tests have failed and then fix them by making more changes. Just use `git push pullrequest` to publish your changes. The CI tests will run with your updated code. Use `hub ci-status --verbose` to monitor their status. ## Compiler flags, useful while debugging the compiler itself: V allows you to pass custom flags using `-d my_flag` that can then be checked at compile time (see the documentation about [compile-time if](https://github.com/vlang/v/blob/master/doc/docs.md#compile-time-if)). Since the compiler is *also* an ordinary V program, there are numerous flags that can be passed when building the compiler itself with `v self`, or when creating a copy of the compiler, that will help you when debugging the compiler. Note: beware that the flags below must be passed, when building the compiler, *not the program*, so do for example: `./v -o w -d time_parsing cmd/v` or `./v -o w -d trace_checker self` ... then use `./w file.v`, instead of `./v file.v`, to compile your program. Note: some of the flags can make the compiler *very verbose*, so it is recommended to create a copy of the compiler rather than replacing it with `v self`. | Flag | Usage | |-----------------------------------|---------------------------------------------------------------------------------------------------------------------| | `debug_codegen` | Prints automatically generated V code during the scanning phase | | `debug_interface_table` | Prints generated interfaces during C generation | | `debug_interface_type_implements` | Prints debug information when checking that a type implements in interface | | `print_vweb_template_expansions` | Prints vweb compiled HTML files | | `time_checking` | Prints the time spent checking files and other related information | | `time_parsing` | Prints the time spent parsing files and other related information | | | | | `trace_scanner` | Prints details about the recognized tokens. *Very* verbose. Use with `./vnew -no-builtin -check-syntax file.v` . | | `trace_parse` | Prints details about the parsed files (number of tokens, lines, bytes). Use it for parsing order issues. | | `trace_parser` | Prints details about parsed statements and expressions. Very verbose. Use it for panics in the parser. | | `trace_check` | Prints the .v file which is checked. Use it to diagnose checker order issues. | | `trace_checker` | Prints details about the statements being checked. Very verbose. Use it for panics in the checker. | | `trace_transformer` | Prints details about the statements being transformed. Very verbose. Use it for panics in the transformer stage. | | | | | `trace_gen` | Prints all the strings written to the generated C file. Very verbose. | | `trace_gen_wanted_value` | Prints a backtrace, when a specific *wanted* value, is part of what is printed in the generated C file. | | | Use: `v -g -o vgen -d trace_gen_wanted -d trace_gen_wanted_value="message = _SLIT0" cmd/v && ./vgen bug.v` | | `trace_cgen` | Prints the .v file for which C code generation runs. Use it to diagnose cgen order issues. | | `trace_cgen_stmt` | Prints details about the statements that are being processed by cgen. | | | Use it for panics in cgen, to see the closest input V source line, that caused the panic. | | | Note: you need `v -no-parallel -d trace_cgen_stmt -o w cmd/v` to make sense of the output of that, | | | otherwise by default cgen uses several threads, and the lines that are printed are out of order. | | | | | `trace_autofree` | Prints details about how/when -autofree puts free() calls | | `trace_autostr` | Prints details about `.str()` method auto-generated by the compiler during C generation | | | | | `trace_ccoptions` | Prints options passed down to the C compiler | | | | | `trace_thirdparty_obj_files` | Prints details about built thirdparty obj files | | `trace_usecache` | Prints details when -usecache is used | | `trace_embed_file` | Prints details when $embed_file is used | | `embed_only_metadata` | Embed only the metadata for the file(s) with `$embed_file('somefile')`; faster; for development, *not* distribution | |-----------------------------------|---------------------------------------------------------------------------------------------------------------------| ================================================ FILE: Dockerfile ================================================ #same container that golang use FROM buildpack-deps:buster-curl LABEL maintainer="ANAGO Ronnel " WORKDIR /opt/vlang ARG USE_LOCAL RUN apt update && \ DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends gcc clang make git binutils && \ apt clean && rm -rf /var/cache/apt/archives/* && \ rm -rf /var/lib/apt/lists/* COPY . /vlang-local RUN if [ -z "${USE_LOCAL}" ] ; then \ git clone --depth=1 https://github.com/vlang/v /opt/vlang && \ rm -rf /vlang-local ; \ else \ mv /vlang-local/* . && \ rm -rf /vlang-local ; \ fi RUN make && \ ln -s /opt/vlang/v /usr/local/bin/v CMD [ "v" ] ================================================ FILE: Dockerfile.alpine ================================================ ## Usage: ## 1) docker build -t vlang_alpine - < Dockerfile.alpine ## 2) alias with_alpine='docker run -u 1000:1000 --rm -it -v .:/src -w /src vlang_alpine:latest' FROM alpine:3.23.3 LABEL maintainer="spytheman " WORKDIR /opt/vlang ENV PATH=/opt/vlang:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ## install development packages RUN apk --no-cache add \ musl-dev libc-dev libc6-compat gcompat \ openssl-dev sqlite-dev mbedtls \ libuv-dev libev-dev libevent-dev libmemcached-dev \ binutils diffutils elfutils pcre strace rsync \ libunwind-dev libunwind-static gc gc-dev \ make bash file git upx tmux micro nano nano-syntax \ gcc gdb wasi-sdk \ mesa-dev mesa-gl mesa-gles \ glfw-dev \ glu-dev \ glew-dev \ freetype-dev \ freeglut-dev \ libxi-dev libxi-static \ libxcursor-dev \ libx11-dev \ icu-data-full \ sdl2_net-dev \ sdl2_gfx-dev \ sdl2_ttf-dev \ sdl2_image-dev \ sdl2_mixer-dev \ sdl2_pango-dev \ sdl2-dev RUN ln -s /opt/vlang/v /usr/local/bin/v COPY . /vlang-local ARG USE_LOCAL RUN if [[ -z "${USE_LOCAL}" ]] ; then \ git clone --depth=1 --quiet https://github.com/vlang/v/ /opt/vlang && \ rm -rf /vlang-local ; \ else \ mv /vlang-local/* . && \ rm -rf /vlang-local ; \ fi RUN mkdir -p /tmp/v /tmp/v /home/ && chown -Rh 1000:1000 /opt/ /tmp/ /home/ ## setup runtime environment for v and bash: USER 1000:1000 ENV HOME=/home ENV VTMP=/tmp/v ENV VMODULES=/tmp/vmodules RUN make && v -version && ls -la v && \ du -b -s . && \ time v doctor && \ time v cmd/tools/vfmt.v && \ time v -prod self && \ true RUN find . -type f -name *_test.v -or -name *.vv -or -name *.out | xargs rm && \ rm -rf v_old vc/ .git/ && \ du -b -s . CMD ["v"] ================================================ FILE: Dockerfile.cross ================================================ FROM mstorsjo/llvm-mingw LABEL maintainer="Delyan Angelov " COPY . . RUN make RUN ./v -os windows -o v.c cmd/v RUN x86_64-w64-mingw32-gcc v.c -std=c99 -w -municode -o v.exe -lws2_32 RUN file v.exe CMD [ "bash" ] ================================================ FILE: GNUmakefile ================================================ CC ?= cc CFLAGS ?= LDFLAGS ?= TMPDIR ?= /tmp VROOT ?= . VC ?= ./vc VEXE ?= ./v VCREPO ?= https://github.com/vlang/vc TCCREPO ?= https://github.com/vlang/tccbin LEGACYREPO ?= https://github.com/macports/macports-legacy-support GIT ?= git VCFILE := v.c TMPTCC := $(VROOT)/thirdparty/tcc LEGACYLIBS := $(VROOT)/thirdparty/legacy TMPLEGACY := $(LEGACYLIBS)/source TCCOS := unknown TCCARCH := unknown HAS_GIT := $(shell command -v $(GIT) >/dev/null 2>&1 && echo 1 || echo 0) GITCLEANPULL := $(GIT) clean -xf && $(GIT) pull --quiet GITFASTCLONE := $(GIT) clone --filter=blob:none --quiet #### Platform detections and overrides: _SYS := $(shell uname 2>/dev/null || echo Unknown) _SYS := $(patsubst MSYS%,MSYS,$(_SYS)) _SYS := $(patsubst MINGW%,MinGW,$(_SYS)) ifneq ($(filter $(_SYS),MSYS MinGW),) WIN32 := 1 EXE_EXT := .exe endif ifeq ($(_SYS),Linux) LINUX := 1 TCCOS := linux ifneq ($(shell ldd --version 2>&1 | grep -i musl),) TCCOS := linuxmusl endif endif ifeq ($(_SYS),Darwin) MAC := 1 TCCOS := macos ifeq ($(shell expr $(shell uname -r | cut -d. -f1) \<= 15), 1) LEGACY := 1 CFLAGS += -I$(LEGACYLIBS)/include/LegacySupport LDFLAGS += -L$(LEGACYLIBS)/lib LDFLAGS += -lMacportsLegacySupport VFLAGS += -cc $(CC) VFLAGS += -cflags "$(CFLAGS)" VFLAGS += -ldflags -L$(LEGACYLIBS)/lib VFLAGS += -cflags $(LEGACYLIBS)/lib/libMacportsLegacySupport.a endif endif ifeq ($(_SYS),FreeBSD) TCCOS := freebsd LDFLAGS += -lexecinfo endif ifeq ($(_SYS),NetBSD) NETBSD := 1 TCCOS := netbsd LDFLAGS += -lexecinfo endif ifeq ($(_SYS),OpenBSD) TCCOS := openbsd LDFLAGS += -lexecinfo endif ifdef ANDROID_ROOT ANDROID := 1 undefine LINUX TCCOS := android endif ##### ifdef WIN32 TCCOS := windows endif TCCARCH := $(shell uname -m 2>/dev/null || echo unknown) ifeq ($(TCCARCH),x86_64) TCCARCH := amd64 else ifneq ($(filter x86%,$(TCCARCH)),) TCCARCH := i386 else ifeq ($(TCCARCH),arm64) TCCARCH := arm64 else ifneq ($(filter arm%,$(TCCARCH)),) TCCARCH := arm # otherwise, just use the arch name endif endif endif endif .PHONY: all clean rebuild check fresh_vc fresh_tcc fresh_legacy check_for_working_tcc etags ctags ifdef prod VFLAGS+=-prod endif # Keep bootstrap C compiler/linker flags aligned with the initial `v1` build. BOOTSTRAP_VFLAGS := $(if $(strip $(CFLAGS)),-cflags "$(CFLAGS)") $(if $(strip $(LDFLAGS)),-ldflags "$(LDFLAGS)") all: latest_vc latest_tcc latest_legacy ifdef WIN32 $(CC) $(CFLAGS) -std=c99 -municode -w -o v1$(EXE_EXT) $(VC)/$(VCFILE) $(LDFLAGS) -lws2_32 || cmd/tools/cc_compilation_failed_windows.sh ./v1$(EXE_EXT) -no-parallel -o v2$(EXE_EXT) $(VFLAGS) $(BOOTSTRAP_VFLAGS) cmd/v ./v2$(EXE_EXT) -o $(VEXE)$(EXE_EXT) $(VFLAGS) $(BOOTSTRAP_VFLAGS) cmd/v $(RM) v1$(EXE_EXT) $(RM) v2$(EXE_EXT) else ifdef LEGACY $(MAKE) -C $(TMPLEGACY) $(MAKE) -C $(TMPLEGACY) PREFIX=$(realpath $(LEGACYLIBS)) CFLAGS=$(CFLAGS) LDFLAGS=$(LDFLAGS) install rm -rf $(TMPLEGACY) $(eval override LDFLAGS+=-L$(realpath $(LEGACYLIBS))/lib -lMacportsLegacySupport) endif $(CC) $(CFLAGS) -std=c99 -w -o v1$(EXE_EXT) $(VC)/$(VCFILE) -lm -lpthread $(LDFLAGS) || cmd/tools/cc_compilation_failed_non_windows.sh ifdef NETBSD paxctl +m v1$(EXE_EXT) endif ./v1$(EXE_EXT) -no-parallel -o v2$(EXE_EXT) $(VFLAGS) $(BOOTSTRAP_VFLAGS) cmd/v ifdef NETBSD paxctl +m v2$(EXE_EXT) endif ./v2$(EXE_EXT) -nocache -o $(VEXE)$(EXE_EXT) $(VFLAGS) $(BOOTSTRAP_VFLAGS) cmd/v ifdef NETBSD paxctl +m $(VEXE)$(EXE_EXT) endif rm -rf v1$(EXE_EXT) v2$(EXE_EXT) endif @$(VEXE)$(EXE_EXT) run cmd/tools/detect_tcc.v @echo "V has been successfully built" @$(VEXE)$(EXE_EXT) -version @$(VEXE)$(EXE_EXT) run .github/problem-matchers/register_all.vsh clean: rm -rf $(TMPTCC) rm -rf $(LEGACYLIBS) rm -rf $(VC) rebuild: clean all ifndef local latest_vc: $(VC)/.git/config ifeq ($(HAS_GIT),1) cd $(VC) && $(GITCLEANPULL) else @echo "git not found; using existing $(VC)/$(VCFILE)" endif else latest_vc: @echo "Using local vc" endif check_for_working_tcc: @$(TMPTCC)/tcc.exe --version > /dev/null 2> /dev/null || echo "The executable '$(TMPTCC)/tcc.exe' does not work." fresh_vc: rm -rf $(VC) ifeq ($(HAS_GIT),1) $(GITFASTCLONE) $(VCREPO) $(VC) else @echo "git is required to clone $(VCREPO) into $(VC)" @exit 1 endif ifndef local latest_tcc: $(TMPTCC)/.git/config ifeq ($(HAS_GIT),1) cd $(TMPTCC) && $(GITCLEANPULL) else @echo "git not found; skipping update of $(TMPTCC)" endif ifneq (,$(wildcard ./tcc.exe)) @$(MAKE) --quiet check_for_working_tcc 2> /dev/null endif else latest_tcc: @echo "Using local tcc" @$(MAKE) --quiet check_for_working_tcc 2> /dev/null endif fresh_tcc: rm -rf $(TMPTCC) ifndef local ifeq ($(HAS_GIT),1) # Check whether a TCC branch exists for the user's system configuration. ifneq (,$(findstring thirdparty-$(TCCOS)-$(TCCARCH), $(shell $(GIT) ls-remote --heads $(TCCREPO) | sed 's/^[a-z0-9]*\trefs.heads.//'))) $(GITFASTCLONE) --branch thirdparty-$(TCCOS)-$(TCCARCH) $(TCCREPO) $(TMPTCC) @$(MAKE) --quiet check_for_working_tcc 2> /dev/null else @echo 'Pre-built TCC not available for thirdparty-$(TCCOS)-$(TCCARCH) at $(TCCREPO), will use the system compiler: $(CC)' $(GITFASTCLONE) --branch thirdparty-unknown-unknown $(TCCREPO) $(TMPTCC) endif else @echo "git is required to clone $(TCCREPO)" @exit 1 endif else @echo "Using local tccbin" @$(MAKE) --quiet check_for_working_tcc 2> /dev/null endif ifndef local latest_legacy: $(TMPLEGACY)/.git/config ifdef LEGACY ifeq ($(HAS_GIT),1) cd $(TMPLEGACY) && $(GITCLEANPULL) else @echo "git not found; using existing $(TMPLEGACY)" endif endif else latest_legacy: ifdef LEGACY @echo "Using local legacysupport" endif endif fresh_legacy: rm -rf $(LEGACYLIBS) ifeq ($(HAS_GIT),1) $(GITFASTCLONE) $(LEGACYREPO) $(TMPLEGACY) else @echo "git is required to clone $(LEGACYREPO)" @exit 1 endif $(TMPTCC)/.git/config: ifeq ($(HAS_GIT),1) $(MAKE) fresh_tcc else @echo "git not found; skipping bootstrap of $(TMPTCC), system compiler $(CC) will be used" endif $(VC)/.git/config: ifeq ($(HAS_GIT),1) $(MAKE) fresh_vc else @if [ -f "$(VC)/$(VCFILE)" ]; then \ echo "git not found; using existing $(VC)/$(VCFILE)"; \ else \ echo "git is required to download $(VC)/$(VCFILE). Install git or provide the file manually."; \ exit 1; \ fi endif $(TMPLEGACY)/.git/config: ifdef LEGACY ifeq ($(HAS_GIT),1) $(MAKE) fresh_legacy else @if [ -d "$(TMPLEGACY)" ]; then \ echo "git not found; using existing $(TMPLEGACY)"; \ else \ echo "git is required to download legacy support sources ($(LEGACYREPO))"; \ exit 1; \ fi endif endif asan: $(MAKE) all CFLAGS='-fsanitize=address,undefined' selfcompile: $(VEXE)$(EXE_EXT) -cg -o v cmd/v selfcompile-static: $(VEXE)$(EXE_EXT) -cg -cflags '--static' -o v-static cmd/v ### NB: Please keep this Makefile and make.bat simple. install: @echo 'Please use `sudo ./v symlink` instead, or manually add the current directory to your PATH.' check: $(VEXE)$(EXE_EXT) test-all etags: ./v$(EXE_EXT) -print-v-files cmd/v | grep -v :parse_text| etags -L - ctags: ./v$(EXE_EXT) -print-v-files cmd/v | grep -v :parse_text| ctags -L - ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2019-2024 Alexander Medvednikov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Makefile ================================================ CC ?= cc VFLAGS ?= CFLAGS ?= LDFLAGS ?= BOOTSTRAP_VFLAGS := $(if $(strip $(CFLAGS)),-cflags "$(CFLAGS)") $(if $(strip $(LDFLAGS)),-ldflags "$(LDFLAGS)") .PHONY: all check download_vc v all: download_vc v download_vc: if [ -f vc/v.c ] ; then \ if command -v git >/dev/null 2>&1 ; then \ git -C vc/ pull; \ else \ echo "git not found; using existing vc/v.c"; \ fi; \ else \ if command -v git >/dev/null 2>&1 ; then \ git clone --filter=blob:none https://github.com/vlang/vc vc/; \ else \ echo "git is required to download vc/. Please install git or provide vc/v.c."; \ exit 1; \ fi; \ fi v: $(CC) $(CFLAGS) -std=gnu11 -w -o v1 vc/v.c -lm -lexecinfo -lpthread $(LDFLAGS) || cmd/tools/cc_compilation_failed_non_windows.sh ./v1 -no-parallel -o v2 $(VFLAGS) $(BOOTSTRAP_VFLAGS) cmd/v ./v2 -o v $(VFLAGS) $(BOOTSTRAP_VFLAGS) cmd/v rm -rf v1 v2 ./v run ./cmd/tools/detect_tcc.v @echo "V has been successfully built" ./v version ./v run .github/problem-matchers/register_all.vsh check: ./v test-all install: @echo 'Please use `sudo ./v symlink` instead, or manually add the current directory to your PATH.' ================================================ FILE: README.md ================================================

V logo

The V Programming Language

[vlang.io](https://vlang.io) | [Docs](https://github.com/vlang/v/blob/master/doc/docs.md) | [Changelog](https://github.com/vlang/v/blob/master/CHANGELOG.md) | [Speed](https://fast.vlang.io/) | [Contributing & compiler design](https://github.com/vlang/v/blob/master/CONTRIBUTING.md)
[![Sponsor][SponsorBadge]][SponsorUrl] [![Patreon][PatreonBadge]][PatreonUrl] [![Discord][DiscordBadge]][DiscordUrl] [![X][XBadge]][XUrl] [![Modules][ModulesBadge]][ModulesUrl]
## Key Features of V - Simplicity: the language can be learned over the course of a weekend - Fast compilation: ≈110k loc/s with a Clang backend, ≈500k loc/s with native and tcc backends *(Intel i5-7500, SSD, no optimization)* ([demo video](https://www.youtube.com/watch?v=pvP6wmcl_Sc)) - Easy to develop: V compiles itself in less than a second - Performance: as fast as C (V's main backend compiles to human-readable C) - Safety: no null, no globals, no undefined behavior (wip), immutability by default - C to V translation ([Translating DOOM demo video](https://www.youtube.com/watch?v=6oXrz3oRoEg)) - Hot code reloading - [Flexible memory management](https://vlang.io/#memory). GC by default, manual via `v -gc none`, arena allocation via `v -prealloc`, autofree via `v -autofree` ([autofree demo video](https://www.youtube.com/watch?v=gmB8ea8uLsM)). - [Cross-platform UI library](https://github.com/vlang/ui) - Built-in graphics library - Easy cross-compilation - REPL - [Built-in ORM](https://github.com/vlang/v/blob/master/doc/docs.md#orm) - [Built-in web framework](https://github.com/vlang/v/blob/master/vlib/veb/README.md) - C and JavaScript backends - Great for writing low-level software ([Vinix OS](https://github.com/vlang/vinix)) ## Stability, future changes, post 1.0 freeze Despite being at an early development stage, the V language is relatively stable, and doesn't change often. But there will be changes before 1.0. Most changes in the syntax are handled via vfmt automatically. The V core APIs (primarily the `os` module) will also have minor changes until they are stabilized in V 1.0. Of course, the APIs will grow after that, but without breaking existing code. After the 1.0 release V is going to be in the "feature freeze" mode. That means no breaking changes in the language, only bug fixes and performance improvements. Similar to Go. Will there be V 2.0? Not within a decade after 1.0, perhaps not ever. To sum it up, unlike many other languages, V is not going to be always changing, with new features introduced and old features modified. It is always going to be a small and simple language, very similar to the way it is right now. ## Installing V from source **This is the preferred method.** ### Linux, macOS, Windows, \*BSD, Solaris, WSL, etc. Usually, installing V is quite simple if you have an environment that already has a functional `git` installation. Note: On Windows, run `make.bat` instead of `make` in CMD, or `./make.bat` in PowerShell. Note: On Ubuntu/Debian, you may need to run `sudo apt install git build-essential make` first. To get started, execute the following in your terminal/shell: ```bash git clone --depth=1 https://github.com/vlang/v cd v make ``` That should be it, and you should find your V executable at `[path to V repo]/v`. `[path to V repo]` can be anywhere. (Like the note above says, on Windows, use `make.bat`, instead of `make`.) Now try running `./v run examples/hello_world.v` (or `v run examples/hello_world.v` in cmd shell). - *Trouble? Please see the notes above, and link to [Installation Issues](https://github.com/vlang/v/discussions/categories/installation-issues) for help.* Note: V is being constantly updated. To update V to its latest version, simply run: ```bash v up ``` > [!NOTE] > If you run into any trouble, or you have a different operating > system or Linux distribution that doesn't install or work immediately, please see > [Installation Issues](https://github.com/vlang/v/discussions/categories/installation-issues) > and search for your OS and problem. > > If you can't find your problem, please add it to an existing discussion if one exists for > your OS, or create a new one if a main discussion doesn't yet exist for your OS. ### Void Linux ```bash # xbps-install -Su base-devel # xbps-install libatomic-devel $ git clone --depth=1 https://github.com/vlang/v $ cd v $ make ``` ### Docker ```bash git clone --depth=1 https://github.com/vlang/v cd v docker build -t vlang . docker run --rm -it vlang:latest ``` ### Docker with Alpine/musl ```bash git clone --depth=1 https://github.com/vlang/v cd v docker build -t vlang_alpine - < Dockerfile.alpine alias with_alpine='docker run -u 1000:1000 --rm -it -v .:/src -w /src vlang_alpine:latest' ``` Compiling *static* executables, ready to be copied to a server, that is running another linux distro, without dependencies: ```bash with_alpine v -skip-unused -prod -cc gcc -cflags -static -compress examples/http_server.v with_alpine v -skip-unused -prod -cc gcc -cflags -static -compress -gc none examples/hello_world.v ls -la examples/http_server examples/hello_world file examples/http_server examples/hello_world examples/http_server: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, no section header examples/hello_world: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, no section header ``` You should see something like this: ``` -rwxr-xr-x 1 root root 16612 May 27 17:07 examples/hello_world -rwxr-xr-x 1 root root 335308 May 27 17:07 examples/http_server ``` ### FreeBSD On FreeBSD, V needs `boehm-gc-threaded` package preinstalled. After installing it, you can use the same script, like on Linux/macos: ```bash pkg install boehm-gc-threaded git clone --depth=1 https://github.com/vlang/v cd v make ``` ### OpenBSD On OpenBSD (release 7.8), V needs `boehm-gc` and `openssl-3.5` packages preinstalled. After installing them, use GNU `make` (installed with `gmake` package), to build V. ```bash pkg_add boehm-gc openssl%3.5 gmake git clone --depth=1 https://github.com/vlang/v cd v gmake ``` ### Termux/Android On Termux, V needs some packages preinstalled - a working C compiler, also `libexecinfo`, `libgc` and `libgc-static`. After installing them, you can use the same script, like on Linux/macos: ```bash pkg install clang libexecinfo libgc libgc-static make git pkg update git clone --depth=1 https://github.com/vlang/v cd v make ./v symlink ``` Note: there is *no* need for `sudo ./v symlink` on Termux (and sudo is not installed by default). ### C compiler The [Tiny C Compiler (tcc)](https://repo.or.cz/w/tinycc.git) is downloaded for you by `make` if there is a compatible version for your system, and installed under the V `thirdparty` directory. This compiler is very fast, but does almost no optimizations. It is best for development builds. For production builds (using the `-prod` option to V), it's recommended to use clang, gcc, or Microsoft Visual C++. If you are doing development, you most likely already have one of those installed. Otherwise, follow these instructions: - [Installing a C compiler on Linux and macOS](https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Linux-and-macOS) - [Installing a C compiler on Windows](https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Windows) ### Symlinking > [!NOTE] > It is *highly recommended*, that you put V on your PATH. That saves > you the effort to type in the full path to your v executable every time. > V provides a convenience `v symlink` command to do that more easily. On Unix systems, it creates a `/usr/local/bin/v` symlink to your executable. To do that, run: ```bash sudo ./v symlink ``` On Windows, start a new shell with administrative privileges, for example by pressing the Windows Key, then type `cmd.exe`, right-click on its menu entry, and choose `Run as administrator`. In the new administrative shell, cd to the path where you have compiled V, then type: ```bat v symlink ``` (or `.\v symlink` in PowerShell) That will make V available everywhere, by adding it to your PATH. Please restart your shell/editor after that, so that it can pick up the new PATH variable. > [!NOTE] > There is no need to run `v symlink` more than once - v will still be available, even after > `v up`, restarts, and so on. You only need to run it again if you decide to move the V repo > folder somewhere else. ## Editor/IDE Plugins - [Atom](https://github.com/vlang/awesome-v#atom) - [Emacs](https://github.com/vlang/awesome-v#emacs) - [JetBrains](https://plugins.jetbrains.com/plugin/20287-vlang/docs/syntax-highlighting.html) - [Sublime Text 3](https://github.com/vlang/awesome-v#sublime-text-3) - [Vim](https://github.com/vlang/awesome-v#vim) - [Vim/Neovim Runtime Files](editors/vim) - [VS Code](https://marketplace.visualstudio.com/items?itemName=VOSCA.vscode-v-analyzer) - [zed](https://github.com/lv37/zed-v) To bring IDE functions for the V programming languages to your editor, check out [v-analyzer](https://github.com/vlang/v-analyzer). It provides language server capabilities. ## Testing and running the examples Make sure V can compile itself: ```bash $ v self $ v V 0.3.x Use Ctrl-C or `exit` to exit >>> println('hello world') hello world >>> ``` `v self` defaults to `-gc none`. Pass `-gc ` if you need a different GC mode. ```bash cd examples v hello_world.v && ./hello_world # or simply v run hello_world.v # this builds the program and runs it right away v run word_counter/word_counter.v word_counter/cinderella.txt v run news_fetcher.v v run tetris/tetris.v ``` When a project has a `.vvmrc` file, `v ` and `v run ` try to use the requested V binary (for example `v0.4.6`) before falling back to the current compiler. tetris screenshot ## Sokol and GG GUI apps/games: In order to build Tetris or 2048 (or anything else using the `sokol` or `gg` graphics modules), you will need to install additional development libraries for your system. | System | Installation method | |---------------------|----------------------------------------------------------------------------------------------------| | Debian/Ubuntu based | Run `sudo apt install libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev` | | Fedora/RH/CentOS | Run `sudo dnf install libXi-devel libXcursor-devel libX11-devel libXrandr-devel libglvnd-devel` | | | | | NixOS | Add `xorg.libX11.dev xorg.libXcursor.dev xorg.libXi.dev xorg.libXrandr.dev libGL.dev` to | | | to `environment.systemPackages` | ## V net.http, net.websocket, `v install` The net.http module, the net.websocket module, and the `v install` command may all use SSL. V comes with a version of mbedtls, which should work on all systems. If you find a need to use OpenSSL instead, you will need to make sure that it is installed on your system, then use the `-d use_openssl` switch when you compile. Note: Mbed-TLS is smaller and easier to install on windows too (V comes with it), but if you write programs, that do lots of http requests to HTTPS/SSL servers, in most cases, it is *best* to compile with `-d use_openssl`, and do so on a system, where you do have OpenSSL installed (see below). Mbed-TLS is slower, and can have more issues, especially when you are doing parallel http requests to multiple hosts (for example in web scrapers, REST API clients, RSS readers, etc). On windows, it is better to run such programs in WSL2. To install OpenSSL on non-Windows systems: | System | Installation command | |---------------------|----------------------------------| | macOS | `brew install openssl` | | Debian/Ubuntu based | `sudo apt install libssl-dev` | | Arch/Manjaro | openssl is installed by default | | Fedora/CentOS/RH | `sudo dnf install openssl-devel` | On Windows, OpenSSL is simply hard to get working correctly. The instructions [here](https://tecadmin.net/install-openssl-on-windows/) may (or may not) help. ## V sync V's `sync` module and channel implementation uses libatomic. It is most likely already installed on your system, but if not, you can install it, by doing the following: | System | Installation command | |---------------------|-------------------------------------| | macOS | already installed | | Debian/Ubuntu based | `sudo apt install libatomic1` | | Fedora/CentOS/RH | `sudo dnf install libatomic-static` | ## V UI V UI example screenshot https://github.com/vlang/ui ## Android graphical apps With V's `vab` tool, building V UI and graphical apps for Android can become as easy as: ``` ./vab /path/to/v/examples/2048 ``` [https://github.com/vlang/vab](https://github.com/vlang/vab). vab examples screenshot ## Developing web applications Check out the [Building a simple web blog](https://github.com/vlang/v/blob/master/tutorials/building_a_simple_web_blog_with_veb/README.md) tutorial and Gitly, a light and fast alternative to GitHub/GitLab: https://github.com/vlang/gitly gitly screenshot ## Vinix, an OS/kernel written in V V is great for writing low-level software like drivers and kernels. Vinix is an OS/kernel that already runs bash, GCC, V, and nano. https://github.com/vlang/vinix vinix screenshot 1 vinix screenshot 2 ## Acknowledgement ### TCC V thanks Fabrice Bellard for his original work on the [TCC - Tiny C Compiler](https://bellard.org/tcc/). Note the TCC website is old; the current TCC repository can be found [here](https://repo.or.cz/w/tinycc.git). V utilizes pre-built TCC binaries located at [https://github.com/vlang/tccbin/](https://github.com/vlang/tccbin/). ### PVS-Studio [PVS-Studio](https://pvs-studio.com/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source) - static analyzer for C, C++, C#, and Java code. ## Troubleshooting Please see the [Troubleshooting](https://github.com/vlang/v/wiki/Troubleshooting) section on our [wiki page](https://github.com/vlang/v/wiki). [WorkflowBadge]: https://github.com/vlang/v/workflows/CI/badge.svg [DiscordBadge]: https://img.shields.io/discord/592103645835821068?label=Discord&logo=discord&logoColor=white [PatreonBadge]: https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.vercel.app%2Fapi%3Fusername%3Dvlang%26type%3Dpatrons&style=flat [SponsorBadge]: https://img.shields.io/github/sponsors/medvednikov?style=flat&logo=github&logoColor=white [XBadge]: https://img.shields.io/badge/follow-%40v__language-1DA1F2?logo=x&style=flat&logoColor=white [ModulesBadge]: https://img.shields.io/badge/modules-reference-027d9c?logo=v&logoColor=white&logoWidth=10 [WorkflowUrl]: https://github.com/vlang/v/commits/master [DiscordUrl]: https://discord.gg/vlang [PatreonUrl]: https://patreon.com/vlang [SponsorUrl]: https://github.com/sponsors/medvednikov [XUrl]: https://x.com/v_language [ModulesUrl]: https://modules.vlang.io ================================================ FILE: ROADMAP.md ================================================ Roadmap with big features. For a list of all features and fixes, check out the changelog. ## [Version 0.3] - [x] gc option - [x] channels - [x] lock{} - [x] thread safe arrays - [x] rune type - [x] replace `ustring` with `[]rune` - [x] fix `byte.str()` - [x] maps with non-string keys - [x] iOS/Android support - [x] parallel cgen - [x] IO streams - [x] struct embedding - [x] interface embedding - [x] interfaces: allow struct fields (not just methods) - [x] short generics syntax (`foo(5)` instead of `foo(5)`) - [x] more advanced errors, not just `error('message')` ## [Version 0.4] - [x] [Coroutines](https://github.com/vlang/v/discussions/11582) (doesn't work on Windows yet) - [x] vfmt: add missing imports (like goimports) - [x] Recursive structs via options: `struct Node { next ?Node }` - [x] First class Option type - [x] Optional function struct fields - [x] Handle function pointers safely, remove `if function == 0 {` - [x] Bundle an SSL library (mbedtls) like GC - [x] Anonymous structs - [x] Improve vweb: allow separation of logic via "controllers", lots of other fixes - [x] New VPM site ## [Version 0.5] - [x] Parallel C compilation via `-parallel-cc` - [x] Parallel parser (not integrated yet) - [x] Parallel checker (not integrated yet) - [x] Improved vweb => veb framework. Separation of global and context (request local) fields. Performance and stability. Based on picoev. - [x] -skip-unused on by default - [x] Lambdas: `a.sort(|a, b| a > b)` - [x] Implicit Veb contexts passed to requests - [x] Direct C/C++ interop without generating wrappers (via -experimental for now) - [x] Allow `$if` everywhere: top level, inside struct definitions, etc ## [Version 0.6] - [ ] Custom attributes - [ ] Contexts that are passed implicitly (e.g. for custom allocation/memory management) - [ ] 64/32 bit int depending on arch (will remove array.len limitation on 64 bit systems) - [ ] `copy()` builtin function (e.g. for easier conversion from `[]Foo` to `[4]Foo`) - [ ] Integrate the new parallel parser/checker/cc - [ ] Incremental compilation - [ ] Runtime race detector - [ ] [Thread safe maps](https://github.com/vlang/v/discussions/11729) - [ ] `recover()` from panics - [ ] -usecache on by default - [ ] ORM migrations - [ ] Make ORM work without installing developer libs (libpq-dev etc) ## [Version 1.0] - [ ] Cross compilation of C - [ ] Big remaining bugs fixed - [ ] More powerful comptime - [ ] Constraints for generics - [ ] Coroutines on Windows - [ ] Autofree memory management option ready for production - [ ] C2V supporting entire C99 standard - [ ] [Shared compiled libs](https://github.com/vlang/rfcs/issues/27) ### Tooling - [ ] More stable VLS - [ ] Profiler improvements - [ ] Basic interactive shell with search, sort, filter, etc. - [ ] VPM - [x] New VPM site - [ ] Package versioning - [ ] A better documentation platform ### Web - [ ] Site that brings everything together in a single style - [ ] Interactive educational platform (learning to program for beginners) ================================================ FILE: TESTS.md ================================================ # Automated tests TLDR: do run `v test-all` locally, after making your changes, and before submitting PRs. Tip: use `v -cc tcc` when compiling tests, because TCC is much faster, compared to most other C compilers like clang/gcc/msvc. Most test commands will use the V compiler and the V tools many times, potentially hundreds/thousands of times. ## `v test-all` Test and build *everything*. Useful to verify *locally*, that the CI will most likely pass. Slowest, but most comprehensive. It works, by running these in succession: * `v test-cleancode` * `v test-self` * `v test-fmt` * `v build-tools` * `v build-examples` * `v check-md -hide-warnings .` * `v install nedpals.args` # Details: In the `v` repo there are many tests. The main types are: ## `_test.v` tests - these are the normal V test files. All `test_` functions in these files, will be ran automatically by V's test framework. NB 1: You can run test files one by one, with: `v file_test.v` - this will run the test_ functions in file_test.v, and will exit with a 0 exit code, if they all had 0 failing assertions. `v -stats file_test.v` - this will run the test_ functions, and show a report about how much time it took to run each of them too. NB 2: You can also run many test files at once (in parallel, depending on how many cores you have), with: `v test folder` - this will run *all* `_test.v` files in `folder`, recursively. `v -stats test folder` - same, but will also produce timing reports about how fast each test_ function in each _test.v file ran. ## `v test vlib/v/tests`: This folder contains _test.v files, testing the different features of the V compiler. Each of them will be compiled, and all the features in them have to work (verified by assertions). ## `v vlib/v/slow_tests/inout/compiler_test.v` This is a *test runner*, that checks whether the output of running a V program, matches an expected .out file. You can also check for code that does panic using this test runner - just paste the start of the `panic()` output in the corresponding .out file. > [!NOTE] > These tests, expect to find a pair of `.vv` and `.out` files, in the folder: > vlib/v/slow_tests/inout The test runner will run each `.vv` file, and will check that its output, matches the contents of the `.out` file with the same base name. This is particularly useful for checking that errors and panics are printed. ## `v vlib/v/gen/c/coutput_test.v` coutput_test.v is a *test runner*, that checks whether the generated C source code matches *all* expectations, specified in *.c.must_have files, in the folder vlib/v/gen/c/testdata/ . Each `.c.must_have` file, *has* to have a corresponding `.vv` file. Each `.c.must_have` file, consists of multiple lines. Each of these lines, *should* be present *at least once* in the output, when the .vv file is compiled with `-o -` . ## REPL tests The test runner for these is `vlib/v/slow_tests/repl/repl_test.v`. The test cases for the V REPL, are stored in .repl files, in the folder `vlib/v/slow_tests/repl/`. Each .repl file in this folder, contains several lines of input to the V repl, followed by a single line of `===output===`, and then the output lines, that the repl would normally show for the input lines. If you change the compiler or the REPL source, and you have breaks in those .repl files, you can replace the current output in them, by running several times `VAUTOFIX=1 ./vlib/v/slow_tests/repl/repl_test.v`, until all the files are fixed and the test pass. ## `v vlib/v/slow_tests/run_project_folders_test.v` This *test runner*, checks whether whole project folders, can be compiled, and run. > [!NOTE] > Each project in these folders, should finish with an exit code of 0, > and it should output `OK` as its last stdout line. ## `v vlib/v/tests/known_errors/known_errors_test.v` This *test runner*, checks whether a known program, that was expected to compile, but did NOT, due to a buggy checker, parser or cgen, continues to fail. The negative programs are collected in the `vlib/v/tests/known_errors/testdata/` folder. Each of them should FAIL to compile, due to a known/confirmed compiler bug/limitation. The intended use of this, is for providing samples, that currently do NOT compile, but that a future compiler improvement WILL be able to compile, and to track, whether they were not fixed incidentally, due to an unrelated change/improvement. For example, code that triggers generating invalid C code can go here, and later when a bug is fixed, can be moved to a proper _test.v or .vv/.out pair, outside of the `vlib/v/tests/known_errors/testdata/` folder. ## Test building of actual V programs (examples, tools, V itself) * `v build-tools` * `v build-examples` * `v build-vbinaries` ## Formatting tests In `vlib/v/fmt/` there are: * `v vlib/v/fmt/fmt_test.v` This checks `.out` tests. * `v vlib/v/fmt/fmt_keep_test.v` This verifies that all `_keep.vv` files in the `vlib/v/fmt/tests/` folder, would be unchanged by `v fmt -w`, i.e. that the v source code formatter, generates a stable source output, that does not change, once it is already formatted once. * `v vlib/v/fmt/fmt_vlib_test.v` This checks that all V source files are formatted, and prints a summary. This is not required. * `v test-cleancode` Check that most .v files, are invariant of `v fmt` runs. * `v test-fmt` This tests that all .v files in the current folder are already formatted. It is useful for adding to CI jobs, to guarantee, that future contributions will keep the existing source nice and clean. ## Markdown/documentation checks: * `v check-md -hide-warnings .` Ensure that all .md files in the project are formatted properly, and that the V code block examples in them can be compiled/formatted too. Note: if that command finds formatting errors, they can be fixed with: `VAUTOFIX=1 ./v check-md file.md` or with `v check-md -fix file.md`. ## `v test-self` Run `vlib` module tests, *including* the compiler tests. ## `v vlib/v/compiler_errors_test.v` This runs tests for: * `vlib/v/scanner/tests/*.vv` * `vlib/v/checker/tests/*.vv` * `vlib/v/parser/tests/*.vv` > [!NOTE] > There are special folders, that compiler_errors_test.v will try to > run/compile with specific options: vlib/v/checker/tests/globals_run/ - `-enable-globals run`; results stored in `.run.out` files, matching the .vv ones. NB 2: in case you need to modify many .out files, run *twice* in a row: `VAUTOFIX=1 ./v vlib/v/compiler_errors_test.v` This will fail the first time, but it will record the new output for each .vv file, and store it into the corresponding .out file. The second run should be now successful, and so you can inspect the difference, and commit the new .out files with minimum manual effort. NB 3: To run only some of the tests, use: `VTEST_ONLY=mismatch ./v vlib/v/compiler_errors_test.v` This will check only the .vv files, whose paths match the given filter. NB 4: To run tests, but without printing status lines for all the successfull ones, use: `VTEST_HIDE_OK=1 ./v test vlib/math/` This will print only the total stats, and the failing tests, but otherwise it will be silent. It is useful, when you have hundreds or thousands of individual `_test.v` files, and you want to avoid scrolling. NB 5: To show only *the currently running test*, use: `./v -progress test vlib/math/` In this mode, the output lines will be limited, no matter how many `_test.v` files there are. The output will contain the total stats and the output of the failing tests too. ## `.github/workflows/ci.yml` This is a Github Actions configuration file, that runs various CI tests in the main V repository, for example: * `v vet vlib/v` - run a style checker. * `v test-self` (run self tests) in various compilation modes. > [!NOTE] The VDOC test vdoc_file_test.v now also supports VAUTOFIX, which is useful, if you change anything inside cmd/tools/vdoc, or inside the modules that it depends on (like markdown). After such changes, just run this command *2 times*, and commit the resulting changes in `cmd/tools/vdoc/testdata` as well: `VAUTOFIX=1 ./v cmd/tools/vdoc/vdoc_file_test.v` ================================================ FILE: bench/README.md ================================================ ### Vectors ```bash Benchmark 1: ./boids_test/bin/Release/net7.0/linux-x64/publish/boids_test Time (mean ± σ): 262.2 ms ± 5.7 ms [User: 231.6 ms, System: 14.1 ms] Range (min … max): 255.4 ms … 275.3 ms 11 runs Benchmark 2: ./vinted_report_generator/main Time (mean ± σ): 208.3 ms ± 1.9 ms [User: 205.4 ms, System: 1.6 ms] Range (min … max): 204.9 ms … 210.6 ms 14 runs Summary ./vinted_report_generator/main ran 1.26 ± 0.03 times faster than ./boids_test/bin/Release/net7.0/linux-x64/publish/boids_test ``` ================================================ FILE: bench/bench_closure.v ================================================ module main import time import sync import os import runtime import v.util.version // Define closure type alias type ClosureFN = fn () int // Test closures with different capture sizes fn create_closure_small() ClosureFN { a := 0 return fn [a] () int { return a } } fn create_closure_medium() ClosureFN { a, b, c, d := 1, 2, 3, 4 return fn [a, b, c, d] () int { return a + b - c * d } } struct LargeData { array [10]int } fn create_closure_large() ClosureFN { data := LargeData{ array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]! } return fn [data] () int { mut sum := 0 for i in 0 .. 10 { sum += data.array[i] } return sum } } // Result structs struct TestResult { test_name string iterations int time_ms i64 ops_per_sec f64 // Operations per second notes string } struct MemoryResult { test_name string count int start_mem_kb int end_mem_kb int delta_kb int bytes_per_closure int check_sum int } // Benchmark group - returns result structs fn benchmark_closure_creation(iterations int) []TestResult { mut results := []TestResult{} // Test small closure creation mut start := time.ticks() for _ in 0 .. iterations { _ = create_closure_small() } small_time := time.ticks() - start mut ops_per_sec := f64(iterations) * 1000.0 / f64(small_time) results << TestResult{'Small Closure Creation', iterations, small_time, ops_per_sec, ''} // Test medium closure creation start = time.ticks() for _ in 0 .. iterations { _ = create_closure_medium() } medium_time := time.ticks() - start ops_per_sec = f64(iterations) * 1000.0 / f64(medium_time) results << TestResult{'Medium Closure Creation', iterations, medium_time, ops_per_sec, ''} // Test large closure creation large_iter := iterations / 10 start = time.ticks() for _ in 0 .. large_iter { _ = create_closure_large() } large_time := time.ticks() - start ops_per_sec = f64(large_iter) * 1000.0 / f64(large_time) results << TestResult{'Large Closure Creation', large_iter, large_time, ops_per_sec, ''} //, "Equivalent iterations: ${iterations/10}"} return results } fn benchmark_closure_call(iterations int) []TestResult { mut results := []TestResult{} closure_small := create_closure_small() closure_medium := create_closure_medium() closure_large := create_closure_large() // Test small closure call mut start := time.ticks() for _ in 0 .. iterations { _ = closure_small() } small_time := time.ticks() - start mut ops_per_sec := f64(iterations) * 1000.0 / f64(small_time) results << TestResult{'Small Closure Call', iterations, small_time, ops_per_sec, ''} // Test medium closure call start = time.ticks() for _ in 0 .. iterations { _ = closure_medium() } medium_time := time.ticks() - start ops_per_sec = f64(iterations) * 1000.0 / f64(medium_time) results << TestResult{'Medium Closure Call', iterations, medium_time, ops_per_sec, ''} // Test large closure call large_iter := iterations / 10 start = time.ticks() for _ in 0 .. large_iter { _ = closure_large() } large_time := time.ticks() - start ops_per_sec = f64(large_iter) * 1000.0 / f64(large_time) results << TestResult{'Large Closure Call', large_iter, large_time, ops_per_sec, ''} return results } fn benchmark_threaded_creation(threads int, iterations_per_thread int) TestResult { total_iterations := threads * iterations_per_thread mut wg := sync.new_waitgroup() wg.add(threads) start := time.ticks() for _ in 0 .. threads { go fn [mut wg, iterations_per_thread] () { defer { wg.done() } for _ in 0 .. iterations_per_thread { _ = create_closure_medium() } }() } wg.wait() elapsed := time.ticks() - start ops_per_sec := f64(total_iterations) * 1000.0 / f64(elapsed) return TestResult{ test_name: 'Multi-threaded Creation' iterations: total_iterations time_ms: elapsed ops_per_sec: ops_per_sec notes: 'Threads: ${threads} Iterations per thread: ${iterations_per_thread}' } } fn baseline_call_performance(iterations int) TestResult { start := time.ticks() for _ in 0 .. iterations { _ = normal_function() } elapsed := time.ticks() - start ops_per_sec := f64(iterations) * 1000.0 / f64(elapsed) return TestResult{ test_name: 'Normal Function Call' iterations: iterations time_ms: elapsed ops_per_sec: ops_per_sec notes: 'Baseline' } } fn benchmark_memory_usage(count int) MemoryResult { mut closures := []ClosureFN{} start_mem := runtime.used_memory() or { panic(err) } for i in 0 .. count { the_closure := create_closure_medium() closures << the_closure if i % 1000 == 0 { _ = the_closure() } } end_mem := runtime.used_memory() or { panic(err) } delta := int(end_mem) - int(start_mem) bytes_per_closure := delta / count // Calculate verification sum mut check_sum := 0 n := if closures.len < 100 { closures.len } else { 100 } for idx in 0 .. n { check_sum += closures[idx]() } return MemoryResult{ test_name: 'Closure Memory Overhead' count: count start_mem_kb: int(start_mem / 1024) end_mem_kb: int(end_mem / 1024) delta_kb: delta / 1024 bytes_per_closure: bytes_per_closure check_sum: check_sum } } fn normal_function() int { return 42 } // Format performance data for readability fn format_perf(ops_per_sec f64) string { if ops_per_sec >= 1_000_000 { return '${ops_per_sec / 1_000_000:5.2f} Mop/s' } else if ops_per_sec >= 1_000 { return '${ops_per_sec / 1_000:5.2f} Kop/s' } else { return '${ops_per_sec:5.2f} op/s' } } fn print_results_table(results []TestResult, title string) { println('|---------------------------|------------|----------|--------------|--------------|') for res in results { perf_str := format_perf(res.ops_per_sec) println('| ${res.test_name:-25} | ${res.iterations:10} | ${res.time_ms:8} | ${perf_str:-12} | ${res.notes:-12} |') } } fn main() { println('# V Language Closure Performance Benchmark Report') // Configurable test parameters base_iter := 100_000_000 // 100 million iterations creation_iter := 10_000_000 // 1 million iterations mem_count := 100_000 threads := 8 thread_iter := 125_000 // Execute tests baseline_result := baseline_call_performance(base_iter) creation_results := benchmark_closure_creation(creation_iter) call_results := benchmark_closure_call(base_iter) thread_result := benchmark_threaded_creation(threads, thread_iter) mem_result := benchmark_memory_usage(mem_count) // Print result tables println('\n## 1. Closure Performance Analysis') println('| Test Name | Iterations | Time(ms) | Ops/sec | Notes |') print_results_table([baseline_result], '1. Performance Baseline') print_results_table(creation_results, '2. Closure Creation Performance') print_results_table(call_results, '3. Closure Call Performance') print_results_table([thread_result], '4. Multi-threaded Performance') // Print memory results println('\n## 2. Memory Overhead Analysis') println('| Test Name | Closure Count | Start Mem(KB) | End Mem(KB) | Delta(KB) | Bytes/Closure |') println('|-------------------------|---------------|---------------|------------|-----------|---------------|') println('| ${mem_result.test_name:-20} | ${mem_result.count:13} | ${mem_result.start_mem_kb:13} | ${mem_result.end_mem_kb:10} | ${mem_result.delta_kb:9} | ${mem_result.bytes_per_closure:13} |') println('\n**Verification Sum: ${mem_result.check_sum}** (Calculated from random sample of 100 closures)') println('\n## Test Environment') println('- V Language Version: ${version.full_v_version(false)}') println('- CPU Cores: ${runtime.nr_cpus()}') println('- System Memory: ${runtime.total_memory()! / 1024 / 1024} MB') println('- Operating System: ${os.user_os()}') println('\n> Test Time: ${time.now().format_ss_micro()}') } ================================================ FILE: bench/bench_gc.v ================================================ // bench_gc.v - Benchmark comparing VGC vs Boehm GC // Run with: v -gc boehm -o bench_boehm bench/bench_gc.v && ./bench_boehm // v -gc vgc -o bench_vgc bench/bench_gc.v && ./bench_vgc import time const n_allocs = 1_000_000 const n_iters = 5 struct Node { mut: left &Node = unsafe { nil } right &Node = unsafe { nil } value int } // Allocate many small objects (typical GC workload) fn bench_small_allocs() { sw := time.new_stopwatch() mut sum := 0 for _ in 0 .. n_allocs { s := 'hello world ${sum}' sum += s.len } elapsed := sw.elapsed() eprintln(' small allocs (${n_allocs}x string): ${elapsed.milliseconds()} ms (sum=${sum})') } // Build a binary tree (tests pointer-heavy allocation) fn make_tree(depth int) &Node { if depth <= 0 { return &Node{ value: 1 } } return &Node{ left: make_tree(depth - 1) right: make_tree(depth - 1) value: depth } } fn tree_sum(n &Node) int { if n == unsafe { nil } { return 0 } return n.value + tree_sum(n.left) + tree_sum(n.right) } fn bench_tree() { sw := time.new_stopwatch() mut total := 0 for _ in 0 .. 10 { t := make_tree(18) total += tree_sum(t) } elapsed := sw.elapsed() eprintln(' tree build+walk (depth=18, 10x): ${elapsed.milliseconds()} ms (sum=${total})') } // Allocate and discard arrays (tests realloc / growing) fn bench_arrays() { sw := time.new_stopwatch() mut total := 0 for _ in 0 .. 100 { mut arr := []int{cap: 16} for j in 0 .. 100_000 { arr << j } total += arr.len } elapsed := sw.elapsed() eprintln(' array grow (100x 100k pushes): ${elapsed.milliseconds()} ms (total=${total})') } fn main() { gc_mode := $if gcboehm ? { 'boehm' } $else $if vgc ? { 'vgc' } $else { 'none' } eprintln('=== GC Benchmark (mode: ${gc_mode}) ===') for iter in 0 .. n_iters { eprintln('--- iteration ${iter + 1}/${n_iters} ---') bench_small_allocs() bench_tree() bench_arrays() } usage := gc_heap_usage() eprintln('--- heap usage ---') eprintln(' heap_size: ${usage.heap_size / 1024} KB') eprintln(' free_bytes: ${usage.free_bytes / 1024} KB') } ================================================ FILE: bench/bench_string_dedup.v ================================================ // Benchmark comparison of four string deduplication methods in V: basic array, pre-allocated array, map, and set module main import time import datatypes // Method 1: Using basic array (no pre-allocation) struct Context1 { mut: used_str []string } fn (mut c Context1) add_used(str string) { if str !in c.used_str { c.used_str << str } } // Method 2: Using pre-allocated array with capacity struct Context2 { mut: used_str []string } fn (mut c Context2) add_used(str string) { if str !in c.used_str { c.used_str << str } } // Method 3: Using map struct Context3 { mut: used_str map[string]bool } fn (mut c Context3) add_used(str string) { c.used_str[str] = true } // Method 4: Using set struct Context4 { mut: used_str datatypes.Set[string] } fn (mut c Context4) add_used(str string) { c.used_str.add(str) } // Generate random test strings fn generate_test_strings(count int, duplicate_ratio f64) []string { mut strs := []string{cap: count} unique_count := int(f64(count) * (1.0 - duplicate_ratio)) // First generate a batch of unique strings for i in 0 .. unique_count { strs << 'str_${i}_${time.ticks()}' // Add timestamp to reduce duplication rate } // The remaining part uses duplicate strings for i in 0 .. (count - unique_count) { strs << strs[i % unique_count] // Cycle through the first half of strings to create duplicates } return strs } fn main() { num_strs := 10000 // Total number of strings duplicate_ratio := 0.3 // Duplicate string ratio (30%) test_strs := generate_test_strings(num_strs, duplicate_ratio) println('Generated test strings: ${test_strs.len} (approximately ${int(duplicate_ratio * 100)}% are duplicates)') // Test method 1: basic array (no pre-allocation) mut ctx1 := Context1{} sw1 := time.new_stopwatch() for str in test_strs { ctx1.add_used(str) } time1 := sw1.elapsed().milliseconds() println('Method 1 (basic array) - Time: ${time1}ms, Final unique strings: ${ctx1.used_str.len}') // Test method 2: pre-allocated array mut ctx2 := Context2{ used_str: []string{cap: num_strs} // Pre-allocate capacity to avoid reallocations } sw2 := time.new_stopwatch() for str in test_strs { ctx2.add_used(str) } time2 := sw2.elapsed().milliseconds() println('Method 2 (pre-allocated array) - Time: ${time2}ms, Final unique strings: ${ctx2.used_str.len}') // Test method 3: map mut ctx3 := Context3{} sw3 := time.new_stopwatch() for str in test_strs { ctx3.add_used(str) } time3 := sw3.elapsed().milliseconds() println('Method 3 (map) - Time: ${time3}ms, Final unique strings: ${ctx3.used_str.len}') // Test method 4: set mut ctx4 := Context4{} sw4 := time.new_stopwatch() for str in test_strs { ctx4.add_used(str) } time4 := sw4.elapsed().milliseconds() println('Method 4 (set) - Time: ${time4}ms, Final unique strings: ${ctx4.used_str.size()}') // Performance comparison println('\nPerformance comparison:') println('Method 2 (pre-allocated array) is ${f64(time1) / f64(time2):.2f} times faster than method 1 (basic array)') println('Method 3 (map) is ${f64(time1) / f64(time3):.2f} times faster than method 1 (basic array)') println('Method 4 (set) is ${f64(time1) / f64(time4):.2f} times faster than method 1 (basic array)') if time3 < time4 { println('Map is slightly faster than set, difference: ${time4 - time3}ms') } else { println('Set is slightly faster than map, difference: ${time3 - time4}ms') } } ================================================ FILE: bench/crypto/ecdsa/ecdsa.c ================================================ #include #include #include #include #include #include #include #include #include #include #define ITERATIONS 1000 #define MESSAGE "Benchmark message" // Function to calculate the difference in microseconds between two timevals long time_diff_microseconds(struct timeval start, struct timeval end) { long seconds = end.tv_sec - start.tv_sec; long useconds = end.tv_usec - start.tv_usec; return seconds * 1000000 + useconds; } int main() { int iterations = ITERATIONS; struct timeval start, end; long total_gen_time = 0; long total_sign_time = 0; long total_verify_time = 0; long avg_gen_time, avg_sign_time, avg_verify_time; // Benchmarking key generation printf("Benchmarking key generation...\n"); for(int i = 0; i < iterations; i++) { gettimeofday(&start, NULL); // Create a new EC_KEY object with the P-256 curve EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if (key == NULL) { fprintf(stderr, "Error creating EC_KEY object.\n"); exit(EXIT_FAILURE); } // Generate the key if (EC_KEY_generate_key(key) != 1) { fprintf(stderr, "Error generating EC key.\n"); EC_KEY_free(key); exit(EXIT_FAILURE); } gettimeofday(&end, NULL); total_gen_time += time_diff_microseconds(start, end); // Free the key EC_KEY_free(key); } avg_gen_time = total_gen_time / iterations; printf("Average key generation time: %ld µs\n", avg_gen_time); // Generate a single key for signing and verification EC_KEY *priv_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if (priv_key == NULL) { fprintf(stderr, "Error creating EC_KEY object.\n"); exit(EXIT_FAILURE); } if (EC_KEY_generate_key(priv_key) != 1) { fprintf(stderr, "Error generating EC key.\n"); EC_KEY_free(priv_key); exit(EXIT_FAILURE); } // Prepare the message hash unsigned char hash[SHA256_DIGEST_LENGTH]; SHA256((unsigned char*)MESSAGE, strlen(MESSAGE), hash); // Benchmarking signing printf("Benchmarking signing...\n"); for(int i = 0; i < iterations; i++) { gettimeofday(&start, NULL); ECDSA_SIG *signature = ECDSA_do_sign(hash, SHA256_DIGEST_LENGTH, priv_key); if (signature == NULL) { fprintf(stderr, "Error signing message.\n"); EC_KEY_free(priv_key); exit(EXIT_FAILURE); } gettimeofday(&end, NULL); total_sign_time += time_diff_microseconds(start, end); // Free the signature ECDSA_SIG_free(signature); } avg_sign_time = total_sign_time / iterations; printf("Average sign time: %ld µs\n", avg_sign_time); // Create a signature for verification benchmarking ECDSA_SIG *signature = ECDSA_do_sign(hash, SHA256_DIGEST_LENGTH, priv_key); if (signature == NULL) { fprintf(stderr, "Error signing message for verification.\n"); EC_KEY_free(priv_key); exit(EXIT_FAILURE); } // Benchmarking verification printf("Benchmarking verification...\n"); for(int i = 0; i < iterations; i++) { gettimeofday(&start, NULL); int verify_status = ECDSA_do_verify(hash, SHA256_DIGEST_LENGTH, signature, priv_key); gettimeofday(&end, NULL); total_verify_time += time_diff_microseconds(start, end); if (verify_status != 1) { fprintf(stderr, "Signature verification failed.\n"); ECDSA_SIG_free(signature); EC_KEY_free(priv_key); exit(EXIT_FAILURE); } } avg_verify_time = total_verify_time / iterations; printf("Average verify time: %ld µs\n", avg_verify_time); // Cleanup ECDSA_SIG_free(signature); EC_KEY_free(priv_key); return 0; } ================================================ FILE: bench/crypto/ecdsa/ecdsa.go ================================================ package main import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "fmt" "time" ) func main() { iterations := 1000 fmt.Println("Benchmarking key generation...") var totalGenTime int64 for i := 0; i < iterations; i++ { start := time.Now() _, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { panic(err) } totalGenTime += time.Since(start).Microseconds() } avgGenTime := totalGenTime / int64(iterations) fmt.Printf("Average key generation time: %d µs\n", avgGenTime) privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { panic(err) } message := []byte("Benchmark message") fmt.Println("Benchmarking signing...") var totalSignTime int64 for i := 0; i < iterations; i++ { start := time.Now() _, _, err := ecdsa.Sign(rand.Reader, privKey, message) if err != nil { panic(err) } totalSignTime += time.Since(start).Microseconds() } avgSignTime := totalSignTime / int64(iterations) fmt.Printf("Average sign time: %d µs\n", avgSignTime) r, s, err := ecdsa.Sign(rand.Reader, privKey, message) if err != nil { panic(err) } pubKey := &privKey.PublicKey fmt.Println("Benchmarking verification...") var totalVerifyTime int64 for i := 0; i < iterations; i++ { start := time.Now() ecdsa.Verify(pubKey, message, r, s) totalVerifyTime += time.Since(start).Microseconds() } avgVerifyTime := totalVerifyTime / int64(iterations) fmt.Printf("Average verify time: %d µs\n", avgVerifyTime) } ================================================ FILE: bench/crypto/ecdsa/ecdsa.v ================================================ import time import crypto.ecdsa fn main() { iterations := 1000 println('Benchmarking key generation...') mut total_gen_time := i64(0) for _ in 0 .. iterations { sw := time.new_stopwatch() _, _ := ecdsa.generate_key() or { panic(err) } elapsed := sw.elapsed().microseconds() total_gen_time += elapsed } avg_gen_time := total_gen_time / iterations println('Average key generation time: ${avg_gen_time} µs') pub_key, priv_key := ecdsa.generate_key() or { panic(err) } message := 'Benchmark message'.bytes() println('Benchmarking signing...') mut total_sign_time := i64(0) for _ in 0 .. iterations { sw := time.new_stopwatch() _ := priv_key.sign(message) or { panic(err) } elapsed := sw.elapsed().microseconds() total_sign_time += elapsed } avg_sign_time := total_sign_time / iterations println('Average sign time: ${avg_sign_time} µs') sig := priv_key.sign(message) or { panic(err) } println('Benchmarking verification...') mut total_verify_time := i64(0) for _ in 0 .. iterations { sw := time.new_stopwatch() _ := pub_key.verify(message, sig) or { panic(err) } elapsed := sw.elapsed().microseconds() total_verify_time += elapsed } avg_verify_time := total_verify_time / iterations println('Average verify time: ${avg_verify_time} µs') } ================================================ FILE: bench/vectors/README.md ================================================ # Comparing C# and V Boids Algorithm Implementations ## Running the C# program: ``` dotnet run ``` Creating a release version of the C# program: ``` dotnet publish -c Release -r ubuntu.20.04-x64 ``` The generated executable will be in `/v/vnew/bench/vectors/bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors` Its size is ~64MB . After stripping, the executable shrinks to just 11MB, but unfortunately it also stops running after stripping :-| . ## Compiling and running the V program: ``` v crun vectors.v ``` ... produces and runs a `vectors` executable which is ~1.3MB in size. Compiling and running the V program, compiled with -prod: ``` v -prod crun vectors.v ``` ... produces and runs a `vectors` executable which is ~176KB in size. After stripping, the executable shrinks to 157KB. It can still run after stripping. Note: using `crun` will make sure that the compilation will happen just once at the start, and then the executable will be just reused by the subsequent commands with identical options. It will also ensure that the compiled executable will not be removed, unlike `run` . ## Some measurements and comparisons Note: the following was done on Intel(R) Core(TM) i3-3225, 16GB RAM: ``` #0 13:41:35 ᛋ master /v/vnew/bench/vectors❱rm -rf vectors #0 13:41:49 ᛋ master /v/vnew/bench/vectors❱ #0 13:41:49 ᛋ master /v/vnew/bench/vectors❱v -o vectors_development vectors.v #0 13:42:14 ᛋ master /v/vnew/bench/vectors❱v -o vectors_production -prod vectors.v #0 13:42:28 ᛋ master /v/vnew/bench/vectors❱ #0 13:42:29 ᛋ master /v/vnew/bench/vectors❱hyperfine ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors ./vectors_development ./vectors_production Benchmark 1: ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors Time (mean ± σ): 347.4 ms ± 7.4 ms [User: 334.4 ms, System: 13.0 ms] Range (min … max): 340.2 ms … 361.7 ms 10 runs Benchmark 2: ./vectors_development Time (mean ± σ): 882.6 ms ± 14.0 ms [User: 880.3 ms, System: 2.3 ms] Range (min … max): 862.4 ms … 912.9 ms 10 runs Benchmark 3: ./vectors_production Time (mean ± σ): 217.9 ms ± 9.4 ms [User: 216.8 ms, System: 0.9 ms] Range (min … max): 206.4 ms … 241.3 ms 12 runs Summary ./vectors_production ran 1.59 ± 0.08 times faster than ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors 4.05 ± 0.19 times faster than ./vectors_development #0 13:43:00 ᛋ master /v/vnew/bench/vectors❱ #0 13:45:07 ᛋ master /v/vnew/bench/vectors❱ls -nlarS ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors ./vectors_development ./vectors_production -rwxrwxr-x 1 1000 1000 179384 Sep 6 13:42 ./vectors_production -rwxrwxr-x 1 1000 1000 1320764 Sep 6 13:42 ./vectors_development -rwxr-xr-x 1 1000 1000 66732821 Sep 6 13:40 ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors #0 13:45:12 ᛋ master /v/vnew/bench/vectors❱ #0 13:53:12 ᛋ master /v/vnew/bench/vectors❱alias xtime='/usr/bin/time -f "CPU: %Us\tReal: %es\tElapsed: %E\tRAM: %MKB\t%C"' #0 13:53:42 ᛋ master /v/vnew/bench/vectors❱xtime ./vectors_development 5.0498380931718074e+07 - 5.0504723697762154e+07 - 5.040198063489048e+07 0.0 - 0.0 - 0.0 CPU: 0.87s Real: 0.87s Elapsed: 0:00.87 RAM: 4404KB ./vectors_development #0 13:53:52 ᛋ master /v/vnew/bench/vectors❱xtime ./vectors_production 4.971971434731853e+07 - 4.973120986372047e+07 - 5.030988639116867e+07 0.0 - 0.0 - 0.0 CPU: 0.20s Real: 0.20s Elapsed: 0:00.20 RAM: 3228KB ./vectors_production #0 13:53:58 ᛋ master /v/vnew/bench/vectors❱xtime ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors (49627678.97075553, 50302418.6269631, 49705582.70645027) (0, 0, 0) CPU: 0.33s Real: 0.34s Elapsed: 0:00.34 RAM: 30544KB ./bin/Release/net7.0/ubuntu.20.04-x64/publish/vectors #0 13:54:02 ᛋ master /v/vnew/bench/vectors❱ #0 14:01:33 ᛋ master /v/vnew/bench/vectors❱ #0 14:01:35 ᛋ master /v/vnew/bench/vectors❱xtime v vectors.v CPU: 0.41s Real: 0.36s Elapsed: 0:00.36 RAM: 59412KB v vectors.v #0 14:01:41 ᛋ master /v/vnew/bench/vectors❱ #0 14:01:42 ᛋ master /v/vnew/bench/vectors❱xtime v -prod vectors.v CPU: 4.97s Real: 5.11s Elapsed: 0:05.11 RAM: 80732KB v -prod vectors.v #0 14:01:48 ᛋ master /v/vnew/bench/vectors❱ #0 14:01:50 ᛋ master /v/vnew/bench/vectors❱xtime dotnet publish -c Release -r ubuntu.20.04-x64 MSBuild version 17.7.1+971bf70db for .NET Determining projects to restore... All projects are up-to-date for restore. vectors -> /v/vnew/bench/vectors/bin/Release/net7.0/ubuntu.20.04-x64/vectors.dll vectors -> /v/vnew/bench/vectors/bin/Release/net7.0/ubuntu.20.04-x64/publish/ CPU: 2.34s Real: 2.64s Elapsed: 0:02.64 RAM: 159816KB dotnet publish -c Release -r ubuntu.20.04-x64 #0 14:01:56 ᛋ master /v/vnew/bench/vectors❱ ``` ================================================ FILE: bench/vectors/vectors.cs ================================================ using System; internal readonly struct Vector { public readonly double X; public readonly double Y; public readonly double Z; public Vector(double x, double y, double z) { X = x; Y = y; Z = z; } public override string ToString() { return $"({X}, {Y}, {Z})"; } } class Program { static void Main(string[] args) { const int boidsCount = 10000; var positions = new Vector[boidsCount]; var velocities = new Vector[boidsCount]; const double maxCoordinate = 10000.0; var random = new Random(); for (var positionIndex = 0; positionIndex < positions.Length; positionIndex++) { positions[positionIndex] = new Vector( x: random.NextDouble() * maxCoordinate, y: random.NextDouble() * maxCoordinate, z: random.NextDouble() * maxCoordinate ); } const double cohesionDistance = 10.0; const double separationDistance = 5.0; var closeBoids = new List(); for (var boidIndex = 0; boidIndex < positions.Length; boidIndex++) { var position = positions[boidIndex]; closeBoids.Clear(); for (var otherBoidIndex = 0; otherBoidIndex < positions.Length; otherBoidIndex++) { if (boidIndex == otherBoidIndex) { continue; } var otherPosition = positions[otherBoidIndex]; var differenceX = position.X - otherPosition.X; var differenceY = position.Y - otherPosition.Y; var differenceZ = position.Z - otherPosition.Z; var distance = differenceX * differenceX + differenceY * differenceY + differenceZ * differenceZ; if (distance <= cohesionDistance * cohesionDistance) { closeBoids.Add(otherBoidIndex); } } if (closeBoids.Count == 0) { continue; } var cohesion = new Vector(0.0, 0.0, 0.0); var separation = new Vector(0.0, 0.0, 0.0); var separationCount = 0; var alignment = new Vector(0.0, 0.0, 0.0); foreach (var closeBoidIndex in closeBoids) { var closeBoidPosition = positions[closeBoidIndex]; cohesion = new Vector( cohesion.X + closeBoidPosition.X, cohesion.Y + closeBoidPosition.Y, cohesion.Z + closeBoidPosition.Z ); var differenceFromClosest = new Vector( position.X - closeBoidPosition.X, position.Y - closeBoidPosition.Y, position.Z - closeBoidPosition.Z ); var differenceMagnitude = Math.Sqrt(differenceFromClosest.X * differenceFromClosest.X + differenceFromClosest.Y * differenceFromClosest.Y + differenceFromClosest.Z * differenceFromClosest.Z); if (differenceMagnitude <= separationDistance) { separation = new Vector( separation.X + differenceFromClosest.X / differenceMagnitude, separation.Y + differenceFromClosest.Y / differenceMagnitude, separation.Z + differenceFromClosest.Z / differenceMagnitude ); separationCount++; } var closeBoidVelocity = velocities[closeBoidIndex]; alignment = new Vector( alignment.X + closeBoidVelocity.X, alignment.Y + closeBoidVelocity.Y, alignment.Z + closeBoidVelocity.Z ); } cohesion = new Vector( cohesion.X / closeBoids.Count, cohesion.Y / closeBoids.Count, cohesion.Z / closeBoids.Count ); var cohesionForce = new Vector( cohesion.X - position.X, cohesion.Y - position.Y, cohesion.Z - position.Z ); if (separationCount > 0) { separation = new Vector( separation.X / separationCount, separation.Y / separationCount, separation.Z / separationCount ); } alignment = new Vector( alignment.X / closeBoids.Count, alignment.Y / closeBoids.Count, alignment.Z / closeBoids.Count ); var currentVelocity = velocities[boidIndex]; velocities[boidIndex] = new Vector( currentVelocity.X + cohesionForce.X + separation.X + alignment.X, currentVelocity.Y + cohesionForce.Y + separation.Y + alignment.Y, currentVelocity.Z + cohesionForce.Z + separation.Z + alignment.Z ); } var positionSum = new Vector(0.0, 0.0, 0.0); var velocitySum = new Vector(0.0, 0.0, 0.0); for (var boidIndex = 0; boidIndex < positions.Length; boidIndex++) { var position = positions[boidIndex]; var velocity = velocities[boidIndex]; positions[boidIndex] = new Vector( position.X + velocity.X, position.Y + velocity.Y, position.Z + velocity.Z ); positionSum = new Vector( positionSum.X + position.X, positionSum.Y + position.Y, positionSum.Z + position.Z ); velocitySum = new Vector( velocitySum.X + velocity.X, velocitySum.Y + velocity.Y, velocitySum.Z + velocity.Z ); } Console.WriteLine(positionSum.ToString()); Console.WriteLine(velocitySum.ToString()); } } ================================================ FILE: bench/vectors/vectors.csproj ================================================ Exe true true net7.0 enable enable Exe ================================================ FILE: bench/vectors/vectors.runtimeconfig.json ================================================ {"runtimeOptions":{"framework":{"name":"Microsoft.NETCore.App","version":"7.0.10"}}} ================================================ FILE: bench/vectors/vectors.v ================================================ module main import rand import math struct Vector { x f64 y f64 z f64 } const boids_count = 10000 const max_coordinate = 10000.0 const cohesion_distance = 10.0 const separation_distance = 5.0 @[direct_array_access] fn main() { mut positions := [boids_count]Vector{} mut velocities := [boids_count]Vector{} for position_index in 0 .. positions.len { positions[position_index] = Vector{ x: rand.f64() * max_coordinate y: rand.f64() * max_coordinate z: rand.f64() * max_coordinate } } for boid_index in 0 .. positions.len { position := positions[boid_index] mut close_boids_ids := []int{} for other_boid_index in 0 .. positions.len { if boid_index == other_boid_index { continue } other_position := positions[other_boid_index] difference_x := position.x - other_position.x difference_y := position.y - other_position.y difference_z := position.z - other_position.z distance := difference_x * difference_x + difference_y * difference_y + difference_z * difference_z if distance <= cohesion_distance * cohesion_distance { close_boids_ids << other_boid_index } } if close_boids_ids.len == 0 { continue } mut cohesion := Vector{} mut separation := Vector{} mut separation_count := 0 mut alignment := Vector{} for close_boid_id in close_boids_ids { close_boid_position := positions[close_boid_id] cohesion = Vector{ x: cohesion.x + close_boid_position.x y: cohesion.y + close_boid_position.y z: cohesion.z + close_boid_position.z } difference_from_closest := Vector{ x: position.x - close_boid_position.x y: position.y - close_boid_position.y z: position.z - close_boid_position.z } difference_magnitude := math.sqrt( difference_from_closest.x * difference_from_closest.x + difference_from_closest.y * difference_from_closest.y + difference_from_closest.z * difference_from_closest.z) if difference_magnitude <= separation_distance { separation = Vector{ x: separation.x + difference_from_closest.x / difference_magnitude y: separation.y + difference_from_closest.y / difference_magnitude z: separation.z + difference_from_closest.z / difference_magnitude } separation_count += 1 } close_boid_velocity := velocities[close_boid_id] alignment = Vector{ x: alignment.x + close_boid_velocity.x y: alignment.y + close_boid_velocity.y z: alignment.z + close_boid_velocity.z } } cohesion = Vector{ x: cohesion.x / close_boids_ids.len y: cohesion.y / close_boids_ids.len z: cohesion.z / close_boids_ids.len } cohesion_force := Vector{ x: cohesion.x - position.x y: cohesion.y - position.y z: cohesion.z - position.z } if separation_count > 0 { separation = Vector{ x: separation.x / separation_count y: separation.y / separation_count z: separation.z / separation_count } } alignment = Vector{ x: alignment.x / close_boids_ids.len y: alignment.y / close_boids_ids.len z: alignment.z / close_boids_ids.len } current_velocity := velocities[boid_index] velocities[boid_index] = Vector{ x: current_velocity.x + cohesion_force.x + separation.x + alignment.x y: current_velocity.y + cohesion_force.y + separation.y + alignment.y z: current_velocity.z + cohesion_force.z + separation.z + alignment.z } } mut position_sum := Vector{} mut velocity_sum := Vector{} for boid_index in 0 .. positions.len { position := positions[boid_index] velocity := velocities[boid_index] positions[boid_index] = Vector{ x: position.x + velocity.x y: position.y + velocity.y z: position.z + velocity.z } position_sum = Vector{ x: position_sum.x + position.x y: position_sum.y + position.y z: position_sum.z + position.z } velocity_sum = Vector{ x: velocity_sum.x + velocity.x y: velocity_sum.y + velocity.y z: velocity_sum.z + velocity.z } } println('${position_sum.x} - ${position_sum.y} - ${position_sum.z}') println('${velocity_sum.x} - ${velocity_sum.y} - ${velocity_sum.z}') } ================================================ FILE: changelogs0.x/0.4.md ================================================ ## V 0.4 *1 July 2023* #### Improvements in the language - **Coroutines with a scheduler**. Only Linux/macOS for now, requires `-use-coroutines` and `coroutines.sleep()` instead of `time.sleep()`. They work with IO and net, but not with GC for now. - `spawn` now spawns system threads, `go` spawns coroutines. - Static type methods: `Foo.new()` to replace factory functions like `new_foo()`. - Smartcasting with complex conditions: `if sum_type is Foo && !sum_type.is_info && get_name(sum_type.info.name) == 'foo' `. - Functions can now return fixed size arrays. - Enum values now can have attributes. - Generic functions as function parameters are now supported: `fn f[T](x T, i int, f_ Fn[T]) T { `. - Anonymous structs can no longer have attributes. - A new `[spawn_stack: 131072]` function attribute for controlling the max size of the stack of the spawned threads. - Channel pop now works with an `or` block: `ch := <-self.item or { return none }` - `it` has been renamed to `index` in array inits. - String interpolation simplified to just '${name}', enforced by vfmt, and updated in the entire code base. - `go foo()` has been replaced with `spawn foo()` (launches an OS thread, `go` will be used for upcoming coroutines instead). - vfmt now supports `// vfmt off` and `// vfmt on` for turning off the formatting locally for short snippets of code. Useful for keeping your carefully arranged matrices intact. - Match branch range expressions with consts: `match x { const1...const2 {} }` - Hot code reloading via `[live]` is now supported in imported modules, not just the main module. - Syntax sugar for map inits without needing explicit casts for interfaces: `all.children := { "abc": rect, "def": ui.rectangle()}`. - `$embed_file()` fixes, including variable args support. - `none` fixes: no longer allowed to be used as a separate type, `dump()` support, not allowed inside `unsafe`. - Const functions: `const y = term.yellow`, then `println(y('abc'))`. - Builtin type names can no longer be used as identifiers. - Generic `typeof[T]()`, `sizeof[T]()`, `isreftype[T]()` functions. - Deprecated `-error-limit` in favour of the documented `-message-limit` option. - Maps now support aliased keys. - Operator overloading now works with reference types. - Generic struct inits with nested generic structs and generic optional types are now allowed. - During array creation, `len:` is required when using default values for the array. - Optimized one byte `[]u8` arrays creation. - Recursive aliasing is no longer allowed (e.g. `type Alias = map[string]Alias`). - Easier custom error creation: `return MyCustomErr{}` instead of `return IError(MyCustomErr)`. - All floats outputs now have `.0` conditionally appended to them to improve clarity. - Custom integer enum types: `enum Xyz as u64 {`. - AST transformer fixes and optimizations. - Stylistic improvements and bug fixes in vfmt. - Casting integers to enums now requires `unsafe{}`. - Improved error and warning messages. - Parallel compilation now uses `sync.Pool`. - `-skip-unused` fixes, soon to be made the default. - Anonymous structs. - Lots of bug fixes: 90% of all bugs ever submitted are closed. - New keyword/type: `nil`. Only to be used inside `unsafe`. Replaces `voidptr(0)`. - V can now find code in the `src/` directory. This allows making V repos much cleaner. - Support `assert condition, extra_message`, where the `extra_message` will be evaluated and shown if the assertion fails. - Operator overloading now works with aliases and generics. - Scanner optimizations. - Using C's #define is no longer allowed in normal V code, only in `.c.v` files. #### Breaking changes - `byte` deprecated in favor of `u8` (`byte` is automatically converted to `u8` by vfmt). - `json`: enums are serialized as strings by default, `[json_as_number]` attribute can be used for the old behavior. - Variable shadowing has been completely banned (previously variable names could conflict with module names). - `[]` is now used for generics instead of `<>`. - Accessing a pointer map value requires an `or {}` block outside `unsafe`. - Anonymous sumtypes have been removed (deprecated for now) due to complicating the language and the compiler too much. #### Checker improvements/fixes - Disallow `Result` type aliases (`type Foo = !Bar`) and `Result` in maps (`map[key]!Type`). - Add a missing check for taking address of literal value member. - Fixed map initialization for maps with option values. - Allow `a << none`, where `a` is `[]?&int`. - Disallow multiple `else` branches in a match. - Fix index expression with sumtype of array types. - Remove hardcoded check for function calls for `C.stat`, `C.sigaction`, etc. - Fix multiple embedded external module interface. - Fix missing check for diff type on map value declaration. - Simplify error handling in the checker (#18507). - Option alias fixes. - Fix alias to struct ptr on struct init. - Sumtypes can no longer hold references. - Fix a bug checking generic closures. - A hard to reach limit of 1 million iterations for resolving all generics. - Fix missing check for unwrapped shift operation. - Fix enum max value validation. - Add a missing mutability check for `array.delete` calls. - Disallow `_ = <- quit`. - Disallow type matching with primitive vars. - Warning instead of error for unnecessary brackets in if/match. - Include import aliases when checking for import duplicates. - Fix inferring generic array type in nested call. - Allow casted `enum val` and `const` as fixed array size. - Disallow multiple return values in const declarations. - Fix contains() with array of interfaces. - Disallow mut for blank idents. - If guards now work with struct fields which are `Option` functions. Such fields can now also be assigned to other fields/variables. - Option receivers can no longer have methods. - `none` can now be cast to all `Option` types, including aliases. - Option references are now supported: `?&Type`. - Arrays of `Option`s are now allowed. - Allow `foo := Foo{}`, when `Foo` has an Option field, that is a struct, that has a `[required]` tag on its fields. - Enums can no longer be initialized like structs. - Capture variables can no longer shadow anonymous function params. - Mixing multi-return results with other types in return statements is no longer allowed. - Assigning anonymous structs to named structs is no longer allowed. - `[required]` fields are now checked for embedded structs. - Fixed a bug with closures with fixed array variables. - Builtin methods `first/last/repeat` can now be used in custom user types (previously they only worked in builtin arrays). - Generic struct initialization no longer needs explicit types to be provided: ```v struct Foo[T, U] { a T b U } foo := Foo{ a: 2 b: 'x' } println(foo) ``` - unsafe: dereferencing nil references is no longer allowed in the following case: ```v a := unsafe { nil } println(*a) ``` - Lots of fixes in the type checker. - Int signedness mismatch is now checked: `cannot use literal signed integer as u8`. - Improved type checker: lots of new type checks and fixed checker bugs. - Unused last expression in `if` is now checked. - Anonymous structs visibility issues fixed. - More type checks. - Lots of fixes in `shared` types. #### Standard library - json: Enum value string serialization supports `[json:'alias']` to change its string values. - Struct fields can now be skipped during JSON/ORM serialization via `[json:'-']` and `[sql:'-']`, in addition to `[skip]`. This allows having custom behavior for different serialization methods. - builtin: heap usage API (gc_memory_use() and gc_heap_usage()) - math.big: refactoring, gcd fixes/improvements, overflow fixes, `mod_inverse`. - flag: fix finalize with multiple shortargs. - runtime: add new functions total_memory/0 and free_memory/0. - time: small cleanup of parse_iso8601 comments, make the C.strftime declaration forwards compatible - stbi: allow customization of number of channels in `stbi.load()`. - stbi: add a `resize_uint8` function for resizing images in memory. - time, x.json2: improve iso8601 time decoding. - builtin: zero out internal map/array pointers on m.free(), to reduce the work for the GC mark phase for non escaping maps/arrays, used in hot loops. - time: add more detailed error descriptions, add custom format parsing with time.parse_format. - sync: add Mutex.destroy and RwMutex.destroy methods. - datatypes: add Bloom filter. - rand: add missing rand.u16(), update doc comments, add test. - builtin: speed up string methods with vmemcpy instead of `for` loop for copying data. - Added new `termios` module. - `net.ssl`: types using ssl contexts can now be converted to strings via `.str()`/printed via `println()`. - `v.reflection`: added type symbol info metadata. - `crypto` and `math` modules have been updated to use `Result` instead of `Option`. - `datatypes.LinkedList[map]` now works correctly. - `urllib.Values.get()` now returns an Option. - `strconv`: `v_printf()` was made private, `v_sprintf()` was deprecated. String interpolation should be used instead. - `net.http`: mime types have been updated to include all official types. - `gg`: `create_image()` now returns `!Image` instead of `Image`, allowing to handle errors. - `sokol`: errors during image creation no longer result in a panic, but can be handled by the programmer. - `sokol`: macOS apps can now be quit using **Cmd+Q**. - `os.hostname()` and `os.loginname()` now return `Result`. - `strconv.atoi` optimizations. - `println()` now supports arrays with recursive references. - `termux`: support for cross-compilation from termux to other platforms. - `readline` module now works much better on macOS: key navigation, history, etc (now on par with Linux). - `os`: fixed a memleak in `getline()`. - `os.Process` now has a `create_no_window` option (Windows only). - `os.Process` now has a `set_work_folder()` method to set the initial working folder of the new child process. - `math.vec` module for generic vector math including 2D, 3D, and 4D vector operations. - Builtin stb_image.h used by gg has been updated to the latest v2.28. - All of vlib has been updated to use separate Option/Result types. - To avoid confusion, all references in the code and documentation to `Optional` have been replaced with `Option`. - `gg.Context` pipeline has more effects, including the `additive` effect. - Much cleaner eof checks in `os`: refactor `err == IError(os.Eof{})` to `err is os.Eof`. - Lots of work on `x.json2`, the pure V json encoder, soon to become official. - New `v.reflection` module for runtime reflection. - Improved `os.mv()`, which now works consistently even across different windows drives/mount points. - `string.trim_indent()`, useful with multi line strings, that start/end with new lines and indentation. - Reduced memory consumption in the `crypto` modules. - Official V UI library is now licensed under MIT. - Deprecated `math.util` and `math.mathutil` have been removed. - New time format support: `time.format_rfc3339()`. - `encoding.html.escape()`. - All public functions in the `hash` and `encoding.base32` modules have been documented. - New `crypto.pem` module. - New `map.reserve()` method. - `net.ssl` has been migrated from a dynamically linked OpenSSL to a statically linked Mbed TLS. This means that V binaries will no longer have an OpenSSL dependency. OpenSSL can still be enabled via `-d use_openssl`. - msgpack module for decoding/encoding msgpack. (`v install msgpack`) - Most of vlib has been updated to use the new Option/Result types. - net, net.http, vweb bugs and fixes. - QuadTree and RingBuffer types in `datatypes`. - Forward iterator for `datatypes.LinkedList`, forward and backward iterators for `datatypes.DoublyLinkedList`. - A new `maps` module, similar to existing `arrays`. It has generic `filter`, `flatten`, `invert`, `to_map`, `to_array`, `from_array` functions. - `utf8.is_number()`, `utf8.is_space()` functions. - New `encoding.base32` module. - `gg.TouchPoint` to differentiate between different types of touch input. - `str.int()` conversion speedup (without -prod). - `os.mkdir()` now has an optional `mode` parameter. - `encoding.csv` is now generic, supports bools, accepts a custom delimiter, and is compatible with io.Reader/io.Writer. - `datatypes` module now uses operator overloading. - All `datatypes` types can be converted to V arrays. - `smtp` improvements including multiple recipients and base64/utf8 support. - `arrays.carray_to_varray()` for converting C arrays to V arrays. - `strconv.v_sprintf()` has been deprecated in favor of string interpolation. - TOML module now supports `[toml:...]` attributes, just like the JSON module. - `os.walk()` is no longer recursive (still works the same). - `io` has been migrated to `Result`. - Third party window control in Sokol. - `string.replace_char()`, `math.round_sig()`. - Improved multiplication performance in `math.big`. #### Web - The builtin websocket library is now thread safe. - Enhanced builtin csrf protection in vweb. - vweb: ability to set and get values on vweb.Context. - vweb: support for host specific static files. - vweb: host option added to controller, and a new host attribute. - vweb: middleware docs improved; same with docs for `[vweb_global]` and `shared`. - vweb: return 404 on file not found. - net.http: copy IANA's list of methods to the http.Method enum. - net.conv: use a pure V implementation instead of C.hton etc. - net.html: `get_tag()` methods to find first tag occurrence. - net.html: fixed text parsing for inline tags. - net.html: fix parsing of nested quoted strings in code tags. - picoev: FreeBSD support. - vweb now supports live page reloading. The web app is instantly updated in the browser (no need to refresh the page) every time a **.v** or a **.html** file is changed. - vweb is now significantly faster and more stable under load, due to a new multithreaded worker pool, which is much more efficient at spreading the workload among all threads equally. - vweb now supports middleware. - vweb now supports controllers. It's now possible to have multiple app structs to better separate logic. - vweb now supports overridable `.not_found()` method for custom 404 pages in vweb. - vweb now uses database pool. - Fixed multipart form parsing in vweb. - Improved vweb stability under load. - `vweb.csrf` module. - `net.urllib` ipv6 support. - `net.Http.Response.text` renamed to `body`. - `net.websocket` timeout is now configurable. #### ORM - Fixed a foreign key bug that could result in an extra insert. - Comptime bug with `[skip]` and `[sql:'-']` fixed. - Checker error for unsupported field types. - Allow structs without the id field, more flexible primary keys. - Improved docs and examples. - Uninitialized structs are no longer inserted into related tables. - All ORM queries now return `![]` (`Result` of an array). This allows handling/propagating DB errors and simplifies working with ORM (one way). - Many ORM improvements: type checks for `limit/offset/order by/where`; support of reference objects in `insert`; struct fields can be used with `limit/offset`; `Connection` interface. - ORM now supports the `like` operator: ```v users := sql db { select from User where name like 'Bob%' } ``` - A new `-d trace_orm` option to see all SQL queries generated and used by V ORM and `-d trace_pg_error` to trace PG errors. - Various ORM fixes and improvements, including string interpolation support, type checks, fn calls in `where`. - Support parenthesized expressions like `select from User where (name == 'Sam' && is_customer == true) || id == 1`. - ORM functions now return `Result`, so the errors can be handled. #### Database drivers - mysql: TIMESTAMP support. - mysql: allocate memory for each string and blob dynamically depending on its value length. - mysql: add the ability to commit transactions. - VFS support in the builtin `sqlite` module; `sqlite.get_affected_rows_count()`. - Improved `pg` compatibility with older PostgreSQL versions before 2014. - `sqlite`, `pg`, `mysql` have been moved to `db.sqlite`, `db.pg`, `db.mysql`. #### Native backend - Refactoring, splitting large files into multiple. - Lots of fixes and new features in the native backend, including making codegen logic platform independent. - Operator support for floats, multi return. - Lots of native backend improvements, including library calls, comptime conditionals, enums, method definitions/calls, structs. - Major improvements to the fast native backend including linking support on Linux. The goal is to be able to self host V soon. #### V interpreter - Some further interpreter work. #### C backend - Fix code generation for generic unions. - Fix `[N]chan` (fixed arrays of channels). - Fix nested fixed array instantiation. - Fix fixed array of map. - Fix stringification of usize struct fields (before, they were treated as 32 bit *signed* numbers). - Now code generated by the С backend, can be compiled by a C++20 compiler. - C backend does not generate unused interface functions now. - Parallelized cc step. Speeds up -prod and clang/gcc compilation by 300-500% (depending on the number of cores). Experimental and hidden behind a -parallel-cc flag, soon to be the default. - Intel C compiler support. - Go backend fixes. - `#preinclude` for low level C interop. #### WASM backend - A new pure WASM backend, based on binaryen, a WASM `builtin` module, and a pure V WASM serialization library. #### Comptime - A new `$res` comptime function to get returned value in defer block (#18382). - Fix comptimeselector option propagation. - A mutability check for comptime assignments. - Fix comptime assigning to sumtype or indexexpr. - Make comptime calls work with or-block. - Compile-time interface fields evaluation. - Compile-time enum evaluation: ```v $for item in MyEnum.fields { println(item.value) println(item.name) } ``` - Added `$option` as a compile-time reflection type representing an any Option type. - All special compile-time reflection types are now lowercase (`$int`, `$enum`, `$option`, etc). - Improved compile time checks, like `$if x is Type {`; `$if T in [$Array, $Struct, $Alias, $Function] {`. - `$for in` works with alias types. - New comptime features for fields: `field.is_`, `field.is_alias`, `field.is_enum`. #### Compiler CLI - `v share file.v` for sharing code via the playground. - `v up` speed up for when it hasn't been run for a long time (**vc/** bootstrapping has been optimized). - `v init` no longer overwrites existing `src/main.v`. - `v self` now uses a faster TCC backend on macOS (Intel/Apple Silicon), just like on Windows/Linux. - A new command line flag `-e` for running short V programs on command line: `v -e "println(2+5)"` ( works just like in Perl). - A new `-ldflags` option, in addition to `-cflags`. Works just like LDFLAGS in C. #### OS support - Added basic QNX support. - Installation instructions for using V on NixOS. - Better `make` support for OpenBSD. - Much improved experience for `v install pcre` on Windows (it now bundles its own .c files, so it compiles cleanly, even if the platform does not have another pcre package installed). - V can now be compiled with tcc on latest macOS and Apple Silicon. - Removed the need for the `[console]` attribute in Windows GUI apps. - More precise WINAPI declarations for easier integration on Windows. - More CI tests on FreeBSD. - Full termux support via `$if termux {`, more predictable logging on Android. - Older macOS support (<10.12). - Windows code has been removed from `v.c` distributed on non-Windows systems. (`v_windows.c` is used on Windows.) #### Tooling - A new VPM site: vpm.vlang.io. A better design, discoverability of packages, descriptions, most downloaded packages etc. - vpm: installation of mixed modules. - `v ls --install -p D:\path\vls.exe` to install a local vls executable. - vdoc: highlight comments with gray color. - vet: allow vetting files with global variables. - Make util.launch_tool/3 more robust, by recompiling V tools always in a known current working folder. - Lots of documentation/readme improvements. - Lots of playground improvements: [play.vlang.io](https://play.vlang.io), including a really cool feature: "Show generated C code". - "Is V still fast?" web-page has been sped up by splitting the result table into multiple years. - GitHub Copilot summaries in PRs. - fast.vlang.io fixes & improvements, new server. - New official IntelliJ plugin: https://intellij-v.github.io. - Lots of new language documentation, a nicer table of contents. - Improved documentation for most of the vlib modules - `make.bat` & `v up` improvements on Windows. - TeamCity test runner support via `v -test-runner teamcity foo_test.v`. - CI optimizations for faster runs. - New official AdventOfCode repo with AOC solutions, also added to CI. - More detailed timings in `v -show-timings`. - `v new web` for quickly scaffolding new web projects. - New stunning playground with an improved look and feel, a much better and more responsive editor, code sharing by link, more convenient keyboard control, reusability for potential embedding: https://play.vlang.io. - Improved call tracing via `-trace-calls`. - Lots of documentation improvements, including a better documentation of the recent Option/Result split. - V REPL: Home/End keys support. Lots of clean up. - DOOM is now translated/compiled and launched on CI servers. A screenshot of the running game is made via `vgret` and is compared to the expected result. - VLS performance improvements, especially on Windows. - `v ls` tool for installing, for updating, and for launching VLS (V Language Server). - `v doc` now has syntax highlighting. ================================================ FILE: changelogs0.x/0.5.md ================================================ ## V 0.5 *3 Sep 2023 - 31 Dec 2025* #### Improvements in the language - Add comptime `if is shared` support (fix #25600) (#25602) - Make `defer{}` scoped by default, use `defer(fn){}` to get the old behavior #25639) (#25665) - Add gotodef support for nested struct members, fn return types, etc (#26131) - Add a new v.comptime stage `COMPTIME`, that runs after the checker (`CHECK`), and before the transformer (`TRANSFORM`), to simplify the work that later stages do #26068 (#26161) - json2: replace encoder with a new implementation. It's 70% faster than the old json2, and 110% faster than json that is based on cJSON (#25224) - Virtual C consts with custom types (const C.MY_CONST u8) - Support `-div-by-zero-is-zero`, which allows for `x / 0 == 0` and `x % 0 == x`, avoiding division by zero traps/panics (#24981) - Limit -div-by-zero-is-zero influence to just the integer types (for f32 and f64, / produces a +inf or -inf value, and the program continues to run) - VLS mode for the language server in pure V - Add support for `@OS`, `@CCOMPILER` `@BACKEND` and `@PLATFORM` (#25174) - Support a new CPU architecture s390x (#24107) - Add initial support for ppc64le (#24287) - Add initial support for loongarch64 (#24343) - Support `js"string literal"` for JavaScript strings (#24653) - VLS mode in the parser for the new language server in pure V - Implement assignable anonymous struct (fix #23855) (#23857) - Remove ancient deprecations (#23479) - `-skip-unused` is now on by default resulting in much smaller cgen and binaries. 70% reduction for hello world. - `-parallel-cc` for speeding up `-prod` and `-cc clang/gcc` compilation by up to 14 times! - C functions no longer need to be manually defined. An `#include "foo.c"` is enough (behind `-experimental` for now). - Fixed arrays now have `.index .any .all .map .sort .sorted` methods - Remove inline sum types completely - Support `in` expr with number ranges: `if var in 1..4 {` (fix #20352) (#22754) - Optimize literal string comparison (`match`, `in` and `==`) (#22643) - Allow `map[k]()?` and `map[k]()()` (#22740) - Add selector option unwrapping inside `if tree.root != none {` (#22895) - Add `array.count` as a method that accepts a predicate, similar to filter, but returning just the number of matches (#23054) - Allow option array element comparison `==` and `!=` (fix #23108) (#23113) - A new `implements` keyword for explicit interface implementation - Allow multi return as fn argument (#21991) - Define a default sumtype value (based on the first variant type) (#22039) - Remove the obsolete .code and .msg fields of IError (#22066) - Fix generic lambda type binding and resolution (#22083) - Comptime support for traversing the method parameters with `$for param in method.params {` ( #22229) - Show missing variants in the sum type error - A much better and detailed unmatched fn arg error - Add support for `@BUILD_DATE`, `@BUILD_TIME` and `@BUILD_TIMESTAMP`, all using v.util.get_build_time(), and overridable through SOURCE_DATE_EPOCH (#22213) - Add support for `-d ident=value` and retrieval in code via `$d('ident', )` - `-warn-about-allocs` for debugging allocations when using manual memory management - `@[freed]` attribute for assign statements (for the above mode) - Implement `&&=` and `||=` operators (#21678) - Improve C var args interop, allow for `fn f(some int, ...) {` (#21812) - A new flag `-n` for skipping notes (similar to `-w` for skipping warnings) - Cross compilation to FreeBSD - Experimental `x.vweb` is now `veb`, the official and recommended way to build web apps in V. Built on top of pico.v. - autofree: -print_autofree_vars command line flag for printing variables autofree couldn't free - Add `@VMODHASH` comptime variable to store the commit sha of a V module (#21091) - Fix sumtype support for option variant types (#21101) - Utilize new diff functions in errors (expected/found) (#21431) - Add @[_linker_section] for global variables - Add map update-init syntax: `new_map := {...old_map, 'k1': 1, 'k2': 5}` (#20561) - Improve coroutines, Photon vcpu creation, coroutines + GC fixes (#20549) - Update Boehm GC libs/headers to the latest version 8.3.0 (#20772) - $dbg statement - native V debugger REPL (#20533) - Implement `@[_linker_section]` attribute (#20629) - Enable `@[export]` for global variables too (#20649) - Add callstack support on v.debug (#20680) - Implement `@[aligned]` and `@[aligned:8]` attributes for structs and unions (#19915) - Update attributes to use new syntax - Update remaining deprecated attr syntax (#19908) - Support `$if T is $array_dynamic {` and `$if T is $array_fixed {` in addition to `$if T is $array {` (#19882) - Prepare for making `-W impure-v` the default (#19940) - Assigning `0` to reference fields now requires unsafe blocks (fix #14911) (#19955) - Unwrap const() blocks - Implement $for comptime T.variants (#20193) - Add `r` and `R` switches for repeating in string interpolation, `'${"abc":3r}'` == 'abcabcabc' ( #20197) - Comptime refactor and cleanup (#20196) - Allow comptime-for to iterate over comptime variables, add `$string` comptime type, cleanup ( #20233) - Unwrap an option value automatically, inside `if o != none {` (#20275) - Complete support for smartcasting to a comptime variable type (#20270) - Improve comptime var checking with `is` operator and smartcasting (#20315) - A new `encoding.xml` module with parser, validation, entity encoding, unit tests (#19708) - Better couroutines support (IO, networking) - Allocations in vweb apps reduced by 80% - Implement `@VCURRENTHASH` to replace `C.V_CURRENT_COMMIT_HASH` (#19514) - int => i64 on 64 bit, i32 on 32 bit (start of the transition) - Fix new int type promotion rules and cleanup native gen() (#19535) - Short lambda expressions like `a.sorted(|x,y| x > y)` (#19390) - Support `-os plan9`, `$if plan9 {`, and `_plan9.c.v` (stage 1 for plan9) (#19389) - fmt: simplify the processing logic for removing inline comments (#19297) - Align the custom values of the enum fields (#19331) - Do not warn/error for `import flag as _` - Keep anon struct decl fields in interfaces (#19461) - Support -N, turning all notices into errors, to ease the process of finding places that may need attention/correction - Pure `array.sorted()` and `array.sorted_with_compare()` methods, that do not modify their receivers (#19251) - UB overflow has been removed - Implement `Enum.from_string(name string)` for converting strings to enum values (#19156) - Disallow casting string to enum, suggest using Enum.from_string() instead (#19260) - Use autocasting in complex conditions (#18839) - Allow alias as fixed array on return (#18817) - Do not allow uninitialized function pointers - Fix compiling V programs with latest clang 16 on windows (clang 16 is stricter than clang 14) ( #19095) - Fix anonymous struct with default expr (#19257) - Allow using consts as enum values (#19193) - `@[attr]` syntax to replace `[attr]` (`[]` is used for too many things). Most likely to be replaced with `@attr()` in the future. - Allow `none` for not first values on map initialization (#18821) - Make all .trace() methods generic on the type of the passed expression #### Breaking changes - Deprecate `gx` and replace all occurences with `gg` (which now contains all the functionality of `gx`) (#24966) - Remove deprecations made before 2024-11-06 - Add a deprecation note for `any` arg, prevent `any` from being used as map key,value or array type (#24277) - Make old `[attr]` syntax an error (`@[attr]` has to be used instead) - builtin: `string.index_after()` now returns an Option (like `string.index()`), use `string.index_after_()` for the old behavior - Vweb is now deprecated in favor of faster and more stable and easy to use veb - time: rewrite parse_rfc3339/1 to improve performance, reject partial timestamps, that miss date info like `22:47:08Z` (#22585) - Deprecate `x.vweb` and `vweb` in favor of `veb`, a faster, easier, and more stable framework. - checker: disallow initializing private struct fields outside structs module (#21183) - sokol: the sokol wrapper was updated, to match its upstream version at commit 058a4c5, several of its APIs no longer exist - templating.dtm: compile_template_file is no longer public - v.trace_calls: `pub fn on_c_main() {`, is now `pub fn on_c_main(should_trace_c_main bool) {` - v.transformer: Transformer.fn_decl is now Transformer.fn_decl_trace_calls - x.vweb: Context.redirect(url string, redirect_type RedirectType) is now Context.redirect(url string, params RedirectParams) - `Request.cookies` map has been deprecated. Replaced with `Request.cookie()` and `Request.add_cookie()`. - Stricter rules for C types (they always have to be declared now) - Remove inline comments (#19263) - `arr[1..4]` now requires `unsafe` if the slice can modify the original immutable array. #### Checker improvements/fixes - Correctly detect variadic arg passed to struct fn (fix #25504) (#25509) - Fix $(field.name) access on closure fn (fix #25513) (#25514) - vls: skip unrelated files (#25531) - Fix mutability in `for in` loops with pointer values (fix #25520) (#25536) - Fix type inference, when pushing an empty array to a 2D array (fix #23854) (#25508) - Prevent array.insert for array of references when non-reference is passed (fix #25511) (#25557) - Add more support for mod autocomplete, allow for .vv files too (#25562) - Fix cast from an empty struct to option (fix #25566) (#25581) - Ensure ?Struct is not parsed as ??Struct when param is ?T (fix #25559) (#25564) - Fix if branch type nr_muls mismatch (fix #25556) (fix #25555) (#25571) - Fix comptime else branch handling (fix #25586) (#25589) - Smart detect `or {}` inside loop when using `c <-val` (fix #24550) (#25435) - Vls fix goto definition (#25595) - Fix generic resolve for external module generic static method call (fix #21476) (#25634) - Correctly detect type, when prepending to generic array (fix #25585) (#25645) - Allow cast from voidptr to sumtype in unsafe block (fix #25652) (#25657) - Disallow calls to a shared receiver method, on a non-shared var (fix #25577) (#25656) - Fix or block endwiths expr (fix #25329) (#25667) - Set ast file fallbacks for vls (fix #25678) (#25679) - Error/warn when using `defer(fn)` inside function-scope and `lock` stmts (#25681) - Maintain correct ref level in generic fn (fix #25676) (#25687) - In vls mode, make ensure_type_exists return true (#25695) - Only collect/hoist inner vars, when `defer` is function-scoped (#25693) - Improve type checking for sumtypes with generics (fix #25690) (#25699) - Unwrap for base type if ft.typ and inferred_typ are both opt (fix #25517) (#25728) - Disallow deference of nil (fix #25740) (#25746) - Fix comptime main fn (#25747) - Parser,fmt,checker: use a trie for matching the generic array methods `all`, `any`, `count`, `filter`, `map`, `sort` and `sorted` (#25759) - Fix array fixed unresolved return check and resolver (fix #25774) (#25790) - Allow explicit sumtype to option casts (fix #25796) (#25812) - Fix possible race on expected arg types unwrapping on cgen (#25815) - Skip init check for options (fix #25798) (#25830) - Fix module var set at change_current_file() (fix #25845) (#25846) - Improve handling of array decompose for dynamic arrays and array init (fix #25838) (#25843) - Force all fn declarations to follow after all other top level statements (fix #25889) (#25890) - Fix used features tracking when printing pointer values (fix #25899) (#25901) - Match type when auto deref occurs (fix #25913) (#25916) - Relax the redundant () check to a notice, to enable a future `v -W test vlib/builtin` job on the CI - remove () from match branch exprs (fix #25950) (#25952) - Fix array map anon fn return fixed array (fix #25928) (#25977) - Cleanup the output of `v new --web abcd` after feedback from https://youtu.be/IuE6Bo1klK0?t=555 - Allow assign to a shared int var (fix #25986) (#25988) - Ensure type of global exists (fix #25910) (#25998) - Ensure fn pointer cannot be used as non-fn argument (fix #26017) (#26022) - Make sure `$for` eval body statements at least once to set types and avoid markused issues later (fix #26058) (#26063) - Fix return static method name (fix #26105) (#26110) - Support gotodef for struct init and sumtype rhs (#26157) - Detect circular type references in sumtype declarations (fix #24511) (#26162) - Add interface type handling and new testcase (fix #24116) (#26165) - Allow enum fields to reference previously declared fields (fix #25241) (#26173) - Clear all ref from autostr receiver_type (needed by #25857) (#26202) - Allow for `_` being used as both `import x as _` and `fn f(_ int) {` (fix (#26219) #26230 - Fix `sizeof(T)` usage in generic struct (fix #24806) (#24808) - Add `$if sizeof(T) == int_literal {` support (#24831) - Improve virtual C consts - Markused,checker: fix hello world size after the introduction of `builtin.closure` in 2d87ac4 ( #24989) - Remove dump() dependency from ComptimeFor (#25000) - Cleanup - remove unused c.using_new_err_struct (#25036) - Cleanup `err` removal (#25043) - Add comptime support for s390x, ppc64le and loongarch64 platforms (#25048) - Allow for `v -is_o -o x mm.v`, where `mm.v` starts with `module abc` (i.e. not just `module main`) - Fix calls with result propagation, using other consts, in const declaration expressions (fix #21609) (#25060) - Fix array init with interface (fix #24255) (#25073) - Fix missing map float key duplicated checking (fix #25098) (#25117) - Fix missing check for struct generic init from call (fix #25084) (#25119) - Fix missing check for empty array to generic param (fix #25056) (#25118) - Rewrite comptime_if_cond() to support comptime if cond evaluate (fix #24938) (fix #25099) (#25122) - Add error for struct not init (fix #24893) (#25134) - Fix sql insert expr propagate result (fix #24833) (#25136) - Fix checking return type call disregarding unwrapping (fix #25140) (#25143) - Ensure the defer behavior matches that of cgen (fix #25148) (#25146) - Nil check for c.table.cur_fn in gen_branch_context_string() (fix #25170) (#25171) - Relax the "unreachable code after a @[noreturn] call" error to a warning to reduce prototyping friction (#25173) - Fix multi return arg passing checking (fix #25167) (fix #25180) (#25177) - Use keywords matcher trie for imported symbol presence checks, instead of `x in p.imported_symbol` (#25201) - Fix iteration over mutable option (fix #24860) (#25199) - Add `T.typ` and `T.unaliased_typ` checking to `$match` (fix #25200) (#25202) - Add more checks for map.delete (fix #25204) (#25205) - Fix static init var (fix #25203) (#25209) - Add top level comptime support for `$match @OS {` too (#25222) - Comptime match only eval true branch (fix #25223) (#25225) - Fix multi return var passing to fn arg (potential fix for #24870) (#25250) - Prevent usage of imported module name prefix as identifier names, to avoid cgen collisions ( #25280) - Disallow duplicate export names (fix #25301) (#25302) - Reduce the verboseness of `unsupported size ... for global` messages, for `v -b native examples/hello_world.v` - Fix chan element type validation with inexistent type (fix #23978) (#24008) - Do not allow auto (de)reference in PrefixExpr * - Fix check for pushing on an unwrapped option array (fix #24073) (#24093) - Fix wrong type hint on predicate arg type mismatch (fix #24122) (#24123) - Fix array generic return checking (fix #24104) (#24214) - Fix stack var outside usage when var is a mutable param (#24249) - Fix codegen for multi return with array fixed (fix #24280) (#24282) - Check anon struct field valid case (partial fix of #24284) (#24286) - Add check for recursive array init on struct (fix #21195) (#24278) - Fix inherited var turning in auto heap (fix #24306) (#24312) - Remove redundant callexpr `c.expr(mut node.left)` rechecks for `ast.CallExpr` (fix #24353) ( #24380) - Do not allow &u8(0), force nil like we do with &Type(0) - Relax the new warning, allow for `pub const pname = &char(C.SDL_POINTER)` to fix the clean compilation of code using vlang/sdl3 - Fix for with mut generic value (fix #24360) (#24426) - Add check for decomposing to interface (fix #24441) (#24453) - Fix generic option array arg passing to `[]T` (fix #24423) (#24457) - Fix resolver for returning struct generic (fix #24493) (#24506) - Reallow passing closures as voidptr parameters with no warning, to enable convenient interfacing with C libs - Disallow invalid expr for `filter`, `count`, `any`, `all` (fix #24508) (#24540) - Replace warning by notice for UTF8 strings validation (fix #24538) (#24543) - Revise logic for reporting import conflicts with module names (#24539) - Fix struct update expr checking, when an alias is used (fix #24581) (#24582) - Fix fn var resolver (fix #24525) (#24542) - Fix checking for int to array of interface (fix #24624) (#24625) - Cycle through all `ast.ParExpr` first in `prefix_expr` (fix #24584) (#24588) - Move `arr <<` logic to `check_append()` - Fix mutable const bug (fix #14916) - Allow for calling main() inside _test.v files - Fix missing type bounding to match expr on `or{}` expr (fix #24656) (#24658) - Add error for `if mut x != none {`, when `x` is an immutable option (fix #24692) (#24694) - Fix compound selector smartcasting/option unwrapping (fix #24662) (#24712) - Fix mutable option (fix #18818) (fix #24622) (fix #24101) (#19100) - Allow `none` to be passed to `?T` param (fix #23381) (#23385) - Fix `for` iterator method `.next()`, not marked as used (fix #23312) (#23321) - Fix generic var inferring to be passed to `[]T` (fix #23315) (#23322) - Clean up and optimise infix - reduce `as` casting (#23327) - Fix structinit validation on nested generic Map[K]V (fix #23329) (#23332) - Fix comptime indexexpr resolving (#23333) - Fix comptime evaluation on infix expr (fix #23341) (#23344) - Fix alias to fixed array w/ size defined by constant (fix #23356) (#23357) - Fix missing option variable checking when casting using `as` operator (fix #23349) (#23358) - Fix assign expected type on rechecking enum assigns (fix #23366) (#23367) - Allow calling `foo(?i64(123))` for `fn foo(x ?I64) {` and `type I64 = i64` (#23373) - Cache `node.args[0]` on `fixed_array_builtin_method_call` and `array_builtin_method_call` (#23411) - Fix missing check for invalid prefixexpr expression `&(&var)` (fix #23365) (#23418) - Disallow `&((&a))` and similar expressions, with innermost `ast.PrefixExpr` (enhance #23418) ( #23419) - Fix call with mut arg with different pointer levels (fix #23157) (#23428) - Fix missing detection for `return` in lockexpr stmts (fix #23434) (#23435) - Do not allow auto reference of voidptr params - Check if unwrapped `m[key]` if m is `Option` (fix #23446) (#23459) - Builtin,checker: remove `@[markused]` from `fn isnil()`, set `c.table.used_features.auto_str_ptr = true` instead (#23464) - Fix checker generic alias type (fix #23474) (#23475) - Fix missing check for `a := [none]` (fix #23457) (#23504) - Fix missing check for concrete type on match branch expr (fix #23506) (#23508) - Fix missing check for invalid argument for builtin (fix #23511) (#23515) - Fix selector nested unwrapping (fix #23519) (#23521) - Fix message with old attr syntax (#23529) - Cache repeated `node.args.len`, `method.generic_names.len`, `node.concrete_types.len` and `node.op.str()` (#23536) - Disallow `expr is Type` if expr is Optional (fix #23486) (#23510) - Make `option_var.str()` an error, when done without unwrapping it first (fix #23557, fix #23558) ( #23563) - Fix private symbol visibility checking (fix #23518) (#23543) - Disallow constant modification on unsafe {} (#23588) - Fix sumtype variant option type mismatch (#23659) - Disallow `arr = voidptr(0)` (fix #23675) (#23687) - Allow for `module no_main` programs, that can redefine their own main function, or not define any of their own as well - Fix match branch checking of nonreturn call on last expr (fix #23698) (#23699) - Check and error for invalid utf8 string literals (#23721) - Fix call from unknown enum (fix #23728) (#23730) - Add checker for passing multi return as arg to func that expects less param (fix #23735) (#23744) - Fix spreed operator ref field validation (fix #23759) (#23760) - Fix missing check for method that returns veb.Result (fix #23647) (#23762) - Allow generic operators to be called in fn (fix #23773) (#23774) - Fix missing struct cast validation (fix #23748) (#23788) - Fix map when casting to interface (fix #23790) (#23799) - Allow for `pub type C.HINSTANCE = voidptr`, being used in ``` @[export: "wWinMain"] fn mymain(x C.HINSTANCE, xprev C.HINSTANCE, lpcmdline &C.WCHAR, cmdshow int) int { ``` in `module no_main` programs (#23812) - Add option type inference on if expr (implement most of #23827, except the error for `v := if c { none } else { none }`) (#23829) - Add missing check for IfExpr and MatchExpr with no valid type (#23832) - Fix MatchExpr type inferring, when `none` is used (fix #23831) (#23833) - Add missing check for generic fntype type names (fix #23453) (#23850) - Add checking for comptime assign without comptime if checking (fix #23796) (#23848) - Fix option ptr field assign checking (fix #23879) (#23880) - Add missing `any` type validation on assignment (fix #23905) (#23906) - Add fntype casting validations (#23872) - Fix signed integer literal overflow error, when most significant bit occupies signed bit (fix #23782) (#23919) - Add missing check for casting generic type to literal values (#23915) - Check if next() method infers generic type correctly (fix #23927) (#23932) - Disallow references to constants (fix #23935) (#23942) - Fix typeof evaluation for generic reference (fix #23951) (fix #23952) (#23958) - Optimize identical type checking (#22596) - Fix `T.unaliased_typ` if branch evaluation (fix #22587) (#22598) - Fix lambda expr with fntype params and restore fixed_array_any_all_test.v (#22625) - Check fixed array builtin method args mismatch (#22626) - Fix generic fn call return type resolve on var assignment (fix #22612) (#22627) - Improve checking parameter mismatches for fixed array builtin methods (#22630) - Add tests for checking the new errors for fixed arrays .sort() calls (#22656) - Fix index expr that left is if expr (fix #22654) (#22661) - Fix return type checks, when returning struct values, implementing IError in non-result fn (fix #22659) (fix #22658) (#22660) - `App.method` field initialisation, for fn fields, initialised with generic methods (#22665) - Allow for `f() or { T{} }` in a generic method, for `fn f() ?T {`, being called with `T`, being a container like []int etc, not just a primitive type like int (#22672) - Allow for `f() or { T{} }` part 2, see also cc55aa5 (handle the case of an ignored result as well) (#22687) - Fix selector with prefixed `&` structinit (#22689) - Fix missing check for fn var with generic return inherited to anon fn (fix #19045) (#22683) - Check for receiver name clashing with global var (fix #22698) (#22708) - Fix none check for match expr with option (fix #22728) (#22732) - Fix option map fn type and missing check for result param type (fix #22736) (#22738) - Fix missing info about generic fn var usage without concrete types (fix #22733, #22734) (#22743) - Fix missing check for stack pointer return (fix #22726) (#22756) - Improve static method call resolution (fix #22773) (#22787) - Skip redundant message for int overflows, while casting integer literals (fix #22761) (#22788) - Fix callexpr after auto C func identification (fix #22800) (#22809) - Fix missing auto `from_string` type restriction (related to #22783) (#22803) - Fix match expr with empty array init expression (#22832) - Disallow `foo[T]` as a value (#22820) - Fix if expr with empty array init expression (related #22832) (#22841) - Improve the position underlining, for last statements in branches of `if` expressions (#22845) - Fix generic fn call with empty array argument (fix #22843) (#22846) - Fix missing or-block check for callexpr (fix #22835) (#22840) - Check array builtin method calls, that do need a mutable receiver, but are called on an immutable one (fix #22850) (#22853) - Check alias of array op overloading and fix op overloading (fix #22851) (#22854) - Disallow struct init with `mutable_field: const_array` (fix #22862) (#22863) - Check struct aliased field unsign type assigning negative value (fix #22868) (#22871) - Fix alias to struct generic type (fix #22866) (#22872) - Fix `json.encode_pretty` with a struct init expression argument (#22897) - Fix codegen for fixed array initialization with a fn call (fix #22887) (#22891) - Fix or-expr check on invalid method call (fix #22949) (#22950) - Fix mut var option unwrap with `!= none`, support `if mut x != none {` too (fix #22936) (#22943) - Prevent a compiler panic, while running `v -check file.v` on files with parser errors (fix #22981) (#22982) - Allow array sort with callexpr (#22989) - Fix `$res()` used in `defer {}` blocks with more statements, add a test (#22998) - Fix generec fn returning generic closure (#23047) - Fix generic fn returning generic closure (related #23047) (#23055) - Fix missing checker for cast from mut var to non-ptr type (fix #23017) (#23056) - Check fn call argument mismatch (fix #23016) (#23061) - Fix empty array append multi dims (fix #23092) (#23096) - Fix selector generic or block (fix #23088) (#23102) - Fix veb route method param with non ctx name (fix #23105) (#23107) - Allow fixed array where voidptr is expected (fix #23090) (#23100) - Fix immutable to mutable reference (fix #22653) (#22663) - Fix missing check on range expr when high var is same iteration value var (#23130) - Allow `[]Enum{len: 10, init: .thing}` (fix #23077) (#23165) - Fix option unwrapping and call from option struct field (#23182) - Add a notice for global variable redeclarations (#23162) - Fix assign check, when rechecking for another concrete type (#23212) - Disallow static fn call when receiver type is unknown (#21970) - Fix sumtype checking for voidptr variant (#21955) - Check comptime veb.html('index.html') (#21961) - Check if a parent generic struct has concrete types or not (#21962) - Add support for static methods in `@FN` and `@METHOD` (#21990) - Add a deprecation warning for `const ()` groups (an error after 2025-01-01) (#22019) - Improve `-d trace_checker` and error diagnostic information on compiler panics - Add error when initializing sumtype with struct as first type (#22067) - Add infix checks for nil (#22045) - Fix map generic fn arg passing (#22071) - Disallow using a preexisting const name in a for loop, as either a key or value ident (#22108) - Fix generic lambda type binding resolution (fix #22109) (#22115) - Fix array alias (#22175) - Restrict multiple union fields initialised at once with a nicer checker error, instead of producing an enigmatic error at cgen time (#22196) - Fix compilation of vlib/v/slow_tests/assembly/asm_test.amd64.v (regression after dfc0c91) - Add missing check for ref passing to non-ref (#22194) - Check struct implements non interface type (fix #22200) (#22218) - Suggest using the `@[_allow_multiple_values]` attribute, when declaring enums that have duplicate values (#22224) - Check for duplicate interface names in the `implements` parts of struct declarations (#22230) - Fix missing struct field type checking for type mismatch (ref vs non-ref in `mt sync.Mutex = sync.new_mutex()`) (fix #18088) (#21949) - Fix fntype var marked as auto heap (#22290) - Check array.delete() argument mismatch (#22307) - Add missing check for duplicated items on in expr (fix #22305) (#22308) - Disallow infix expr on left side of assign (#22322) - Fix array fixed return type for interface methods (#22320) - Check arguments mismatch of array.sorted_with_compare() (fix #22327) (#22328) - Add an error for returning an `any` value in pure V code (prevents invalid cgen) (fix #12623) ( #22334) - Cleanup the checking of array method calls (#22338) - Fix voidptr type checking (#21923) - Fix unknown fixed array size for `const n = int(sizeof(u64)); _ = [n]int{}` (fix #21544) (#21548) - Fix checking of default field initialisations, that are part of unions of structs tagged with `@[noinit]` (#21587) - Disallow sum type with `Result` variants (#21620) - Add error for `field map` (i.e. a plain untyped map), used inside a struct (#21625) - Fix missing concrete type checking on a generic type specifier (#21614) - Fix missing option and result wrong type return type definition (#21626) - Turn warnings for private fields into errors (#21296) - Support nested labeled for statements (#21658) - Fix the return type of overloaded operators, defined on aliases of primitive types (fix #21654) ( #21663) - Fix match expr with auto promote number (#21696) - Fix sorting compare fn with mut reference parameter (fix #21662) (#21706) - Fix `$if x {` condition, using `const x = $d('ident', false)` (fix #21709) (#21713) - Fix generic variable resolution on generic func return assignment (#21712) - Fix result call or_block with multi-statements (fix #21504) (#21717) - Allow `\uxxxxx` in raw strings (#21724) - Limit recursion in Checker.ensure_type_exists/2 to 40 levels (it is usually 4 or less) (#21734) - Add error for `field [$d('x', 2)]int = [1, 2]!` (#21741) - Fix nested if expr method call (#21773) - Fix generic inference in if expressions used in assignments (#21781) - Disallow nil in non-nil arrays and vice versa (#21786) - Check expr evaluated but not used (fix #21436) (#21816) - Fix wrong receiver generic resolution with embed types (#21833) - Check mismatch of fn call mut argument (fix #21857) (#21873) - Fix global fixed array key resolution when it is a constant ident (#21900) - Improve checks for embed in anon struct (#21877) - Fix builtin fn var resolving (#21899) - Fix spawn when calling undefined function (#21906) - Require enum values to be declared, before using them in other enum values (#21913) - Check enum field value duplicate (#21920) - Allow embed of type alias anon struct (#21928) - Ambiguous expression notice for `& << >>`, similar to `&& ||` - Disallow using aliases of ?Type as !Type (#21128) - Fix option checker arg validation for ptr passing on non expected ptr (#21087) - Optimize option and result type check, add more typinfo to error details (#21105) - Move error handling for `any` type to the checker to resolve parsing issues (#21146) - Move error handling for user defined type duplicates to the checker to resolve parsing issues ( #21147) - Detect redundant ref when assigning call expr with ref return (#21141) - Fix multi return using nil and voidptrfix (fix #17343) (#21144) - Fix C struct embedded init fields checking (#21137) - Remove resolved vfmt workaround and TODO (#21175) - Move more match validation from the parser into the checker, add error for match without branches (#21181) - Improve the error message for an unknown type (#21207) - Allow passing `none` to `fn f(arg ?&Type) {` (fix #21213) (#21231) - Fix -parallel-cc regression (part 1, workaround .filter(fn[c]) used in checker/orm.v) (#21238) - Detect and error on unreachable code in loops, after `continue` and `break` statements (#21294) - Disallow `Result` callbacks functions like `map/filter/all/any` (#21055) - Fix missing check for or expr on string interpolation (#17566) - Allow pass array as mut param to spawn fn (#21283) - Turn array assign warning into error (#21341) - Ignore last semicolon on or-expr (#21361) - Disallow structs with `@[params]` attribute as mutable function parameters (#21206) - Set auto Return pos correctly; cgen: autofree fix for optional returns - Disallow invalid ptr operations (#21515) - Fix wrong checking for heap struct (#21511) - Allow alias enum flagged to have bit operations (#21532) - Simplify, utilize pref.vroot (#21096) - Fix option interface member checking when `none` is passed (#21509) - Check invalid lambda expr (#20461) - Fix comptime if with comptime smartcast (#20466) - Fix anon struct init with const fields (fix #20452) (#20463) - Disallow `option` or `result` return type, for infix operator overloading (#20494) - Cleanup the const variable evaluate for fixed array fields of structs (#20503) - Fix missing check for struct initialization with `@[noinit]` attribute, through using `T{}` ( #20516) - Fix mark methods into used-list, when generics as receivers (fix #20509) (#20527) - Modify comments on generic receiver type storage (#20539) - Fix checking give const map as default or init value to struct fields (fix #20512) (#20546) - Fix return map index with or_block (#20544) - Cleanup the generic tests (#20553) - Fix `@[deprecated]` attribute for consts (fix #20523) (#20550) - Cleanup in method_call() (#20554) - Disallow `non_opt_array << optvalue` (#20573) - Fix non dereferenced enum in match statements (fixes #10045) (#20591) - Fix .variant smartcast on non-comptime variables (#20575) - Disallow static maps: `mut static x := map[string]int{}` (#20596) - Allow `#define X` and `asm riscv64 {}` blocks in .v files, with `-freestanding` (make embedded usecases easier) - Add cast overflow checks (#20641) - Disallow assigning none to _ (#20646) - Fix checking for option matching with non-option (#20673) - Disallow `(x) := 10` (#20695) - Disallow `none` as match cond (#20688) - Fix comptime ident checking on defer stmt (fix #20719) (#20723) - Add error for `x as Y.field`, suggesting using `(x as Y).field` instead for clarity (#20725) - Disallow sum type holding alias ptrs (#20786) - Optimise out calls to `arg_typ_sym.embed_name()` when there are no errors (#20820) - Fix if branch option type mismatch (fix #20809) (#20830) - Fix auto deref arg when fn expects ref (#20846) - Fix struct field init with generic fn variable (fix #20847) (#20878) - Cleanup in assign_stmt() (#20880) - Check assigning immutable reference struct field (fix #20814) (#20883) - Fix struct field init with generic anon fn (add the test from #18294) (#20888) - Fix checking match branch call expr twice (#20910) - Support `Flags.bit ^ Flags.bit1` and `~Flags.bit` (flagged enums) (fix #20925) (#20929) - Fix some specific interface generic inference within generics struct and method (#20932) - Remove notice when shifting signed int for `@[translated]` (#20935) - Silence "assigning 0 to a reference field" and "uninitialized fn struct fields" notices for `@[translated]\nmodule ...` files (#20938) - Fix missing check for interface cast of option type (#20961) - Silence more warnings for `@[translated]` files (#20964) - Fix comptimeselector passing to generic argument (#20985) - Remove unnecessary string interpolation in deprecation method calls (#21007) - Disallow void return value lambdas in array.map method calls (#21011) - Cleanup and simplify `check_ref_fields_initialized` methods (#21016) - Cleanup and simplify struct processing p1 (#21009) - Add support for deprecation messages for structs and struct fields (#21017) - Cleanup and simplify struct processing p2, extend test (#21025) - Fix undefined reference to interface struct field regression (after #21025) (#21030) - Add test for interface embedding and interface with erroneous implementation (test related to #21030) (#21033) - Disallow `Optional` and `Result` high val in a `for x in low..high {` loop (#21043) - Fix missing incompatible pushval type for chan <- operator (#21040) - Disallow `$for i in struct.values` and `$for i in enum.fields` (#19845) - Parser, checker: fix var scope in lambda(fix #19860) (#19871) - Change the warning `more than 1000 possibilities in match range` to a notice (#19862) - Fix inability to use multiple `import some modname as _` in the same .v file (fix #19899) (#19900) - Disallow casting strings to pointers outside `unsafe` (#19977) - Disallow directly indexing sumtype and interface, when using as parameters(fix #19811) (#19982) - Fix loop on aggregates of arrays (in match branches) of sumtypes (fix #18548) (#19988) - Disallow indexing mut struct, passed as a fn parameter (#19992) - Enhance err msg for unknown types for comptime `$for` (#20057) - Fix .clone()/.move() with shared maps (#20083) - Fix generics method call with struct short syntax args(fix #20030) (#20100) - Fix unwrap, when generic structs are used as arguments, in uncalled methods (fix #20132) (#20135) - Fix generic fn with generic fn call returning generic map (fix #20106) (#20150) - Cast sumtype to its variant generic type (#20166) - Refactor `string` to `enum` error check, handle `EnumName(string_variable)` too (#20210) - Fix generic array method call with multi-types (#20237) - Remove unnecessary struct ref field initialization checks and notifications at map initializing( fix #20245) (#20251) - Add a notice, for accessing by key, map values, that contain pointers (to use unsafe or an `or {}` block) (#20266) - Fix mismatch checking when a function returns sumtype as an argument (fix #19325) (#20264) - Fix and cleanup uninitialized checks for array initialisers with `len:` (fix #20272) (#20279) - Give an error for `.free()` method calls, when used on fixed arrays (#20320) - Fix type mismatch checking for assignments with generics (fix #20298) (#20327) - Fix too strict checking with generics in assignment type mismatch (fix #20335) (#20346) - Disallow `string` to `voidptr` cast entirely (#20351) - Fix generic method calls with multi generic types (fix #20330) (#20360) - Turn the option/result split warning into an error - Turn propagation warning into an error (finishes the option/result split) - Fix fn call with option call argument in autofree mode (#19515) - Bring back pascal case check for aliases - C.xx = C.yy aliases - Allow casted integral types in match ranges (#19572) - Warn about byte deprecation, when used as a fn parameter (#19629) - Allow size of fixed array to be integral casts (#19663) - Fix generic array append (#19658) - Check error of implementing other module private interface (fix #19620) (#19688) - Extend byte deprecation warning to array init types (#19671) - Extend byte deprecation warnings to return types (#19668) - Fix negative cap, len checks in array init (#19694) - Turn warning for var and param module name duplicates into error (#19645) - Fix closure in if guard, including with multi_return (#19765) - Fix comptime enumdata value property access (#19768) - Fix `field ?&Type` without default value (#19786) - Avoid nil assign to option var (#19746) - Allow for a shared variable to be whole reassigned (keeping the same mutex state) (fix #15649) ( #19751) - Disallow module name duplicates in local names (#18118) - Check enum fields with duplicate value (fix #19309) (#19310) - Disallow alias ptr cast of a map value (#19336) - Require `else` branch in `[flag]` enum match (#19375) - Disallow assigning pointer values to option struct fields (#19380) - Fix generic comparison for conditional assignment (#19401) - Allow using ! and ~ on aliased bool and integral types (#19403) - Warn -> error for uninitialized ref fields - Parser, checker: allow lambdas anywhere anonymous functions are expected (#19436) - Allow for `each(a, |x| println(x))`, i.e. using lambda expressions, when expecting `fn (x int)` - Check fixed array init with default expression (#19472) - Allow for `const source = $embed_file(@FILE).to_string()` - Fix C.type in imported modules - Disallow assigning `nil` to struct fields (#18725) - Use autocasting in complex if conditions (#18753) - Disallow invalid prefix on left side of assign stmt (#18750) - Allow no return in compile_error else block (#18758) - Fix interface param resolution (#18780) - Add an error for `$tmpl` function type mismatches (#18826) - Disallow voidptr cast to struct (#18845) - Fix type checker on auto deref var (#18842) - Check generic sumtype declaration (fix #18741) (#18865) - Fix closure with inherited sumtype variable (#18894) - "v -line-info" for a quick run to fetch info about objects on one line - Make sure vweb actions return vweb.Result - Do not allow modifying immutable vars via arrays with refs - Support `@STRUCT` in static methods - Fix generic struct field init recursively (related #19014) (#19025) - Fix struct field fntype value call (#19067) - Explicitly disallow creating type aliases of `none`, i.e. `type Abc = none` (#19078) - Fix assigning an array slice (fix #19120) (#19137) - Fix assigning array slice in struct init (#19150) - Check enum static from_string arguments errors (#19163) - Disallow taking the address of consts with int literal values (#19160) - Check struct embed with wrong position (#19245) - Optimize out needless string interpolations from the most common case in `Checker.expr_or_block_err` - Check error for or_expr inside infix expression (#19213) - Disallow `thread` as var name (#19174) - Check error for sumtype in array (#19183) - Disallow an empty `chan` type (#19167) #### Parser improvements - Fix vls mode strut mut keyword (fix #25548) (#25551) - Fix vfmt comment in struct init after the update expr (fix #24361) (#25668) - Fix infix expr comment in middle (fix #24183) (#25671) - Disallow using generic functions as a field type name inside struct decl (fix #25452) (#25705) - Warn on `@[deprecated_after]` used without a corresponding `@[deprecated]` attribute (#25712) - Fix last stmt is fn call in or_expr (fix #25732) (#25739) - Allow for `|mut x, y|expr` (fix #25734) (#25735) - Allow using `a`, `b` and `it` as var names, when using the builtin array methods (fix #25729) ( #25755) - Disallow generic function to be exported (fix #25794) (#25806) - Support `-d trace_parse` to ease diagnosing problems related to the order of parsing of .v files in modules - Fix the language support for a nested anonymous C.struct (fix #25807) (#25789) - Disallow untyped `chan` used as a fn parameter type (fix #25818) (#25854) - Improve the unused import warning message (add fixing alternatives) (#25880) - checker,parser,ast: make `type MyBuilder = strings.Builder` work (part 1); add `mod` fields to ast.SumTypeDecl and ast.AliasTypeDecl (#25943) - Remove dead code in Parser.is_array_type/0 (#26080) - Check invalid struct name in struct_init() (fix #26030) (#26093) - Remove the support for the obsolete generic fn call syntax f() (first deprecated in 2022/11) ( #26126) - Fix comptime for lock shared field (fix #26143) (#26146) - checker,parser: add multifile gotodef support for -line-info (#26167) - Optmize Parser.call_kind (#26196) - Split parser methods to files based on topic (#24786) - Fix arch loongarch64 comptime support (fix #24906) (#24907) - Fix const error - pref,parser: implement support for `-force-bounds-checking` to enable easier testing of functions tagged with `@[direct_array_access]` (essentially turning off that flag) - Allow keyword as struct param key on fn call (fix #24957) (#24958) - Fix syntax error for `for c in [othermod.Struct{field: 255}] {` (fix #24943) (#24978) - Reduce calls to util.contains_capital - Fix overriding of fn names in `-translated` mode (fix #25024) (#25061) - Fix asm modifier parsing (allow for `=r, =&r, +r, +&r,=m,=rm,=@ccl, =*r`) (fix #25070) (#25072) - Allow using aliased types in interface method implementations (provide backwards compatibility to `ui`, during the migration of code from `gx` to `gg`) (#25106) - Fix interface method declaration with fixed array return type (fix #25137) (#25145) - Prepare for eliminating a warning for `v -cross -o vc/v.c cmd/v` (part 1) (reduce CI annotation noise) - Add duplicate import symbol detect (fix #25185) (#25187) - vfmt,parser: move mark used from vfmt to parser (#25190) - v.ast: add a `mod` field to ast.FnTypeDecl too - Fix parse_cflag() support other flags between allowed_flags (fix #24121) (#24146) - Minimise allocations done for the common case in find_struct_field - Fix orm generic struct table type parsing (fix #24049) (#24149) - Fix mutiple imports at one line (#24241) - Fix range expr precedence on compound logical and operator (fix #24252) (#24275) - Fix invalid field name checking (fix #24279) (#24283) - Fix wrong string parsing (fix #24297) (#24298) - Fix panic for `struct Abc { pub mut: }` (fix #24404) (#24403) - Allow `mut static counter := 0` inside `unsafe {}` blocks (prepare for removing a `-translated` mode quirk) - Fix duplicate mod imports (fix #24552) (#24559) - Reduce memory usage of ast.ScopeObject and ast.Ident instances (#24704) - Reduce allocations in empty_comptime_const_expr (#23324) - Add error for array init of Results `[]!type{}` (fix #23360) (#23375) - Allow map cast syntax `map[k]v(expr)` (#23401) - Inline some commonly used fns (#23535) - Fix anon fn return type option/result followed by comment parsing in vfmt mode (fix #23607) ( #23608) - Keep track of the number of all scanned tokens too, and show it with `-stats` - Fix the error message position, for a `struct Abc`, that lacks a body (#23627) - Prevent unused warning on `import mod { Sym }`, when `Sym` is later used, for more cases (fix #23412) (#23626) - Add support for `-d trace_parse_file_path_and_mod`, to help diagnosing module lookup problems - Allow for `@[has_globals]` to be used for all V programs, turn the `@[wasm_import_namespace]` error into a notice - Remove table dep for script main check - Fix enum value parsing inside array initialization (fix #23937) (#23941) - Fix the registration of fixed arrays, when size_expr is a const (fix #23946) (#23949) - Disallow invalid expr in comptime `$for` (fix #23953) (#23959) - Fix generic struct init detection `T{}` (#22682) - Improve the assert informations (related #22668) (#22679) - Make C struct fields public and mutable by default (fix #22695) (#22706) - Fix enum redeclaration error (fix #22759) (#22766) - Fix struct field name using keyword (fix #22826) (#22829) - Optimise mark_var_as_used calls, by moving it to an ast.Scope method (#22842) - Optimize method parameter detection in used check (#22915) - Fix block position's last line (#22913) - Support `@[must_use]` tag for fns/methods, and an experimental `-check-result` option (#22983) - Allow `type` as field type on params struct construction (fix #23091) (#23098) - Allow `type` and other keywords as plain attr value (fix #23150) (#23154) - Support `@[tag]` for hash statements, like `#define` and `#flag` (#23210) - Fix lots of parser panics, discovered through fuzzing with radamsa - Improve the error for keyword `lock`, used as a variable name (#21937) - Improve the error message position for invalid array attr keys (#21944) - Fix const field str() (#21998) - Update `@include` in templates, to work with relative paths & prevent recursive calls (#21943) - Check fn call args without comma between them (related #22021) (#22075) - parser,scanner,ast: make the scanner and parser more robust, by implementing more limits ( preventing panics, discovered by fuzzing) - Protect against too deep recursion in Expr.pos() calls - Check too many layers embedded generic type (fix #22089) (#22091) - Cache ident lookups for consts in ast Expr str (#22101) - Improve Type and TypeFlag related operations (#22107) - Fix parsing map value inside or expr (fix #12164) (#22180) - Fix const field str() (#22192) - Fix `.${var}` used in a template, compiled by `$tmpl()` (fix #22231) (#22270) - Check enum method duplicated (fix #20924) (#22294) - Register selective import aliases as used (#21613) - Allow multiple flag values in enum.from() for flag enums (fix #21569) (#21615) - Disallow duplicate operator overload (#21675) - Support `[$d('s', 4)]int{}`, move resolving to method on `ComptimeCall` (#21701) - Support `$d()` in fixed size array `struct` fields (#21731) - Suggest using type alias when defining methods on non-local types (#21803) - Sugggest map initialization with the correct syntax (#21817) - Fix parameter collision for generated `@[flag]` enum methods, with modules named `flag` (#21844) - Fix high order generic fn resolution (#21871) - Fix recognition of `mod.Enum.val` inside fn args (#21908) - Fix option as possible match case for sumtype (#21079) - orm: disallow invalid infix for where clause in `delete` and `update` (#21113) - Fix case of falsely registering imports as used, remove unused imports (#21156) - Remove redundant comments_mode field (#21198) - Update file path fields; use more expressive name for file path, remove obsolete `file_name_dir` field (#21202) - Add missing docstrings for vlib/v/ast/comptime_const_values.v functions (#21219) - Allow struct init on `for in Iterator{} {` (fix #21179) (#21282) - Fix `for x in Iterator{} {`, when there are no field initialisations (#21333) - Add check for result type on chan init (#21363) - Fix comptime panic for `$tmpl("x.html")`, when the template file contained % at the end (#21402) - Parse string and array typ idx of `ScopeVar` and `Ident` (#21523) - Fix close_scope() missing, when field.name is `sort` or `sorted` (fix#20436) (#20485) - Check non-generic interface defining generic method (#20545) - vast,ast: output map init update expression (#20574) - Implement `MyEnum.from(1)!` generic static method (#20411) - Fix `MyEnum.from(0)!`, implement `MyFlaggedEnum.zero()` (#20623) - vfmt,parser: keep the original import name in ast.Import, and use it without modifications for paths unders ~/.vmodules - Allow double quotes in `@include` template directives (#20628) - Fn type declaration does not check already registered name (#20732) - Fix global const ordering with string inter literal (fix #20760) (#20770) - Disallow option alias with option parent type (#20769) - Make Scope.find methods more robust, when called on default initialised `scope &Scope = unsafe { nil }` fields (#20774) - Fix parsing of cgen.v, in normal mode, when the table is empty (no files in `builtin` are preparsed) (fix #20606) (#20611) - Fix infinite loop in Parser.sql stmt in `-silent -print-watched-files` mode (used by `v watch`) ( #20873) - Disallow defining map key more than once (#20905) - Fix formatting comptime if expr, after inc expr (fix #20927) (#20931) - Fix for comptime with fully type name (fix #20948) (#20988) - Allow lock prefix instructions and numbered reg in inline asm blocks (#21022) - Add better error for mut variadic fn argument (#21063) - parser: fix parsing comments after new attribute syntax - parser: fix failures found with fuzzing (#19873) - parser: deprecate old attribute syntax & update remaining (missed) attributes (#19879) - parser: fix infix expr handling with cast on left side of << operator (#19985) - ast: fix generic structs with multiple levels of generic embedding (#20042) - parser: implement thread returns result and multi_returns (fix #19281) (#20194) - parser: fix formatting struct decl with comments (#20207) - parser: fix formatting enum and interface decl with comments (#20216) - parser: fix fn call with newline opening brace (fix #20258) (#20267) - parser: fix parse_vet_file() with vfmt off/on flag (#20273) - Fix assigning static method to anon fn (#19499) - ast: fix formatting a struct declaration with a nested struct (#19592) - Add `set_all` + `clear_all` methods to `[flag]` enum bitfields (#19717) - ast: reduce cost of frequently called functions by using constants (#19733) - Warn on unused imports, even when they are declared via `import math { sin, cos }` (#19738) - ast: add missing docstrings for the public fns in vlib/v/ast/types.v (#19752) - Give a friendly error when misusing if over $if (#19810) - Add multiple struct attributes error for new attribute syntax - parser: fix fixed array with eval const size (#19269) - parser: disallow using `sql` as name (#19298) - parser: fix `;` support for `module x;` - parser: fix fixed array of option values (`_ := [10]?int{}`) (#19392) - parser: fix assigning with in another module sumtypes 2 (#19415) - Support `;` statements, allowing for oneliners like `./v -e 'import os; println( os.ls(os.args[1])!.sorted(a > b) )' vlib/math` (#19345) - v.ast: improve Stmt.str(), showing more details about ast.Block, ast.DeferStmt, ast.ForInStmt, ast.GlobalDecl - Change warn to error, for const names with upper letter (fix #18838) (#18840) - Disallow declaring static functions as method receivers (#19007) - Disallow having builtin type as type names for `enum`, `sum type` and `alias` (#19043) - Support `const x := 123`, to make extracting locals as constants less annoying while prototyping - Fix struct field fn type with default value (fix #19099) (#19106) - Fix `for i++; i<10; i++ {` (fix #18445) (#19035) - Fix fn return alias of fixed array (#19116) - Fix generic struct init (Stack[&Person]{}) (fix #19119) (#19122) #### Comptime - comptime: fix comptime parameter resolve for `unsafe { nil }` to be `voidptr` (fix #25558) ( #25570) - comptime: fix codegen ptr field reading from comptimeselector (fix #25616) (#25620) - comptime: dont emit empty blocks (#26171) - comptime: support type interpolation in the msg argument of `$compile_warn(msg)` and `$compile_error(msg)` (#24992) - comptime: fix $match with fn type (#25271) - Support `$if T is $pointer {` and `$if T is $voidptr {`, to make it easier to implement a pure V dump(), without cgen specific code (#24628) - i32 is now `$int` too (fix #24346) (#24378) - Fix `$dbg` with `@[heap]` structs (fix #23979) (#23989) - Check invalid comptime field name assignment (fix #24415) (#24421) - Enable s390x + docs (#24114) - Add `typeof(var).indirections` and `T.indirections` (#22805) - Add `typeof(expr).unaliased_typ` (#22806) - Allow sumtype init by variant comptime var `T(v)` / `SumType(v)` (#22664) - Fix missing bool AttributeKind.kind (#23159) - Fix comptime `T.methods` with generic types and interface checking with `is` operator (fix #22721) (#22724) #### Compiler internals - markused: fix markused struct heap (#25542) - markused: fix array.prepend C code dependency (fix #25573) (#25582) - markused: fix fn marked as used when variable and fn uses same name (fix #25649) (#25650) - checker,transformer: add always true/false branch detection for the `if` and `match` constructs ( #25674) - v.util: measure more precisely how long a new tool recompilation lasts in launch_tool, when using `v -d trace_launch_tool self` - transformer: fix struct init comparison turning into boolean (#25724) - v.builder: support V_NO_RM_CLEANUP_FILES=1, to ease debugging of -usecache issues - v.builder: make it easier to reproduce the exact specific stages of -usecache module compilation by logging the full CLI options for each - v.builder: fix `.vsh` mode doing an implicit `import os`, now only for .vsh file itself (fix issue spotted in #25736) (#25745) - v.builder: improve diagnostic information for a failed build_thirdparty_obj_file - transformer: transform ArrayInit into a function call for C and native backends (part 1) - builder,pref: add `-file-list` support (implement feature #25707) (#25749) - pref: for -usecache, set .parallel_cc = false and .no_parallel = true to make compilations more deterministic and ease CI diagnostics - markused: fix missing builtin__memdup definition, when an option struct field is used (fix #25801) (#25802) - transformer: move array logic to array.v - v.builder: improve the error message for failing cgen; suggest `-g` and `-show-c-output` - v.pref: fix GitHub download URL for the photonwrapper .so file (fix #25708) (#25831) - v.pref: use `v download` for downloading the prebuilt `photonwrapper` shared library (#25849) - markused: fix const as fn mark as used (fix #25888) (#25895) - transformer: disable generic str_intp opt (fix #25896) (#25897) - v.scanner: remove obsolete .is_crlf and .is_vh fields (#25918) - v.scanner: use a named return for decode_XXX_escape_single methods, to reduce the generated C diff churn, during scanner code updates - markused: add new auto_str() used funcs for bootstrap (#25938) - v.builder: provide more detailed error message, on `msvc: failed to build a thirdparty object`, not just the failed command - v.builder: improve formatting of the `failed to build a thirdparty object` message for msvc - scanner: remove old generic check logic (fix #25959) (#25997) - transformer: fix the setting of a generic flag for fixed array type with `-new-transformer` ( #26009) - transformer: add file/line info for fn with `expand_simple_interpolation` (#26135) - transformer: add early return to avoid transform getting applied twice for a `for x < y {` body ( #26153) - markused: fix option none markused (fix #26147) (#26151) - v.builder: enable gc back with msvc, build separate `.debug.obj` thirdparty files when -g is passed, to prevent linking issues (#26215) - v.builder: support compiling asm .S files to .o files, mentioned in #flag directives (needed for #26185) (#26211) - v.builder: fix compile asm file, followup of PR #26211 (#26227) - scanner: fix multi-level string interpolation in if/match branch (#24805) - markused: fix mark for array init from sumtype (fix #24887) (#24889) - markused: whitelist `_option_none` too (fix #24862) (#24885) - markused: remove `@[markused]` from option and result fns (#24900) - markused: skip unused symbols, dump fns and generic specialization (fix #24921) (fix #24927) ( #24924) - parser,markused: support `@[markused]` for interface declarations too (#24963) - markused: fix interface fields and chan usage (fix #24961) (#24962) - v.builder: add a clearer error message for `v -shared run empty.v` (issue found by Felipe Pena) - markused: use eprintln for `PANIC DEPS` too (for consistency and easier redirection for the whole trace) - v.util: add support for setting VUTIL_RETRY_MAX_COUNT=1 to ease the workflow for developing backends - markused: improve the tracking of used closures (#25009) - markused: improve array resources tracking + remove all_fns loop for orm (#25007) - markused: fix generic map index (fix #25012) (#25022) - markused: improve array tracking (range, gated) (#25023) - markused: fix option tracking on sumtype (fix #25025) (#25028) - markused: fix thread type mark by go/spawn expr (fix #25049) (#25054) - scanner: refactor string interpolation (fix #24198) (#25053) - markused: fix array append c code dependency (fix #25057) (#25058) - markused: fix option array element (fix #23089) (#25179) - markused: fix option map value (fix #25186) (#25188) - parser,fmt,markused: add top level comptime `$if` support (enable `$if platform { import module struct Abc {} }`) (#25216) - v.builder: add -DNO_DEBUGGING in addition to -DNDEBUG, when compiling with -prod - v.builder: support `-d trace_type_symbols_after_checker` - scanner: uncomment working rune test (#25305) - v.util: fix handling of "start \u005c${...} end" in cgen (fix #25304) (#25306) - markused: fix marking of mutable generic method calls (fix #25312) (#25314) - Remove closure usage from the compiler frontend (simplify bootstrapping/porting on more exotic platforms) - markused: support orm or expr (fix #24040) (#24059) - markused: fix for gated index range on string (fix #24187) (#24200) - v.util.version: fix output for V full version when VCURRENTHASH not defined (#24264) - markused: fix generic method call mark (fix #24395) (#24399) - v.pref: add get_build_facts_and_defines/0 and set_build_flags_and_defines/2 - v.util.version: fix output for V full version (followup on issue #24263 and PR #24264) (#24478) - v.util: use internal diff (#24495) - v.pref: prevent overriding backend (fix #21758) (#24526) - markused: fix for generic ptr receiver on method call (fix #24555) (#24558) - markused: fix `x := t.wait()`, when `t := go fn () string {` (fix #24577) (#24580) - markused: fix printing smartcasted interface values (fix #24579) (#24583) - pref: avoid changing the backend with `.js.v` when `-backend` has already been used (fix #7840) ( #24654) - Remove dump() calls inside the compiler itself (make bootstrapping of dump() implemented before cgen easier) - markused: fix `-skip-unused` on a short program, that prints array (fix #23436) (#23437) - markused: fix `eprintln(err)` on imported module on short program (related: #23498) (#23499) - markused: fix markused auto str detection (fix #23501) (#23503) - markused: fix option ptr printing (fix #23559) (#23562) - checker,markused: add identification for sumtype.type_name() call (fix #23732) (#23739) - markused: improve stability (avoid runtime crash) when processing generic functions (partial fix for #23927) - markused: fix markused behavior on array / map index getter / setter / slice (#23931) - markused: fix markused behavior on struct field's default expression (fix #23909) (#23933) - builder: do not search for msvc when it is not needed (#23386) - pref: stop parsing CLI options, on encountering `--` (#23470) - util: show `unknown command` suggestions, for more misspelled variants, like `v sefl`; make util.new_suggestion calls parametrizable - pref: add Preferences.vroot_file/1 (done here, without using it, to ease the bootstrapping of the cheaders extraction, that will follow next) - pref: fix panic in parse_args_and_show_errors, called with no args (fix #23713) (#23794) - pref: allow for `-os wasm32_emscripten` and filtering `_d_wasm32_emscripten.c.v` and `_notd_wasm32_emscripten.c.v` files. (#23797) - v.builder: show the last line of the C compiler output, in case of errors, in addition to the truncated first lines (the last line is useful, since it usually has an error counter) - os,v.transformer: fix warnings for `./v -os cross -o vc/v.c cmd/v && clang-18 -o v_from_vc vc/v.c -lpthread` - util: fix stack overflow during parsing of `#flag -DName=$d(...)` (#23895) - builder: extract Builder.show_parsed_files/0 to make it easier to debug import/parsing issues - builder: remove forgotten b.show_parsed_files/0 call - util.version: centralise the use of `@VCURRENTHASH`, to minimise the vlang/vc diffs for each commit - builder: support `-d trace_parsed_files` - util: shorten the V paths used in the C `#line` directives with tcc (the ../../../.. etc is no longer needed with newer tcc) (#23974) - Add `:parse_text` to the paths of .v files, printed by `-print-v-files`, for parse time generated snippets - v.pref: support a `_wasm32_emscripten.c.v` suffix for platform files too - builder: fix msvc build thirdparty obj file from .cpp (fix #22772) (#22789) - v.util: use temporary workaround for the vinix build problem (when VFLAGS is set, and `-ldflags ` is passed at the same time) - Allow getting notified about unused function params (#22879) - v.scanner: remove `Scanner.is_started` field (#22918) - v.scanner: fix string interpolation for float e format (fix #22429) (#23147) - cbuilder: remove flto with parallel-cc, it slowed down linking 10x - cbuilder: store split up C files in vtmp - v.builder: integrate more compile/linker options into parallel_cc.v (#23190) - v.builder: prevent passing `-x objective-c` with `-parallel-cc` for now - v.builder: move filtering logic for `-parallel-cc` to parallel_cc.v - v.pref: support `-debug` and `-cdebug`, as more explicit alternative names for `-g` and `-cg` ( #23208) - v.builder: fail the whole v compilation, if linking or compiling during `-parallel-cc` fails ( #23211) - v.pref: implement `-no-prod-options` to turn off passing `-O3 -flto`, while still keeping the `$if prod {` branches (passing custom flags with `-cflags -Os` already works) - v.builder: support `-no-prod-options` with `-cc msvc` as well - scanner: guard against scanner panic, discovered by fuzzing in PR#22016 - v.builder: show the thirdparty object compilation commands too, when using `-showcc` (when the cache is empty) - builder: allow for `v -dump-defines - -check cmd/v`, which is faster, because it can skip code generation - Reduce allocations for the most common cases (#22142) - transformer: add support for instrumenting the V compiler with `-d trace_transformer` - tools,cgen,pref: add `-coverage` support + `vcover` tool (#21154) - v.utils: allow to set the names of the compared items, when diffing strings (#21650) - v.pref: fix regression of command flags not working, when there is a subfolder, named after the command, in the current working folder (#21647) - transformer: handle `enum_variant = some_const + 10` (fix #21777) (#21779) - v.builder: print the suggestion for using `v xyz` instead of `v xyz.v` just once (#21801) - v.builder: improve the C compilation output on cgen errors (#21885) - v.scanner: use table lookups for very frequently done character checks (#21931) - markused: mark explicitly all used array and map methods with `-skip-unused` (fix #21907) (#21914) - v.util: use tmp instead of cache dir for temporary diff files (#21075) - v.util: fix module lookup if module import parts end with the word `modules` (#21083) - v.util: update `githash` to be able to get the githash of every passed project (#21178) - v.util: improve detection for opendiff when automatically searching difftools (#21241) - v.util: improve color_compare_files (#21247) - v.util: improve find_diff_cmd: don't add spaces to result without env opts (#21242) - v.util: fix diff coloring, add test (#21260) - v.util: polish off diff utils after recent updates and fixes, add doc comments to pub fns (#21275) - v.builder: suggest using `v wipe-cache`, when the object files are not recognized - pref: be more conservative when generating code using `-cross`, allow for `$if cross ? {` - builder: use cc enum in CcompilerOptions, fix cc detection, enable cc guessing without prod flag ( #21370) - pref: fix version flag handling (#21377) - pref: make minor performance related changes / simplify (#21379) - builder: simplify generic cc detection (#21380) - pref: extract architecture related code into `arch.c.v`; rename `pref.c.v` to `pref.v` (#21387) - pref: update `os_from_string`, add missing `qnx`, remove deprecated wasm options that used `-` instead of `_` (#21390) - v.util: rewrite diff module, deprecate old functions (#21403) - v.util: fix color when auto tool is `diff` (#21435) - v.util: make diff_test.v more robust to the color settings for the chosen local diff tool - v.util: fix performance with `v test-cleancode`, when a slower diff tool is installed (#21447) - v.util: remove fast path in `diff.compare_text` (#21458) - v.pref: error for `v file.v --unknown-option` (#21391) - v.util: make launch_tool failures more detailed (for the `Text file busy; code: 26` case), bump tool_recompile_retry_max_count from 3 to 7 - v.util: make launch_tool more robust, when multiple `v -b js file.v` commands are run at the same time (all trying to recompile the JS backend program) (#20631) - builder: allow for `./v -freestanding -cc riscv64-elf-gcc -d no_main -no-builtin -no-preludes -showcc -keepc x.v` - pref: support file_notd_freestanding.v + file_d_freestanding.v, remove dependency to `os`, of $ embed_file(), when compiling with -freestanding (#20712) - v.builder: reduce the default noise from successfully rebuilding cached thirdparty object files - pref: allow fetching the photonwrapper .so (for the coroutines) with curl too, or print details for manual download (#20855) - scanner: disallow a shebang line, that is not at the top of a file (#21029) - strings.textscanner: fix off-by-one error in skip method (#21045) - scanner: implement support for UTF-32 escape codes in string literals (#19911) - scanner: add new_silent_scanner/0, Scanner.prepare_for_new_text/1, make .ident_char/0, .ident_string/0 and .text_scan/0 public (#20045) - pref: support VNORUN=1, to enable running of tests, vsh files etc (i.e. just compile them, for debugging later) - scanner: fix backslashes followed directly by newline in string literals (fix #20291) (#20296) - scanner: fix escape character handling in character/rune literals (fix #20301) (#20304) - pref: disable the -macosx_version_min clang flag by default (#20297) - builder: remove passing `-fno-strict-aliasing`, for `-prod` to gcc/icc (#20368) - markused: add `-skip-unused` for programs that `import x.vweb` too (do not skip unused routing methods) - checker, builder, pref: support `-dump-defines -` to help explore all the available user and system defines for a given program (#19576) - pref,builder: add support for `-macosx-version-min 10.2` and `-macosx-version-min 0` (with default of 10.7) (#19626) - pref: fix unintended file extensions in default output names, allow for `v run file.c.v` (#19745) - transformer: fix using a constant, instead of a fn parameter with the same name (fix #19766) ( #19773) - maps: add maps.merge() and maps.merge_in_place() generic utility functions (#19776) - coroutines: only attempt to add/remove roots when GC is on. - markused: cleanup in mark_used(), use robust index names, instead of the much more brittle integer values (#19543) - pref: support `-fast-math`, passing either -ffast-math or /fp:fast (for msvc) to the C backend, and `$if fast_math {` to detect it at comptime - parser, transformer: fix transformer.infix_expr() and cleanup parse_types.v (related #19269) ( #19276) - pref,builder: support -use-os-system-to-run to workaround segfaults using not fully updated xcode command line tools - v.builder: fix compiling code, that imports modules from both `src/modules` and `modules` (#19437) - os, v.builder: show more details, when a program ran by `v run file.v`, exits by a signal (fix #19412) (#19471) - pref: make -autofree work without -gc none - builder,pref: allow thirdparty objects compilation with CPP compiler (#19124) - scanner: fix string interpolation with nested string interpolation in inner quotes p. 3 (#19121) - scanner: error early on an unsupported escape sequence in a string, like `\_` (fix #19131) ( #19134) - v.token: add inline next_to() and cleanup related calls (#19226) #### Standard library - arrays: fix rotate_left() and rotate_right(), add test (#25539) - encoding.base58: fix encoding, add test (#25538) - x.crypto.chacha20poly1305: move up responsibility for allocs into higher caller (#25574) - crypto.cipher: fix decryption in CBC mode, add test (#25584) - os: use `@[noinline]` on os.create/1 to workaround a `-cc gcc -prod` panic (fix #25549) - time: fix non-digit checks for parse_rfc3339() (#25597) - gg: add explicit bounds checking for image caching methods in gg (fix #25590) (#25591) - time: fix quarter calculation in custom_format() (#25608) - rand: fix randomness in shuffle() (#25617) - gg: destroy unused GPU resources before replacing cached images (#25615) - encoding.binary: fix serialize skip struct shared fields (related to issue #25600) (#25613) - x.crypto.chacha20poly1305: make implementation use fixed sized arrays more (#25627) - builtin: make result string end with null in `u8(x).repeat(y)` (fix regression after #22100) ( #25625) - gg: fix address of const warnings for `v -experimental program_using_gg.v` - builtin: add .hex() methods to the `rune` and `char` types too (#25635) - datatypes: fix insert() and delete() for items in second half of DoubleLinkedList[T]{}, add test ( #25647) - builtin: use an explicit loop to determine min_common_indent in string.trim_indent/0 to reduce allocations and reduce the reasons for misfires of the closure detection heuristic - vlib: use `defer(fn) {` syntax where appropriate (part 2 of #25639) (#25653) - x.json2: fix decode_number not initializing value to zero (fix #25641) (#25675) - crypto.hmac: optimize hmac.new, support calculations with a blocksize > 256 (#25686) - math.unsigned: fix put_bytes(), add test (#25718) - builtin: reset .len and .cap to 0 too, in the array.free() method (#25717) - os: add pipe and stdio_capture support (implement #25714) (#25716) - encoding.utf8.validate: fix validation, add test (#25748) - crypto.blake2b,crypto.blake2s: add `@[direct_array_access]` to hot functions (#25750) - strconv: fix handling of subnormal numbers like `'1.23e-308'.f64()` (fix #25751) (#25752) - crypto.sha3: remove `import math` (just for int_max), to improve compilation time and complexity for code that uses sha3 - builtin: add declarations for C.GetCurrentThreadId(), C.gettid() and C.pthread_self() - builtin: add pid: and tid: fields to the panic reports (part 2 of #25808) (#25809) - gg: add doc comments for the FN** types (#25814) - rand: add missing i8() utility function (#25819) - builtin: fix C.SYSTEM_INFO (fix #25788) (#25823) - builtin: support `-d no_getpid` and `-d no_gettid` for systems that lack proper process management APIs - math: fix vec2,3,4 project not using the right formulas (fix #25811) (#25813) - math.vec: swap u and v in the .project() method of Vec2,Vec3,Vec4 (#25841) - crypto.cipher: fix xor_key_stream() for OFB mode, add test (#25844) - encoding.binary: use unions for small speed increase and readability (#25867) - math.complex: replace `==` with eq_epsilon() in equals() (#25873) - crypto.cipher: fix xor_key_stream() for CTR mode, add test vector created with OpenSSL (#25866) - os: enhance os.cp() to mimic Python's shutil.copy2() (#25893) - io.util: use correct TempDirOptions parameter type name in temp_dir() (#25904) - builtin,sync: eliminate calls to _us32_lt in new_map/6, and in the spinloops in Channel.try_push_priv, Channel.try_pop (#25912) - rand: restore error margin in dist_test.v back to 0.05 (the updated seeds were found by @tankf33er in #25907) - builtin: reduce the max size of string representations of integers (#25919) - builtin: remove commented code, improve comments - x.crypto.chacha20: fix deprecation warning during compilation of Cipher.rekey/2 - math.easing: fix in_out_expo(), add test (#25944) - builtin: split builtin.v and builtin.c.v into smaller, and more focused .v files, to ease working on unrelated subsystems (#25965) - transformer: fix `v -new-transformer vlib/strconv/atoi_test.v` (#26021) - gg: add more documentation for color substraction (fix #21549) (#26023) - toml: fix for single `\r` occurence in multi-line `"""` strings (`\r\n` is still allowed) (#26029) - toml: remove workarounds + `TODO`s for fixed issue #9507 (#26037) - x.json2: fix decode_number for u8 (fix #26027) (#26033) - rand.wyrand: switch to using the original C._wymix() as a performance optimisation (#26051) - strconv: fix float scientific notation (fix #26045) (#26046) - x.json2: fix decoding of float values in scientific notation (fix #26043) (fix #26062) (#26060) - builtin: add a declaration for C.memchr too (#26054) - toml: add compliance up until official toml-lang/toml-test@c6a78f1 (#26067) - builtin: fix some C fn parameter types (#26069) - toml: add compliance to official toml-lang/toml-test@8bb8d9c (#26070) - toml: remove special cases for `jq` normalization (#26092) - toml: fix remaining valid `key/*` exceptions (#26125) - builtin: make string.index_ public, to simplify code using a redundant `x := s.index(sub) or { -1 }` pattern (#26123) - builtin: add declarations for C.memmem and C.mempcpy (#26129) - builtin: speed up, fix and test impl_utf8_to_utf32 (#26109) - toml: fix remaining valid `array/*` exception (#26138) - toml: fix unicode decoding panic on invalid TOML `key/duplicate-keys-06.toml` (#26140) - toml: allow `true` and `false` as keys when parsing root table (#26144) - toml: allow dotted key lengths > 2 within nested arrays of arrays (#26145) - flag: fix `v vet -W vlib/flag/` (fix remaining doc comments) - x.json2: fix memory access error, when decoding string enum values (fix #26176) (fix #26179) ( #26178) - toml: fix invalid exception by erroring on duplicate keys in inline table (#26177) - time: implement faster and simpler `push_http_header` (#26155) - toml: fix remaining invalid exceptions for `table/*` (#26189) - toml: reach 100% TOML v1.0.0 compliance with the official test suite (#26203) - x.json2: remove workaround_cast(), add isize usize decode support (#26210) - x.crypto: initial addition of curve25519 module (#24748) - thirdparty: add NDEBUG check before glGetErrorCode if-statement in sokol_gfx.h (#24754) - math.big: remove unnecessary code from / and % (the same is done in div_mod, which they call) ( #24766) - builtin: add a rune iterator method to strings, allowing `for for i, r in s.runes_iterator() {` without first allocating an array for all the runes (#24769) - builtin: support `-d builtin_free_nop` to help diagnose problems with too early manual free() calls - builtin: use s.runes_iterator() in trim_runes/2 to avoid needless allocation - builtin: add string.expand_tabs() (#24781) - os: do not resolve symlinks in os.find_abs_path_of_executable/1 (fix #24759) (#24761) - os: improve documentation (#24790) - gg: allow for `-d gg_memory_trace_frame` to be used in combination with `-prealloc -d prealloc_dump` - sync: add SpinLock (#24788) - os: fix documentation for environ function (#24796) - sync: fix documentation for new_spin_lock function (#24795) - sync: add implementation for WaitGroup.go/1, add test (#24797) - sync: improve documentation (#24799) - sync: fix spin lock, add destroy() and try_lock(), add valgrind annotate support (#24798) - os: add os.write_bytes/2 as a complement to os.read_bytes/1, add test - sync: use SpinLock for channel (fix #24680) (#24802) - crypto: fix ambiguous expressions in DES implementation (#24814) - sync: use an atomic counter in test_waitgroup_go in waitgroup_test.v - datatypes: add lockfree version of counter and ringbuffer (#24839) - sync: add thread local storage (TLS) support (#24849) - math.unsigned: fix rotate_left() for uint256, add test (#24872) - math.unsigned: replace untested comments for uint256 public APIs (#24873) - log: use `@[noinline]` for level_from_tag/1 and target_from_label/1 to avoid triggering panics for programs using `log`, compiled with -prod and -cc gcc>10 (fix #24874) - math.big: fix toom-cook 3-way multiplication (#24888) - runtime: add used_memory() (#24897) - runtime: add note for the availability of the used_memory implementation (#24913) - os: remove commented code in home_dir() function (#24929) - math.big: fix the order of calculations in mod_pow() to improve performance (#24935) - math.big: add shrink zeros to karatsuba and toom-cook (#24937) - math.big: fix big_mod_pow() (#24939) - os,runtime: move some C struct and fn def to `builtin` (#24942) - math.big: fix validate_string and integer_from_regular_string (check for characters.len > 0, before accessing characters[0]) - builtin: prepare for adding a `-force-bounds-checking` option - strconv: fix bounds check bug, discovered by the equivalent of `./v -g -force-bounds-checking test vlib/toml/` (thanks to tankf33der) - builtin: fix OOB bugs in s.is_bin, s.is_oct, s.is_hex, discovered through `./v -force-bounds-checking test vlib/builtin/` - regex: fix OOB bug discovered through `./v -g -force-bounds-checking vlib/regex/` (fix by @penguindark) (#24960) - time: fix custom_format panic (fix #24977) (#24987) - time: fix more panics in the supported specifiers in Time.custom_format/1 (#24988) - vlib: add `archive.tar` module to enable reading of .tar ang .tar.gz files (#24995) - builtin: fix warnings for `./v doc -m -f html vlib/builtin/` - sokol.gfx: set the missed array_count field too in the `set_vert_uniform` and `set_frag_uniform` APIs (#25019) - builtin: fix `assert "ä ö å æ ã ø ô é ë".title() == "Ä Ö Å Æ Ã Ø Ô É Ë"` (fix #25017) (#25026) - Apply `@[markused]` to builtin_init, remove its heuristic from markused.v - gg: improve drawing effect and logic of draw_rounded_rect_empty (#25062) - math.bits: add asm implementations for some 64 bit ops (#25020) - vls: autocomplete for module functions: e.g. `os. ...` - math.big: move from u32 to u60 digits (#25018) - os: simplify file.c.v using cross platform f.seek/2 calls, add EINTR handling to f.write_full_buffer/2 (fix #25107) (#25110) - builtin: add arr.pop_left() func (#25133) - math.big: refactor add_digit_array() (#25138) - math.big: optimize add_digit_array() (#25139) - math.big: optimize subtract_digit_array() (#25142) - strconv: produce a maximum of 8 digits after the `.` for f32.str() (fix #25141) (#25144) - math.big: restore and refactor str() and integer_from_string() (#25154) - os: remove `unknown host OS` panic from os.get_host_os() - flag: fix tail/single bool flag error condition logic in `flag_to.v` (fix #25166) (#25172) - flag: improve the fix for #25166 tail/single bool flag error in `flag_to.v` (#25189) - readline: fix wide char display width for Chinese characters (fix #25219) (#25220) - repl: fix handling of lines with comments like `math.pi // comment` (fix #25229) - time: always return utc() timezone for Time.unix/0 (fix #17784) (#25233) - builtin: fix C prefix for proc_pidpath() (#25239) - math.big: replace division with Knuth, improve performance (#25242) - time: move the nanosecond comparison before the rest in the Time == Time implementation - builtin: add a temporary ctovstring_impl/1 API to enable `ui` to compile cleanly for PR#25264, part 1 - json2: replace encoder with new implementation (#25224) - json2: improve enum decoding; fix handling of required fields at the end of a json string (#25289) - json2: improve checker with better EOF detection (#25075) - json2: prepare for moving into json2 (#25039) - json2: fix remaining json2 discrepancies (#25029) - json2: support custom decoders (#25021) - json2: fix number decoding and improve errors (#25015) - json2: add support for decoding utf-16 surrogates, produced by some JSON encoder implementations ( Python, Java, C#) (#25193) - x.crypto: add a new `ascon` cryptographic module, based on https://doi.org/10.6028/NIST.SP.800-232 (Lightweight Cryptography Standards for Constrained Devices) (#25260) - x.crypto.ascon: improve the core of Ascon permutation routine (#25278) - x.crypto.ascon: improve single-shot functions of ascon hashing variant; add benchmark (#25282) - x.crypto.chacha20: improves the internals of chacha20, add a bench (#25311) - builtin: string.index_after() ?int - cli: account for initial indent on subcommands (#23985) - Remove `strings.Builder.clear()`, fix `array.clear()` not working in the JS backend (#23992) - gg: make draw_rect_empty/5 draw more exact borders, independent of the device, and fitting the draw_rect_filled/5 shapes (#24024) - sync: fix a helgrind false positive, for a data race, on PoolProcessor (#24023) - sync.pool: restore the parallel operation (surrounding the cb call in process_in_thread in a lock in 1b52538, effectively disabled parallelism) - x.crypto.chacha20: change internal cipher to support a 64 bit counter (related to #23904) (#24039) - os: fix swap_bytes_u64 (#24033) - x.crypto.chacha20: fix `xor_key_stream` failing after a while (fix #24043) (#24046) - crypto.sha3: be big-endian friendly (#24045) - x.crypto.chacha20: makes the underlying cipher routine aware of the 64-bit counter (#24050) - x.crypto.chacha20: enable support for 64-bit counter (fix #23904) (#24053) - x.crypto.slhdsa: add a SLH-DSA implementation, a stateless hash-based DSA, a post quantum cryptographic module (#24086) - encoding.binary: add encode_binary()/decode_binary() generic functions (#24106) - crypto.rc4: change the return type of `new_cipher` to be `!&Cipher` (#24113) - crypto: add a `crypto.ripemd160` module (#24119) - encoding.iconv: fix iconv on termux (fix #23597) (#24147) - sync: remove the call to C.pthread_rwlockattr_setpshared (not needed, since it is the default on POSIX) (#24166) - pkgconfig, termios: Support NetBSD (#24176) - encoding.binary: fix serialize map struct (fix #24190) (#24192) - builtin,v.gen.wasm: support `-b wasm -d no_imports` (#24188) - datatypes: add a Set.array/0 method to help get all the elements from a set as an array (#24206) - json: fix option time (fix #24242) (fix #24175) (#24243) - log: add local time / utc time selection support (#24268) - json: link with libm (fix #24272) (#24273) - rand: add uuid_v7(), session function, simplify uuid_v4() (#24313) - toml: fix handling of multiline string with CRLF (fix #24321) (#24322) - toml: fix crlf escape check (fix #24328) (#24329) - x.json2: add u16(),u32() (fix #24337) (#24342) - rand: fix uuid_v7 seperator (#24348) - rand: check the separators for the generated UUIDs in random_identifiers_test.v - builtin: add string.is_identifier() (#24350) - x.crypto.chacha20: add a check counter overflow to set_counter for standard mode (#24365) - comptime: fix `$if var.return_type == 1 {` (fix #24391) (#24393) - comptime: enable ppc64le, add docs (#24433) - toml: add compile error when passing `encode/1` types of T != struct (fix #24435) (#24443) - sync.stdatomic: workaround for libatomic.a indirect symbols tcc bug (fix #23924) (#24472) - math.big: fix the + operator for big.Integer for negative numbers, add test (#24487) - math.big: respect the sign of the dividend in % operator, add test (#24489) - os: add note for the availability of the debugger_present implementation (#24492) - term: add writeln_color() (#24463) - math.big: add missing assert for test_multiply_karatsuba_02 (#24534) - builtin: fix mix prod and debug ucrt lib (#24498) - math.big: fix Karatsuba's add_in_place() function, add carry handler on exit (#24541) - math: add `exp_decay` to `interpolation.v` (#24545) - math.big: optimize divide_array_by_digit() (#24566) - sync.stdatomic: add atomic types (#24561) - sync.stdatomic: turn panic() in new_atomic[T]() into a $compile_error() (#24573) - sync: add condition support (#24574) - builtin: flush stdout on panic (#24606) - Document the behaviour of % for negative numbers; in V: -10 % 7 == -3 (#24604) - math.big: remove unnecessary casting from Integer.is_power_of_2/0 (#24614) - math.big: make is_power_of_2() be false for negatives (it now matches Julia's ispow2/1) (#24619) - vlib: vanilla_http_server (#24202) - os: support `dotfiles := os.walk_ext('.', '', hidden: true)` (#24617) - builtin: remove playground related code (the current playground uses a container/sandbox) (#24632) - comptime: fix `T.indirections` comparison (fix #24630) (#24636) - math.big: add test for radix_str() and integer_from_radix() (#24644) - runtime: make free_memory() and total_memory() return Result types to allow for reporting errors ( #24651) - math.big: improve the performance of radix_str() ~9 times (#24666) - math.big: speed up ~10x integer_from_radix() (#24674) - sync.stdatomic: fix bug with add() and sub() returning the new values, add voidptr support, add swap() and compare_and_swap() (#24685) - sync.stdatomic: add atomic_thread_fence(), cpu_relax() (#24690) - v: support `@DIR` (as a comptime equivalent to `os.dir(@FILE))` at runtime) (#24742) - thirdparty: print the glGetError() code on failure too in sokol_gfx.h, to make diagnostic easier - builtin: make array.ensure_cap/1 public - os.font: fixes for `-os android` - vlib: add a pool module (#24661) - zstd: make the api more V like - szip: fix panic on empty files (#24335) - json: fix default struct field initialization with long array (#23355) - markused,builtin,strconv,vlib: reduce generated C sizes for compilers != tcc, for short programs, by simplifying the generation of backtraces, and reducing string interpolations in panics (#23380) - thirdparty/sokol: allow `-cflags -D_SGL_DEFAULT_MAX_VERTICES=4194304` to customize how many vertices you can send through gg/sokol in a frame - crypto.ecdsa: expand ecdsa module, to support other curves like secp384r1, secp521r1, secp256k1 ( #23407) - crypto.ecdsa: fix memleaks, reported by the CI sanitizer jobs (#23450) - ci: force the checking of changed vlib/crypto/ecdsa files with the sanitizer jobs - builtin: add a `@[markused]` tag to `isnil()`, because cgen generates calls to it in some cases ( #23462) - builtin: reduce a bit the generated #if defined checks for small programs (#23484) - crypto.ecdsa: improve safety checking, unify signing (and verifying) api to accept options ( #23463) - regex: fix misspelled word "firts" in replace_n description (#23514) - os: add split_path/1: `os.split_path('/usr/lib/test.so') -> ('/usr/lib','test','.so')`; fix platform dependent behaviour of os.dir/1, os.base/1, os.file_name/1 (#23532) - breaking,log: set stderr as default log output, add .set_output_stream() to allow for opting in the old default of stdout (#23444) - builtin: add `-prealloc -d prealloc_memset -d prealloc_memset_value=65 -d prealloc_dump`, to better analyze the memory patterns of running V programs - builtin: change the default builder size used for string interpolations, from 256 bytes to 64 bytes - gg: mark create_image_with_size as deprecated (image resizing is done by `stbi.resize_uint8/3`, with a different fn signature) (#23580) - crypto.ecdsa: split out the C wrapper to a new .c.v file (#23595) - builtin: add &u8.free() (fix #23592) (#23598) - crypto.ecdsa: fix bug in .with_no_hash handling (#23612) - crypto.ecdsa: fix handling of sign() with custom_hash (#23619) - runtime: add note for the availability of the free_memory/0 implementation (#23620) - builtin: make public the `FnGC_WarnCB` alias (#23633) - os: add disk_usage/1 (#23634) - builtin: add string.split_by_space() (#23651) - crypto.ecdsa: migrate `ecdsa.PrivateKey.new()` to use a high level API (#23640) - gg: fix incorrect Event.mouse_x and Event.mouse_y on gg.Context.event_fn and gg.Context.on_event on HiDPI displays (#23668) - crypto.ecdsa: migrate generate_key and simplify it (part 3) (#23662) - encoding.csv: add support for multithreading to `encoding.csv.RandomAccessReader` (#23677) - v.builder: add` os.quoted_path()` to os.system calls using v.pref.out_name, for the compress flag (fix #23685) (#23686) - time: reduce chances of failures on the CI, by time_test.c.v; make the failure diagnostic easier - time: improve the robustness of time_test.c.v (check if the diff is within ±1 second of the current timezone difference) - crypto.ecdsa: migrate core routines for signing (and verifying), it now requires using OpenSSL 3 ( #23705) - all: use arguments() instead of os.args in some files - math.big: fix 1/115792089237316195423570985008687907853269984665640564039457584007908834671663 leading to panic (fix #23771) - v.cflag: support `#flag $when_first_existing(libABC.a, /some/path/libABC.a, ...)`, without panicing (unlike `#flag $first_existing(...)`) (#23780) - term: add more comments in vlib/term/README.md - log: fix panic on mutex destroy, when exiting a program, while a thread is still logging - log: fix valgrind_test.v failure - math.vec: add `rotate_around_*` (cw/ccw) functions to `vec.Vec2[T]` (#23807) - math.big: bump newton_division_limit to 1_000_000 (workaround issue #23806) - math.big: add vlib/math/big/big_division_test.v (follow-up to 270941a) - strconv: fix strconv.atof64() inconsistency with the other .ato functions; make it return an error by default, when it detects an extra non number character after a number (#23815) - os: add File.write_u8/1 and File.read_u8/0 helper methods - ci,os: fix bootstrapping with `-os cross -o vc/v.c` (avoid the generic calls in the new write_u8 and read_u8) - log: remove the notice about the stdout -> stderr migration (#23837) - veb: fix "error parsing request: io.Eof" when expecting a request body, but the data is not ready yet (fix #22464) (#23842) - json: fix json.decode autofree codegen (fix #23834) (#23839) - time: add .week_of_year() method for time.Time instances (#23838) - time: add documentation for remaining time-related functions and ISO 8601 parsing (#23867) - crypto: add missing doc comments for public methods (#23864) - builtin,os: fix warnings for `./v -os cross -o vc/v.c cmd/v && cc -o v_from_vc vc/v.c -lpthread` - crypto.ecdsa: migrate new_key_from_seed to use high opaque, simplify the logic (#23876) - math: fix `./v -prod -cstrict -cc gcc-11 vlib/math/math_bench_test.v` (use unions to implement f64_bits/1 and f64_from_bits/1 for compilers != tcc) - crypto.ecdsa: complete the migration to the newer OpenSSL APIs (follow up to #23876) (#23877) - x.json2: add a convenience Any.as_map_of_strings/0 method - cli: add missing struct members to str() method and fix some comments (#23893) - crypto.ecda: improvement the performance of `PrivateKey.new` by avoiding match+assignments ( #23899) - crypto.ecdsa: improves internal function of `calc_digest_with_evpkey` (#23901) - crypto.aes: fix notices about order of operations (fix #23898) (#23902) - Revert "math.bits: port changes from e66e996, so that `-cstrict -cc gcc-11` passes for `markdown` as well" - crypto.ecdsa: improve the performance of the `.public_key` method of `PrivateKey` (#23920) - gg: add is_key_down/1 helper method - datatypes: optimize linkedlist (fix #23928) (#23934) - x.json2: fix "\\" scanner bug, disallow (ch < 0x20) unescaped control characters (#23954) - crypto.ecdsa: improve internal `sign_digest` routine (#23960) - builtin: improve performance of `string.starts_with/1` and `string.ends_with/1`, when compiled with tcc (#22620) - builtin: improve `fixed_array_any_all_test.v` (related #22609) (#22621) - builtin: temporary fix fixed_array_any_all_test.v (#22624) - builtin: support `-d no_gc_threads` for turning off passing `-DGC_THREADS=1` while compiling the GC library - encoding.utf8: fix is_punct func (fix #22646) (#22647) - log,time: improve performance for writing a line to a log, add Time.format_rfc3339_micro/0 ( #22662) - flag: add missing short flag match in `flag.to_struct`, add test (#22696) - bitfield: add `shift_left/1` and `shift_right/1` methods to `BitField` (#22700) - x.json2: pre-arranging the replacement of the decoder, to match https://github.com/enghitalo/v/tree/decoder2_to_json2 (#22729) - builtin: improve fixed_array_any_all_test.v (#22746) - builtin: add `string.is_pure_ascii()` (#22748) - os: document the various enum values in os.Signal (#22770) - builtin: fix runes.to_upper() (fix #22742) (#22755) - ci: use os.system to redirect output - vlib: initial addition of `x.encoding.asn1` (#22783) - os: work towards being able to again use `-autofree` while recompiling the V compiler several times - x.encoding.asn1: fix time creation to also accommodate negative timezone offsets (#22861) - vlib: remove modules/functions/fields, deprecated in 2023 (#22750) - term: improve performance of repeated can_show_color_on_stdout and can_show_color_on_stderr calls, by caching their results (#22893) - builtin: make int_min/2 and int_max/2 public - json: mark json_print_pretty/1 with `@[markused]` (used by cgen) - math.big: use `@[manualfree]` to workaround -autofree compilation issues with gitly, and other projects using `crypto.rand` and `math.big` - x.encoding.asn1: improve performance (#22948) - gg: use a larger fontstash text atlas by default (2048x2048, and customizable), instead of 512x512 (fix #21610) (#22959) - Revert "os: deprecate `os.getwd` in favor of `os.get_current_dir` (part 1) (#22966)" - log: tag log.fatal with @[noreturn] (#22986) - runtime: force runtime.nr_jobs() to return 1, while V is bootstrapping itself, from vc/ source, that was compiled with `-os cross` (fix #22991) - json: fix decode codegen for []&type (fix #23007) (#23010) - os: add os.get_trimmed_lines() too - crypto.sha3: add support for Keccak-256 and Keccak-512 (#23058) - rand: add missing i32 APIs, corresponding to the int ones - math.big: fix `assert big.integer_from_int(1) == big.integer_from_bytes([u8(0), 0, 0, 0, 1])` (fix #23115) (#23124) - math: use libc wrappers for math.log2/1, math.log10/1, math.log1p/1 and math.log_b/1; make `assert math.log10(10) == 1.0` pass in the common case (#23129) - gg: add `icon` field to gg.Config, for easier access (fix #23135) (#23138) - math: fix math.log10() for `-exclude @vlib/math/*.c.v` (fix #23136) (#23140) - json: add primitive type validation (fix #23021) (#23142) - json: fix memory leak on result messages (checked with `json_option_raw_test.v`, compiled with `-fsanitize=address,pointer-compare,pointer-subtract`) (#23172) - vlib: add new `rand.cuid2` module (#23181) - json: fix memleak on sumtype decoding (#23197) - vlib: enable more satnitized memleak detection runs without false positives on the CI (#23200) - json: fix argument freeing for json.encode and json.encode_pretty calls (#22781) - encoding.base58: fix notice for slice creation (#21935) - gg: reset ctx.mouse_d? and ctx.scroll_? at the end of each frame (fix #21945) (#21946) - builtin: v_segmentation_fault_handler signal_number i32 - builtin: fix 'aaaa'.split('aa') (fix #21936) (#21951) - builtin: panic on trying to grow arrays with capacity bigger than 2^31, instead of overflowing a.cap (partial fix for #21918) (#21947) - gg: add a note that Context.new_streaming_image has to be called after Sokol's setup - gg: add more documentation comments for gg.Config (the parameters of gg.start and gg.new_context) - regex: fix regex.split() (fix #16876) (#21953) - json: increase test cases before enabling sumtype decode in all json libraries (#21958) - gg: change the type of gg.DrawImageConfig.rotate from `int` to `f32` - gg: deprecate gg.DrawImageConfig.rotate, in favor of gg.DrawImageConfig.rotation, improve the documentation comments (#21963) - x.crypto.chacha20: make Cipher struct public (fix #21967) (#21968) - tmpl: fix an extra newline in @for; builtin: some i64 fixes - gg: add an optional size: parameter to the .draw_pixels and .draw_pixel methods (defaults to 1.0) - sokol: update to match upstream at c0e0563 (#21971) - Add support for `Any` in `decode_struct`, `encode_struct` and `to_any` (#21972) - crypto.cipher: make Stream.xor_key_stream implementers require a mutable receiver (#21974) - sokol.audio: fix `./v -cc clang-18 -gc none simple_bytebeat.v` (the audio depends on threads) - time: `d`,`c`,`dd`,`ddd`,`dddd` pattern support for parse_format() (#22003) - flag: add optional value description to string parameters (#22024) - flag: add custom value descriptions for bool, int, and float flags too (#22032) - flag: fix assigning to `@[tail]` field when no fields has been matched yet in `flag.parse[T]()` ( #22043) - crypto: add a crypto.pbkdf2 module (#22047) - hash: add more methods to the hash.Hash interface, to match the ones in Go (#22001) - arrays: simplify arrays.sum and arrays.reduce (#22076) - x.json2: support @[skip] as well (#22077) - builtin,thirdparty: fix compilation of libgc with `-cc msvc -gc boehm` (thanks to @Ekopalypse) - stbi: change Image.data from voidptr to &u8, to reduce casts (#21977) - time: update parse_format comment description in parse.c.v (#22104) - vlib: add an `arrays.parallel` module, containing `parallel.run/3` and `parallel.amap/3` implementations (#22090) - builtin: support `-d builtin_print_use_fprintf`, make the C fn declarations stricter (#22137) - builtin: fix map.clear() not resetting map's metas and keys blocks (fix #22139) (#22140) - builtin: fix incomplete m.clear(), allowing the map to have a duplicated entry for its first key ( fix #22143) (#22144) - builtin: fix m.clear() having different observable behavior to `m = {}`, after multiple iterations of setting keys and clearing (fix #22145) (#22146) - builtin: fix bug in .clear() caused by sizeof(u32) being 4, not 2 (fix #22148) - flag: add support for parsing `flag.FlagParser` style flags in `to_struct[T]` (#22152) - flag: fix parse_bool_value() (#22160) - flag: correct bool logic, add test (#22162) - flag: fix parsing `flag.FlagParser` style short flags in `to_struct[T]` (#22172) - gg: change the type of PenConfig.thickness to f32 - builtin: remove remaining references to v_calloc in function comments (#22179) - builtin: remove string interpolation from panic/1, to be able to use tools like cbmc in more cases (#22182) - flag: add a relaxed parsing mode, that turn flag match errors into `no_match` entries instead ( #22191) - encoding.binary: add `u16`/`u32`/`u64` -> `[]u8` conversion functions (#22193) - crypto.sha1, crypto.sha256, crypto.sha3, crypto.sha512: improve performance for non prod builds, by tagging the block_generic functions with `@[direct_array_access]` - builtin: fix string.trim() (fix #13021) (#22205) - crypto.bcrypt: reduce runtime cost for running bcrypt_test.v, by reducing the iteration count - crypto.scrypt: add a new `scrypt` module to vlib/crypto (#22216) - sync.stdatomic: add OpenSUSE paths for libatomic - crypto.scrypt: add missing comment of source for test vector (#22222) - json: allow passing an anon struct as a decode type (#22228) - flag: fix parse_bool_value() with different order short args (fix #22176) (#22242) - builtin: drop C in int.v (#22245) - strconv: fix format_fl()/format_es() (fix #13210) (#22244) - json: fix decoding of structs with embeds (#22264) - crypto.rand: add support for convenient generation of a random big integer in the interval `[0, n)` (#22266) - json: fix json encode/decode with embed support (#22277) - io: add a BufferedWriter and supporting methods (#22265) - vlib: add a go like `x.benchmark` module, that estimates automatically how many iterations are needed, to get a statistically significant result (#22215) - math: document q_rsqrt - io: make buffered_writer_test.v more robust - builtin: enable GC lib on rv64 build (#22319) - json: support null sum types in decode() - crypto: ecdsa module (on top of openssl) - bench: crypto/ecdsa.v - math.big: fix `a + b` and `a - b`, when the signs are different, add more test cases (#22330) - builtin,v: reduce overhead and memory usage for very frequently called methods (#21540) - builtin: reduce allocations in s.index_kmp/1 and s.replace/2 (#21561) - os: remove mut declarions for unchanged vars in `os_nix.c.v` (#21564) - os: make minior improvement to C function semantics and related code (#21565) - builtin: simplify splint_nth methods (#21563) - toml: fix `@[toml: ]`, support `@[skip]` (#21571) - builtin: update `last_index_u8`, deprecate `index_u8_last` string methods, make consistent with `last_index` (#21604) - builtin: implement a JS version of `string.split_any` (#21612) - crypto: add a `crypto.sha3` hash and extended output functions (#21664) - crypto.sha3: remove unnecessary return at the end of the write function (#21669) - builtin: fix string.find_between(), when not found end string return '' (#21670) - builtin: add string.camel_to_snake/0 and string.snake_to_camel/0 methods (#21679) - cgen,x.json2: fix generic map decoding (#21704) - encoding.base32: fix warning of implicit clone of array, by using an explicit unsafe block ( #21728) - vlib: simplify byte character conditions by using methods like is_capital, is_lower, is_letter etc (#21725) - gg: add Context.draw_cubic_bezier_recursive/2 and Context.draw_cubic_bezier_recursive_scalar/9 ( #21749) - ci: fix deprecations_consts.out (the warning for math.max_i8 is now an error; it was deprecated since 2023-12-31) - math: add divide_truncated/2, divide_euclid/2, divide_floored/2 and modulo_truncated/2, modulo_euclid/2, modulo_floored/2 (#21759) - math: avoid unused calculations for math.modulo_floored/2 and math.modulo_euclid/2 - crypto.blowfish: apply `@[direct_array_access]` to very commonly used functions (#21771) - encoding.binary: little_endian_f32_at - arrays: add arrays.chunk_while/2, where `arrays.chunk_while([0,9,2,2,3,2],fn(x int,y int)bool{return x<=y})==[[0,9],[2,2,3],[2]]` - sokol: reduce _SGL_DEFAULT_MAX_VERTICES back to 1<<17 (1<<22 in 811ac12, leads to ~140MB of memory usage for gg/minimal.v, instead of just ~38MB) - vrepl: fix os.input() (#21811) - Improve consistency and behavior regarding explicit mutability (#21566) - builtin: add `pub fn arguments() []string {`; make `os.args` use it, remove edge case in cgen ( #21852) - builtin: support `-d use_bundled_libgc` to make it easier to debug/upgrade reliably libgc cloned from ivmai/bdwgc (#21869) - time: increase http_header_string performance (#21894) - builtin: add s.trim_space_left/0 and s.trim_space_right/0 methods (#21903) - strconv,math.bits: eliminate bounds checking in commonly used routines - arrays: fix arrays.fold, when the `init` value in the call, is an array (#21921) - string: fix leak in replace_once - builtin,dlmalloc: fixes for `v vlib/v/gen/c/coutput_test.v` for gcc14.1, which is stricter - Min window width and height - builtin: str.last_index(); pref: hide-auto-str; - toml: update the alexcrichton and BurntSushi repos to their successors toml-rs, and toml-test, record new exceptions (#21152) - breaking,vlib: update handling of imports whose symbols are not directly used in imported file, remove `pub const is_used = 1` workarounds (#21160) - json: allow `i32` decoding and encoding (#21162) - json2: add ability to decode arrays (#21163) - json2,checker,toml: allow field.typ compile-time checking with MatchExpr and add array of option checking (#21171) - gg: draw_text with custom fonts - x.json2: add a way to decode an array (#21186) - os: clarify some doc comments (#21209) - os: fix double free in os.get_raw_line() (used by os.input), with `-autofree` (#21204) - time: extract Duration related code into duration.v (#21229) - builtin: implement an `at_exit(cb)` wrapper for C.atexit (part 1) (#21254) - os: format readme, fix markdown inside html (#21286) - time: update unix time acces, fix issues related to deviating unix times (#21293) - vlib: refactor empty string checks to use `s == ''` or `s != ''`, instead of `s.len == 0` (#21300) - cli: update `command_test.v` (#21307) - cli: extend control over defaults (#21308) - thirdparty/sokol: bump _SGL_DEFAULT_MAX_VERTICES and _SGL_DEFAULT_MAX_COMMANDS again; mark them with `__v_ start` and `__v_ end` - sync: add Gentoo paths for libatomic - sync.stdatomic: add flag lines for gcc 14 too - gg: make `PenConfig` fields public (#21353) - builtin: fix undefined read s[0], from ''.is_lower() and ''.is_upper() in c7af2c2 - builtin: fix empty string lower / upper assert (#21358) - cli: simplify flag parsing (#21392) - os,runtime: workaround for v.c generation instability - datatypes: fix for set `-` operator, union and intersection, now they no longer change the receiver (fix #21315) (#21362) - sync.stdatomic: add paths for compilation with musl on Gentoo (#21400) - os: fix os.execute stderr redirection (fix #20986) (#21404) - time: fix the string representation of a negative Duration (#21407) - cli: make program outputs using the cli module testable in `cli/testdata` (#21456) - math.unsigned: permit _ separators in Uint128 decimal strings passed to uint128_from_dec_str ( #21461) - cli: fix default flags when their command equivalents are disabled (#21469) - toml: simplify `decode_quoted_escapes` (#21472) - os: fix join-path (#21425) - builtin: simplify MessageError.msg() (#21524) - all: replace usages of C.atexit(cb) with `at_exit(cb) or {}` (part 2) (#21263) - math.unsigned: fix some Uint256 bugs and add tests (#21528) - x.crypto.chacha20: speed up the core functionality of the ChaCha20 stream cipher (#20470) - log: enhance log time format setting (#20484) - encoding.csv: add a new utility fn `new_reader_from_file/2` (#20530) - readline: add completion support (#20559) - builtin: add `is_hex()`, `is_int()`, `is_bin()`, and `is_oct()` methods to the string type ( #20540) - builtin: add empty string verification for the new string .is_oct() etc methods, suggested on PR #20540 (#20564) - json: fix struct with option enum field (fix #20597) #20597 - x.json2: fix panic on calling json2.decode of an optional enum (fix #20593) (#20603) - vlib: add a compress.zstd module (#20616) - io: ensure BufferedReader.read_line() returns `io.Eof`, instead of `error('none')` (#20619) - log: add support for l.set_short_tag/1 (#20652) - Update error checking for new error io.Eof (#20656) - io: allow BufferedReader.read_line() to accept custom line delimiters (#20655) - builtin: implement unbuffer_stdout/0 (#20662) - x.crypto: add sm4 module (#20651) - crypto.aes: optimise performance (#20674) - os: add proper process termination with p.signal_term() (#20671) - os: simplify and unify os.join_path and os.join_path_single, and add more tests (#21494) - bitfield: enhance operation with multiple flags (#20683) - os: fix File.read() in JS backends (fix #20501) (#20633) - os: add error_posix() and error_win32() for explicit platform error handling and default behavior (#20694) - log: implement set_always_flush/1 for log.Log, log.ThreadSafeLog and log.Logger (#20698) - x.vweb: error() and simpler redirect(); comptime: a clearer error - builtin: add a string.u8_array() method (#20736) - os: add os.stat() and helpers (#20739) - os: make os.SystemError struct public so the os.error_* functions can be used by other modules ( #20754) - os: refactor to use os.stat and os.lstat instead of unsafe C calls (#20759) - os: make os_stat_test.v more robust to reporting false positives - x.crypto: add poly1305 message authentication code (mac) in pure v (#20752) - encoding.binary: add _fixed variants for the conversion fns, that accept fixed arrays (#20766) - x.crypto.sm4: make sm4 use the encoding.binary _fixed fns (#20773) - builtin: add gc_collect/0, gc_get_warn_proc/0, gc_set_warn_proc/1. Use them to turn off GC warnings by default. (#20788) - builtin: support `-d gc_warn_on_stderr`, to show the GC warnings, without installing a custom warn fn callback - x.crypto: add AEAD ChaCha20Poly1305 algorithm in pure v (#20817) - x.crypto.chacha20: remove deprecated `math.max_u32` in favour of builtin `max_u32`, remove unneceseary bits, reorder (#20838) - json: fix decode struct ptr (#20828) - time: add a .http_header_string() method on Time (#20861) - json2: reorganize encode string (#20862) - vlib: add `encoding.txtar` (port of Go's txtar module) (#20874) - gg: handle dpi change, when moving window to another monitor (#20886) - time: add a tm_gmtoff field to `C.tm` (a BSD and GNU extension) (#20907) - x.json2: add skippable field attr `@[json: '-']` (improve backwards compatibility with the `json` module) (#20892) - time: rename identifiers and parameter names (#20913) - io: add a `string_reader` submodule (#20893) - toml: return an error from toml.parse_file(), when the passed file path does not exist (#20912) - x.json2: fix encoder commas (#20916) - time: microoptimise the Time formatting methods (use custom number->string conversion, instead of string interpolation) (#20917) - x.json2: improve performance of string encoding for unicode special characters and emojis (#20867) - x.json2: minor performance improvement, update benchmark recommendations (#20954) - os: workaround a `-prod -cc gcc` bug, affecting os.open_file (fix #20923) (related to #20872) ( #20960) - cli: add pluralization to err msg, if required number of args is not met (#20971) - os: remove repetitive words in comments (#20981) - gg: fix empty circle in native; http: post_form_with_cookies; veb: print veb action in html errors - io.reader: make read_all constants public (#20997) - builtin: expose gc_disable(), gc_enable(), gc_is_enabled(), in addition to the existing gc_collect() (#21002) - x.json2: improve error message upon missing comma (#20602) - builtin: fix a few grammar errors in builtin.string comments (#21010) - io.string_reader: fix needs_fill_until check (#21005) - builtin: add missing return type to fn signature for C.GC_get_stack_base - x.json2: predefine buffer capacity for encoding to avoid reallocations (#20920) - rand: add PRNG.fill_buffer_from_set/2 (#21037) - sokol.gfx: update the PixelFormat V enum, to exactly match the C sg_pixel_format from thirdparty/sokol/sokol_gfx.h - json: fix recursive pointer encoding (#19840) - os,picohttpparser,sokol,strconv: prepare for making `-W impure-v` the default (#19846) - os: add fast path to mkdir_all, when the given folder already exists (#19869) - os: ignore empty path segments in `join_path` (#19877) - os: fix bootstrapping for OpenBSD - x.json2: replace deprecated type byte with u8 in the tests (#19909) - vlib: change byte to u8 (#19930) - sync: add a FreeBSD specific version of vlib/sync/sync_default.c.v (#19962) - datatypes: add push_many for doubly and singly linked list + add insert_many for heap (#19975) - datatypes: make `Direction` pub and fix and add tests for `push_many` (#19983) - gg: fn (data voidptr, e &Event) for events, allows methods - vlib: add a `compress.szip` module, deprecate the `szip` one after 2023-12-31 (#20003) - os: create the folder described by `XDG_CACHE_HOME`, *if it is non empty, and it does not exist yet*, when calling `os.cache_dir()` (#20046) - vlib: use the builtin flush functions, instead of the C. ones (#20108) - crypto: add blake2s and blake2b hashes (#20149) - os: fix `mv_by_cp` for directories (#20154) - os: update mv fns, improve performance, add params struct to control overwrite behavior (#20156) - gg: fix overlapping slices in `draw_slice_filled()` (#20182) - json: fix option sumtype handling (#20186) - builtin: add `@[direct_array_access]` to js string trim_right method (#20222) - json2: add encoder support for `time.Time` (#20228) - json2: fix encoding of 💀🐈 etc emojis (fix #20243) (#20247) - json2: make public the generic function `map_from/1` (#20294) - json2: optimise encoding to be faster than cJSON with -prod (#20052) - json2: support sumtype encoding in a more robust way (#20093) - json2: strict module (#17927) - crypto: fix notices/errors for `v -N test vlib/crypto` - crypto: add blake3 hash (#20319) - sokol: fix compiling gg and other graphical examples on OpenBSD (#20333) - csv: Add a sequential reader too (suitable for very large .csv files, it does not read everything at once) (#20140) - builtin: add an `unsafe { a.reset() }` method, for quickly setting all bytes in an array to 0 - math.fractions: use operator overloading and deprecate old functions (#19547) - gg: fix the alignment of the bottom border of draw_rounded_rect_empty on macos and linux - crypto.bcrypt: fix bcrypt failure for valid pass and hash (fix #19558) (#19569) - sokol: update sokol to the latest version - builtin: fix sizeof(C.BOOL) (windows specific) (#19589) - math.big: fix incorrect division with negative numbers (fix #19585) (#19587) - os: add a convenient way to ignore certain system signals (#19632) - os: fix os.ls(folder) on windows, when a protected folder can not be opened (#19647) - os: add a convenient way to ignore certain system signals (#19639) - crypto.sha: fix calculating the same hash values when .sum() is called several times for sha1/256/512 (fix #19696) (#19697) - crypto.md5: fix calculating the same hash values, when .sum() is called several times (#19703) - os: add a new function `execute_opt` (#19723) - os: add os.page_size() (#19770) - os: implement os.fd_is_pending/1, os.Process.pipe_read/1, os.Process.is_pending/1 (#19787) - builtin: copy min/max integer values consts from `math` to builtin so that the entire math module doesn't have to be imported(#19809) - json2: add support for nested structs (#19579) - math: speedup the pure V math.pow implementation for non-fractional powers (#19270) - math: add more C. fn overrides, for the default C backend (speed up examples/path_tracing.v) ( #19271) - time: add `MMM` support for parse_format() (#19284) - os: include sys/sysctl.h on FreeBSD to avoid implicit definition of sysctl function (#19293) - crypto.md5: change the Digest.write return type, from `?int` to `!int` (#19311) - v.help: use os.executable() instead of `@VEXE` as an anchor, so `v help` will work more robustly. - toml: fix custom `to_toml` for complex structs (#19338) - vlib: add net.http.file, allowing for `v -e "import net.http.file; file.serve()"` (#19348) - vlib: remove functions and fields, deprecated before 2023-03-20 - toml: fix toml encoding of complex types (#19408) - arrays: add a partition function, that splits a given array, based on a criteria, passed as a callback fn (#19417) - toml: add decoding for struct fields of type map[string]T (#19447) - arrays: add arrays.each, arrays.each_indexed, and tests for them - encoding.html: implement `unescape()` (#19267) - eventbus: add generic support for event name (#18805) - readline: add support for ctlr+w and ctrl+u shortcuts (#18921) - strconv.atoi: fix string.int() returning numbers for non number characters (fix #18875) (#18925) - builtin: reduce the number of array allocations for consts in all V programs (#18889) - builtin: move array.data to the top of the struct - os.notify: implement the kqueue backend for notify.FdNotifier (#19057) - vlib: add a new module `builtin.wchar`, to ease dealing with C APIs that accept `wchar_t*` ( #18794) - arrays: add more util functions and tests for them - find_first, find_last, join_to_string ( #18784) - vlib: use sync.new_mutex() consistently for initialising all vlib structures containing mutex fields - crypto.pem: add a static method `Block.new`, to replace `new` (#18846) - crypto.pem: add decode_only and general improvements to decoding (#18908) - log: improve the most common use case, it's no longer necessary to create a `Log` instance ( #19242) - crypto.sha512: make the new384/0, new512_256/0, new512_224/0 functions public - json: fix option alias support (#18801) - time: fix `parse_format` with `YY` (#18887) - math.big: allow bitwise ops on negative signum (#18912) - math.big: make is_odd public and add test cases (#18916) - math.big: add checked division methods (#18924) - math.big: add `isqrt_checked` and standardize error format (#18939) - sokol: use GLCORE33 on linux - os,term.termios: add termios.set_state/2, state.disable_echo/0, use them in os.input_password, to fix `v -os wasm32_emscripten examples/2048/` - gg: implement Android specific APK asset loading for the `create_image` function (#19015) - sync: make sync.Direction public (#19047) - time: store time with nanosecond resolution in time.Time, deprecate Time.microsecond, add utility methods and tests (#19062) - time: add a format_rfc3339_nano() method to time.Time - time: add 'i', 'ii' in custom_format() for 12-hours clock(0-12-1-11) (#19083) - gg: expand the `-d show_fps` background, so fps>100 will not overflow it - Math.big: restore gdc_euclid, use it for smaller numbers, fix bench_euclid.v . - Add new generic `arrays.uniq`, `arrays.uniq_only`, `arrays.uniq_only_repeated`, `arrays.uniq_all_repeated`, `arrays.distinct` - builtin: add support for `-d builtin_writeln_should_write_at_once` and `-d builtin_write_buf_to_fd_should_use_c_write` (#19243) - builtin: always show the assert message, if it was defined in the source, in non test programs too (fix #19240) - time: check if a day is a valid day of its month (#19232) - toml: Add generic automatic decoding and encoding of simple structs, when they don't implement custom methods (#17970) #### V interpreter - Add comptime-if support (#24919) - Reset return value after const eval and fix if-expr (#24955) - Add more infix op support; fix early func return (#24965) - Fix if-else; add infix op; fix func calls (#24972) #### Web - net: fix cookie parsing when `;` is used (fix #25544) (#25561) - veb: new fasthttp module with -d new_veb (multithreaded, epoll/kqueue): makes veb multithreaded and fixes frequent hangs - veb: fix gzip middleware decode/encode (fix #20865) (fix #25753) (#25754) - veb: gzip support for StaticHandler (fix #20859) (#25758) - veb: support markdown content negotiation, compliant with https://llmstxt.org/ (#25782) - fasthttp: move kqueue related code to a separate file - veb: add zstd compression support (#25816) - veb: remove println('send_file ct=...') leftover (#25834) - ci: reduce false positives for veb_should_listen_on_both_ipv4_and_ipv6_by_default_test.v by retrying it 3 times (since sometimes binding to the port it listens to fails) - veb: add an early startup panic error message, when the result type of route handler methods *is not* `veb.Result` (fix #25970) (#25973) - net.mbedtls: make errors more verbose, to ease remote diagnosis of issues - net.openssl: make errors more verbose, to ease remote diagnosis of issues - veb: improve the before_request documentation - veb: add method.location too, to the invalid return type error, to ease diagnosing problems while prototyping - wasm: fix const reference another const (fix #25722) (#26010) - fasthttp: fixes and improvements (#25906) - wasm: export pub fns in main module when targeting wasi (#26041) - net.http: use error_with_code in download_file() (fix #26056) (#26057) - net.http,veb: fix detection of the headers/body boundary in parse_request_head_str (fix #26091) ( #26112) - fasthttp: expand http request parser (related to #26091 part1) (#26104) - net.ftp: fix get() command conversation, add test (fix #18858) (#26194) - x.sessions: verify HMAC signatures when extracting sessions IDs from cookies (#26199) - net.http: fix a panic in parse_multipart_form, for small/incomplete form data (fix #26204) - net.http: support keep-alive connections in server (fix #26136) (#26218) - picoev: fix documentation (#24811) - veb: fix `app.text()` -> `ctx.text()` in `README.md` - net.http: fix panic in parse_multipart_form for invalid boundary (fix #24974) (#24976) - net.http: remove debug println statement from post_multipart_form (#25030) - net.http: reduce the false positives on the CI for server_test.v, let test_host_header_sent_to_server return early, when the server can not start - net: improve tracing output for `-d trace_tcp`; move `error_code()` calls right after the corresponding C APIs (errno is a global that should be read immediately to be valid) - veb: fix a spurious error with Chromium, for POST requests, split into 2 parts, 1st with only http headers, without body (fix #25191) (#25195) - net.http: Use a full url when using a proxy, instead of only the path (#25228) - net.http.file: allow for serving requests to static files with cache busting suffixes like `/dist/littlejs.js?1117` - veb: fix generic field access from alias (fix #25215) (#25246) - ci: change url to http://archive.ubuntu.com in .github/workflows/disable_azure_mirror.sh - net: add `read_ptr/2` (from `read/1`) to `UdpConn` for consistency with `TcpConn` (#24000) - net: make `close/0`, `select/2` and `remote/0` methods of `UdpSocket` `pub` (#24004) - Fix $dbg on function that uses veb comptimecall (fix #23999) (#24088) - veb: allow route methods, that are tagged with `@[unsafe]` - veb: support `-d veb_max_read_bytes=16384`, `-d veb_max_write_bytes=16384`, `-d veb_default_port=1234`, `-d veb_max_http_post_size_bytes=8388608` - net.http: support `v -http -d http_folder=vlib/_docs` (allow customizing the folder, port, and index file through CLI arguments to v -http) - thirdparty: upgrade to mbedtls v3.6.3.1, add a .patch file with the local changes (#24602) - veb: fix handling of default CorsOptions.allowed_headers (#24703) - veb: add `ctx.no_content()` + prevent content-type being set if the mime type is empty (#23425) - net.ftp: use unsafe { nil } - net.smtp: make public the Attachment fields (to be used as plain structs in initialisation) ( #23477) - x.vweb: remove the entire module (it's now veb) - ci: fix failure of the docker-ubuntu-musl job (keep vlib/vweb/vweb_app_test.v in the skip_files) - picoev: enable running veb services on Termux - thirdparty: improve `-cstrict -cc clang-18 -prod` compatibility for programs that do `import net.mbedtls` - net.http.file: use urllib decode uri, to handle urls to files that have unicode characters in their name (fix #23683) (#23684) - veb.csrf: do not print anything by default, add an `verbose: true` option, to restore the old behavior if needed (#23725) - net.unix: make unix_socket_test.v trace its actions more thoroughly - veb.request_id: new middleware that implements request ID tracking (#23727) - veb: update the blog tutorial - net.openssl: use proper library search path for local installations of OpenSSL 3, use `SSL_get1_peer_certificate` instead of the deprecated `SSL_get_peer_certificate` . - ci: fix vweb_run_at.run.out and vweb_run_at.skip_unused.run.out, ensure stable ordering of stdout/stderr for `v run file.v`, in case of compiling a program with warnings/notices. - veb: handle sendfile errors, when the connection is canceled, before the file is completely transferred (#23891) - veb: translations via %translation_key - picoev,net.http: use Time.http_header_string method, to improve performance (#22619) - Do `import veb`, only for templates that do use functions defined in `veb` - picoev: support `-d picoev_verbose_errors`, do not use any naked `eprintln` by default, since that is a low level module - picoev: fix the incompatible pointer type cast error in the C.epoll_wait call (#22785) - net.mbedtls: define MBEDTLS_THREADING_PTHREAD, in mbedtls_config.h; call C.mbedtls_ssl_conf_read_timeout explicitly in the wrapper, with a shorter timeout value of 317ms ( determined experimentally) - veb: fix large file transfer timeout (fix #22489) (#22924) - net.http: send Host headers with port (when the port is != 80 or 443) (fix #22941) (#22942) - net.mbedtls: support compiling with `-d mbedtls_client_read_timeout_ms=7000`, `-d mbedtls_server_read_timeout_ms=60000`, and `-d trace_mbedtls_timeouts` - net.urllib: fix parse of url relative address (fix #21061) (#23180) - veb: fix key value and translation file name (#23203) - Check for using comptime $veb.html()/$vweb.html(), without importing veb or vweb (#21957) - net: add net.Dialer and net.Connection interfaces, abstracting the different types of connections, already supported by the V network stack (#21657) - net.mbedtls: support Server Name Indication (SNI) (#22012) - veb: extract constants into consts.v (#22132) - vweb: mark vweb as deprecated in its README, recommending using veb instead (#22131) - veb: fix `vweb_livereload` reference to `veb_livereload` (#22171) - veb: fix a few minor errors in the README.md (#22177) - net.mbedtls: store the client ip (for ipv4), shutdown on handshake failure, in .accept() (#22184) - veb: implicit context - veb: make implicit context work with custom user types - net.websocket: use retrying on EINTR in Client.listen() (#22279) - net: allow ipv6 address with brackets (fix #22313) (#22316) - net.http: change default http.Server listening address to :9009, to avoid conflicts with tools, that start their own http servers on 8080 like bytehound (#21570) - net.urllib: update parse host to allow for better error handling (#21602) - net.html: quick workaround for a cgen problem for `const x = int(0x80000000)` - net.http: implement http.download_file_with_progress/2, saving each chunk, as it is received, without growing the memory usage (#21633) - veb: update import name in docs (#21668) - Add `m3u8` MIME type `application/vnd.apple.mpegurl` for multimedia playlists (#21688) - veb.auth: use constant time comparison in compare_password_with_hash (#21693) - net.http: correct `Response.status()` method comment, to indicate returning of a `Status` enum field, instead of struct (#21735) - net: fix TcpConn.peer_ip/0 to only return the ip address, without the port number (#21831) - Add mime type `text/x-vlang`, for `.v` and `.vsh` file extensions (#21851) - net.conv: add conv.reverse_bytes_u64/u32/u16 (#21917) - Update `mbedtls` to latest compatible version v3.3.0 (#21118) - veb.auth: a minor find_token fix - Improve descriptions (#21155) - ci: change listen ports in vweb_should_listen_on_both_ipv4_and_ipv6_by_default_test.v for both vweb and x.vweb, to reduce probability of network errors - ci: mark both vweb and x.vweb versions of vweb_should_listen_on_both_ipv4_and_ipv6_by_default_test.v as flaky - breaking,net.ftp: allow to choose a different port than port 21 (change FTP.connect to accept `host:port`, not just a `host` address) (#21185) - x.vweb: accept query params as method arguments (#21201) - net.http.file: support index_file (`index.html` by default), and auto_index (true by default) parameters to file.serve() - veb: copy x.vweb to veb, and make it work with comptime - ci: fix the ubuntu-docker-musl job by skipping veb_app_test.v - pref: support a shortcut: `v -http` for `v -e "import net.http.file; file.serve()"` . - net: add a .port()! method for net.Addr (#21412) - net: improve error message in .port() - picoev: handle `EAGAIN` or `EWOULDBLOCK` quietly (#21480) - net.unix: remove debug/trace eprintln (#21517) - net: fix vlib/net/tcp_test.v (since .listen_tcp with af .unix, is now expected to return an error) (#20472) - net: remove unused import in tcp_test.v - x.vweb: add error, when static directory does not exist (#20455) - net.urllib: fix parsing url error, when querypath is '//' (fix #20476) (#20504) - vweb: unify listen address from tcp and print (#20448) - net.unix: make the error messages in unix_test.v more specific (#20537) - vweb: add an optional Context.before_accept_loop/0 method, to make testing easier and more robust (#20538) - vweb: fix routes without results in vweb_app_test.v (#20548) - vweb: make vweb_test.v more robust and faster, by embedding its server as a module - Small fixes and backport changes from vweb (#20584) - net.smtp: implement mail attachment support (fix #19920) (#20640) - vweb: fix quickstart docs in the module's README.md on how to create a new vweb project (#20644) - net.http: add a temporary fix for the intermittent segfault with http.get_ text/1 and `-prod -cc gcc` 13.2.0 (fix #20506) (#20660) - x.vweb: support HTTP 1.1 persistent connections (#20658) - x.vweb: use `$if debug_ev_callback ? {` for the `[vweb] error: write event on connection should be closed` message - x.vweb: add cors middleware (#20713) - x.vweb: add new sessions module (#20642) - net: fix non-blocking read/write (#20438) - net: reduce flakiness of tcp test (#20761) - picoev: renaming, doc (#20567) - x.vweb: add full static host support, for urls ending with /folder/ , where the folder backing it, has `index.html` inside (#20784) - x.sessions: change session Store interface to use results instead of options (#20796) - net: fix function name in split_address doc comment (#20794) - doc: x.vweb static website capabilities (#20808) - thirdparty: update picohttpparser (#20843) - picohttpparser: restore formatting for g_digits_lut, after f09826e (#20844) - x.vweb: fix handling of static URL paths like `/sub.folder/a_folder` (#20863) - veb: a new module veb.auth for authentication logic (tokens, hashed passwords) - veb.auth: make work with any db - net: workaround a `-prod -cc gcc` bug (#20872) - picoev: add more logging of errors (#20558) - picoev: remove fmt off tags (#20569) - net.mbedtls: use `char` and `usize` types for describing more precisely the C API of mbedtls ( #19837) - vweb: add the mime type for .toml files (#19875) - net.openssl: use actual C values for the SSLError enum (#19945) - vweb: .html('custom_template.html') - vweb: add an optional parameter to the .redirect/2 method, to be able to set the http code for the redirects (#20082) - x.vweb: fix large payload (#20155) - x.vweb: reimplement csrf module (#20160) - net: make net.fionbio and net.msg_nosignal constants public in net_windows.c.v (#20183) - net.http: remove unused `read_set_cookies` function (#20187) - os, net.http.file: add a folder listing to the http static file server, started by file.serve/1 ( #20192) - websocket: enable using an already existing connection (from vweb or another http server) (#20103) - x.vweb: fix fsanitize-address test for SSE, improve documentation on the usage of `takeover_conn` (#20249) - net.http: support `-d no_vschannel` on windows, to fix long waits, while connecting on some systems (#20265) - x.vweb: fix `$vweb.html()` integration in cgen for the newer `x.vweb` module (fix #20204) - net: support only ip and ip6 in net.tcp_listener (#20336) - x.vweb.assets: reimplement assets module for x.vweb (#20280) - x.vweb.sse: reimplement SSE module for x.vweb (#20203) - js.dom: add querySelector[All] and NodeList (#20240) - vweb: add mime type support for static .md files - net.conv: add varinttou64 and u64tovarint functions, for the variable unsigned integer encoding, described in rfc9000 (for QUIC) (#19568) - net.http: support passing on_running, on_stopped, on_closed callback functions to http.Server{}, as well as show_startup_message: false. (#19591) - net: fix handling of spurious wake-up signals, lost when calling select() in mbedtls and openssl ( continue on C.EINTR) (#19600) - net: use conv.hton* consistently, instead of `$if tinyc { conv.hton16(port) } $else { u16(C.htons(port)) }` - net.http: support passing an HTTP proxy server in http.fetch (#19606) - net.http: add a retry mechanism to http.fetch(), when the socket inevitably errors (#19660) - wasm: implement inline assembly (#19686) - net.http: increase max_redirects to 16 (#19743) - picoev: implement raw mode (#19771) - flag,json,net: handle C calls in .v files (part of enabling `-W impure-v` as default) (#19779) - net.http: add socks5|http(s) proxy support [Linux] (#19676) - net.http: fix http.fetch(), without explicit method (default again to .get, not to .acl) - net.http: default explicitly to Method.get for http.Request and http.FetchConfig too - examples: add examples/fetch_ip.v, showing how to contact http://ifconfig.co/json and parse the result - net.http: fix post error with https on windows (#19334) - net.ssl: implement SSLConn.peer_addr() (#19333) - http: Request.host - net.ftp: fix dir() for file names, which contain spaces (fix #18800) (#18804) - net.http: make listener public, and add addr in Server struct (#18871) - net.http.chunked: return `!string` on decode (#18928) - net.conv: rename functions to match other langs, making them easier t… (#18937) - wasm: remove dependency on thirdparty/binaryen, webassembly backend rewrite (#18120) - wasm: add a -wasm-stack-top flag to compiler (#19157) - net.mbedtls: add SSLListener to allow creating SSL servers (#19022) - picoev, picohttparser: reimplement in V (#18506) - vweb: fix parsing of form fields, send with multipart/form-data (by JS fetch) - vweb: make vweb route paths case sensitive (#18973) - net.mbedtls: have shutdown close accepted connections too (#19164) - http: add support for stream connections, and custom .on_redirect, .on_progress, .on_finish callbacks to http.fetch() (#19184) - vweb: add a user_agent utility method to the vweb context (#19204) - vweb: avoid the controllers having to be defined in specific order (#19182) #### ORM - Mark orm_where_in_test.v to be skipped in the sanitize-memory-clang job - Fix fkey insert as assigment expr (fix #25568) (#25575) - Fix double fkey insert and update (fix #25593) (#25606) - Add index attr support (#25604) - Fix autofree detection for is_or with block style (fix #25969) (#26089) - Allow multiple set() in one update() call (fix #26116) (#26117) - Add check for invalid index field name (#26142) - Supoprt DISTINCT keyword (#26163) - Support lowercase operators `like`, `in`, `not in` etc (fix #25032) (#25035) - Fix sub_structs (fix #25104) (#25105) - orm: fix default value quote (fix #24052) (#24057) - orm: fix type alias not supported in table columns (fix #15478) (#24062) - orm: fix gen sql complex where (fix #24136) (#24138) - orm: skip orm_complex_where_test.v for `sanitize-memory-clang` too - orm: add function call based builder API for dynamic queries (fix #24178) (#24196) - orm: set default value for require field if database value is null (fix #24221) (#24222) - orm: fix option field with default null value (fix #24222) (#24228) - orm: add or_where() method to the builder (fix #24244) (#24250) - orm: add IN and NOT IN (#24634) - orm: add `in` and `not in` to orm_func (fix #24639) (#24642) - breaking,orm: add table attrs; add table/field comment support for mysql and pg (#24744) - orm: fix codegen for option fk (fix #23383) (#23400) - Fix orm.Connection only allowing immutable Connections (#22684) - Fix order by with custom column name (#22813) - Support plain `@[serial]` attribute for marking struct fields (#22814) - Fix crash when working with array field (fix #22822) (#22824) - Fix list generation and escape loose backtick (#23039) - Fix mark as used var on insert statement (fix #23032) (#23038) - Fix update stmt with enum value (fix #23031) (#23037) - orm: fix subquery without where expr (#21598) - orm: ilike for case insensitive text search - orm: update readme with more specifics (#21697) - Add error for unchecked option multi return types, fix undefined behavior (#21106) - orm: fix checking invalid recursive structs (fix #20285) (#20491) - orm: fix checking invalid recursive structs in sql stmts (fix #20278) (#20505) - orm: fix orm insert issue if table missing [Issue : #20017] (#20580) - orm: fix orm_option_time_test.v after 2d0ed2c made insert in parent tables with child ones missing fail - orm: insert expressions returning id - orm: fix code generation for an option time.Time field (#20031) - orm: fix the generated SQL for the "not equal" operator (#20321) - orm: add null handling and option fields (#19379) - orm: make is_null/is_not_null unary ops; don't bind null in where (#19635) - orm: add `references` attribute to allow foreign key declarations on fields (#19349) - orm: support different foreign key types, not just an integer id (#19337) - orm: add support for V enum struct fields (#19374) - orm: quote table and field name in `[references]` (#19387) - orm: fix inserting sequential values (id=0), in tables with an i64 primary field (#18791) - Add OR in where on update and delete (#19172) #### Database drivers - db.sqlite: fix orm f32 field retrieval for sqlite (fix #25583) (#25592) - db.pg: support returning `Result` type with column names (#25737) - db.sqlite: allow for `mut db := sqlite.connect_full(":memory:", [.readwrite, .create, .fullmutex], "")!` defaulting to unix/win32 depending on the platform - db.pg: support LISTEN/NOTIFY (implement feature #23983) (#26133) - db.pg: fix `v check-md vlib/db/pg/README.md` - Revert "db.sqlite: support calling exec_param_many with [][]string or []string (it now accepts a sumtype of both) (#26100)" - Reapply "db.sqlite: support calling exec_param_many with [][]string or []string (it now accepts a sumtype of both) (#26100)" - db: modify mysql/pg/sqlite interface for pool working (#24780) - db.sqlite: fix get_text trimming data after (including) first 0 character (#25040) - db.mysql: use mysql datatype for alloc string_binds_map, not orm's (#24126) - db.mysql: fix handling of nullable timestamp (fix #24120) (#24125) - db.mysql: add null result support (fix #24130) (#24131) - db.mysql: use hardcoded const declare (fix #22086) (#24162) - db: connection pool (#24161) - db: mysql,pg,sqlite add transaction support (fix #24290) (#24352) - db.pg: fix incompatible fn signature (#24549) - db: add redis (#24730) - db.sqlite: add tracing for more calls, when using `-d trace_sqlite`, not just for the ORM - db.pg: add support for prepared statement, with db.prepare/3 and db.exec_prepared/2 (#23442) - db.mysql: add SSL support; turn ConnectionFlag into `@[flag]` (#23975) - db.sqlite: add instructions for installing SQLite's amalgamation or development package, if it is missing - db.mysql: fix invalid memory access in exec_one for returned rows with NULL fields (#21317) - db.sqlite: fix exec_param_many bug (#21008) - db.mysql: add support for the FreeBSD name of the mariadb client library (#20039) - db.pg: fix using postgresql on windows, improve instructions for installing it (#20053) - db.mysql: add ability to prepare and execute statements separately (#20146) - db.pg: fix compilation error with the msvc compiler on windows, and add readme (#20326) - pg: handle C calls, move to .c.v files (#19739) - db.pg: allow postgres connection using service definitions (#19288) - vlib: remove deprecated `pg`, `mysql`, `sqlite`, `mssql` modules. Leave only the `db.` prefixed `db.pg`, `db.mysql` etc - db.mysql: add the exec family of methods (#19132) - db.sqlite: add exec_param_many and exec_param methods (#19071) - db.sqlite: make functions return results, breaking change (#19093) #### Native backend - Fixed array, `-new-transformer` dynamic array (#25817) - Add `$if trace_native_todos ? {` to reduce noise in `v test-all` - Add comptime cpu archs support (#24956) - Add support for (elf) globals (#25016) - Improve consts, support more assigns (#25277) - Structs multi_assign and multi_return (#25281) - Support more assign ops, reduce code duplication (#25283) - Begin array support, `a := []Type{len: x, cap: y}` and `a[i]` read/write (#25299) - native: use builtin exit function (#24578) - native: improve string support (#24600) - native: implement `for in string` for amd64 (#24613) - native: support nested structs, improve support for right expr of IndexExpr (#24627) - native: leave only the unique paths in g.linker_include_paths, before doing lookups - native: support C constants (#24660) - native: add a temporary special case for `C.EOF` (#24724) - native: fix convert_int_to_string, add comments in the verbose (-v) mode (#23743) - native: fix int prints (#23747) - native: for statement : add support for all expressions handled by g.condition (#23752) - native: fix inc and improve support for i32 (#23753) - native: support negative integer literals (#23755) - native: fix missing symbols CaptureStackBackTrace and __debugbreak (#23765) - native: fibonacci test - native: add support for enums of different types (#23786) - native: fix unsigned and signed int comparison (#23808) - native: support `-no-builtin` (generate executables < 1KB Linux with `v -no-builtin -b native examples/hello_world.v`) - native: use i32 instead of int - native: make native tests pass on windows; refactor PE file generation (#19140) - native: parse dll files to resolve extern symbols (#19433) - native: move functions out of amd64.v (#18857) #### C backend - Fix resolution type Map[string]T when T is AliasToMap (fix #25494) (#25510) - Fix markused for option generic param (fix #25501) (#25525) - Fix empty struct initializer for clang (fix #25467) (#25526) - Fix match codegen for option match case (fix #25533) (#25537) - Fix codegen for alias for array fixed initialization (fix #25512) (#25540) - Ensure option none/ok state is also compared (#25532) - Fix match codegen for option expr on case (fix #25545) (#25553) - Add `-no-closures` option to detect closure usage earlier (for emscripten or for less well supported platforms) (#25565) - Create ctemp before lockexpr gen (fix #25576) (#25612) - Fix if expr with condition that requires temporary variable (fix #19584) (fix #23903) (#25621) - Fix multi return of a fixed array (fix #25626) (#25628) - Fix generic multiple indirections on print (fix #22793) (#25633) - Fix `fn (d Struct) a[T]() T { return d }` when T is a sumtype (#25644) - Minimize code generated for asserts (generate the common parts for the pass/fail case once) ( #25642) - Handle pointers in json map decode/encode (fix #25632) (#25646) - Fix `defer` stmts with `if` exprs and `or` blocks that return a value (#25651) - Fix infix expr ComptimeSelector type (fix #25659) (#25662) - Fix passing sumtype child to generic function taking sumtype parent (fix #25660) (#25664) - Fix multi generics fn name (fix #23886) (#25673) - Fix `defer` generation within comptime `$if`/`$match`/`$for` (#25677) - Fix codegen for if comptime and array fixed (fix #25691) (#25697) - Correct function definitions for callbacks in imported modules (fix #25700) (#25719) - Improve codegen for array fixed init for g++ compiler (fix #25723) (#25725) - Fix codegen for operator overload method_name on alias to builtin types (fix #25709) (#25726) - Fix missing cast if fixed array is surrounded in brackets (fix #25629) (#25741) - Fix comptime for types not being recognized with maps correctly (fix #25742) (#25743) - Fix dump(ptr_to_fixed_array_value) - it now returns the argument directly (thanks @tankf33der) ( #25764) - Cast member variables to correct types in comptime $for (fix #25771) (#25773) - Include `ast.ComptimeSelector` in fixed array checks (fix #25767) (#25777) - Checker,cgen,type_resolver: prevent stale type cast on comptime `$for`, handle in dumpexpr (fix #25781) (#25784) - Reduce the nested expr level complexity of Gen.ident - Fix tcc __attribute__, fix os.notify (followup to #25779) (#25804) - Ensure array of string is not cloned with depth 0 (fix #25783) (#25793) - Support `-d trace_check` and `-d trace_cgen` to help diagnose checker and cgen ordering issues - Support `-d trace_cgen_fn_decl` and `-d trace_cgen_gen_fn_decl` too - Show the v_gettid() hex with `-d trace_cgen_fn_decl` and `-d trace_cgen_gen_fn_decl` - Use variadic_count == 1 when passing variadic to call of same array type (fix #25827) (#25837) - Fix nested or in assign decl (fix #25864) (#25865) - Fix variadic on translated (fix #25862) (#25876) - Allow @[cinit] for const variables (#25881) - Fallback to field type when default_expr_typ is 0 (fix #25891) (#25903) - Fix map value init with array fixed const (fix #25887) (#25902) - Fix cast type changed before last stmt in `stmts_with_tmp_var` (#25915) - Update wyhash to version 4.2 (#25907) - Use final_sym for elem_sym in index_of_array (fix #25960) (#25961) - Fix variadic call on sumtype with array of itself (fix #25898) (#25964) - Correct T{} init for []Type aliases (fix #25962) (#25963) - Fix array init with fixed array from return call (fix #25954) (#25971) - Fix fntype unwrap on ifguard (fix #25911) (#25914) - Add a source .location field to `$for method in Type.methods {` (#25976) - Fix iterator on alias to fn ptr (fix #25911) (#25978) - Fix shared int string intp (fix #25984) (#25989) - Allow init shared field with default value (fix #25990) (#25991) - Allow init of struct from struct with array of optional values (fix #26000) (#26005) - Fix default value in if/else or block (fix #26002) (#26020) - Fix fnptr indirections declaration (fix #25940) (#25987) - Fix bool cast from value (fix #26028) (#26031) - Fix cast() generic type bug (fix #26065) (#26066) - Fix fn_var_signature() support nr_muls (fix #26049) (#26075) - Fix cast_expr() for alias (fix #26076) (#26079) - Handle CallExpr in dumpexpr (fix #26084) (#26087) - Clean code in return stmt (fix #25968) (#26118) - Fix cast to array (fix #26099) (#26102) - Fix fn_var_signature() allow option type (fix #26088) (#26120) - Fix scoped struct array fixed generation (fix #26111) (#26114) - Fix option array init with non option values (fix #26148) (#26170) - Fix heap fixed array assign (fix #26149) (#26169) - Fix stack overflow for `@[heap]` structs with large fixed arrays (fix #22690) (#26183) - Fix print interface when arg0 is function call (fix #26184) (#26188) - Checker,table,cgen: fix generic interface confusion (fix #25478) (#26181) - Only run freestanding_module_import on amd64 (#24763) - Fix sumtype option unwrapping (fix #24746) (#24770) - Protect against unlimited recursion in type_default_impl, by converting to a verror/1 call instead - Fix `static` and `volatile` var deref (fix #24778) (fix #24779) (#24807) - Fix codegen for interface method closure get (fix #24810) (#24818) - Fix codegen for multi return assignment with option type (fix #24812) (#24817) - Fix if codegen when func parameter is option type (fix #24813) (#24816) - Skip `struct none {` in cgen, if `none` is not used by V code reachable from `fn main() {` ( #24824) - Skip `struct map {` and related type declarations, when no V maps are used (#24826) - Fix anon struct encode (fix #24836) (#24852) - Fix json decode option alias (fix #24843) (#24853) - Fix const indexexpr dep (fix #24850) (#24851) - Fix codegen for generic interface with multi return generic type (fix #24838) (#24858) - Fix anon struct init passing (fix #24879) (#24884) - Allow alias to map `type Dict = map[string]string` (fix #24878) (#24883) - Builtin,cgen,markused: add struct @[aligned] support for structs allocated on the heap too ( #24886) - Add a `__closure_init` call for sokol/gg programs on android as well (#24892) - Allow alias types to be iterated if parent type has `next` method (fix #24890) (#24894) - Use alias `next` method if defined in `for x in iterator {` (#24905) - Fix const fixed array with type alias (fix #24936) (#24946) - Fix callback codegen on generic struct resolution (fix #24947) (#24948) - Move sort fn after interface definitions(fix #24465) (#24967) - Fix struct field init within fn without result type (fix #24970) (#24973) - Move closure C code to V code under vlib/builtin/closure/ (#24912) - Parser,ast,checker,cgen: use enum comparisons instead of string ones on ast.ComptimeCall.method_name (#25003) - Fix generic key's type with `in` operation (fix #24983) (#25011) - Remove unused enum declarations too (#25033) - Parser,checker,cgen: remove unused `err` declaration or `or { }` blocks (#25034) - Add a test for builtin_init being present (part 2 of 4a6941a) - Fix closures on s390x, ppc64le, loongarch64 platforms, add test to s390x CI (#25047) - Fix anon fn checking adding unresolved generic type on codegen (fix #25050) (#25055) - Fix building on Termux after fa904c4 - Use `#if defined __BIONIC_AVAILABILITY_GUARD && ...` to be compatible with more Termux versions - Fix asm stmt separators (#25067) - Fix translated file fixed-array assignment (#25080) - Fix codegen for passing int from selector to voidptr expect arg (fix #25081) (#25083) - Fix codegen for option void fn return block unwrap (fix #25074) (#25082) - Fix alias to sumtype cast initialization (fix #25086) (#25091) - Allow alias sumtype smartcasting (fix #25085) (#25096) - Fix codegen for generic struct field array option (fix #25093) (#25097) - Fix mutable sumtype (fix #25108) (#25111) - Fix generic return assign to ComptimeSelector (fix #25125) (#25131) - Fix address of call with `cast(&(arr.last() as Type))` (fix #23528) (#25132) - Fix eq for anon C structs (#25152) - Fix generated str method for enums that have C values (use ifs, instead of switch) (fix #25135) ( #25157) - Fix autofree with option array (fix #25124) (#25149) - Fix assigning fn address (fix #24537) (#25158) - Fix veb alias type identification and generic CastExpr (fix #24895) (#25155) - Revert "checker,cgen: evaluate comptime `$if` results in checker *only* (fix #25123) (fix #25156) (#25150)" - Evaluate comptime if results in checker only (with fixed -cross compilation) (#25162) - Fix generic_fn_name generating incorrect names for C structs (#25164) - Add comptime match support (#25165) - Fix resolving generic interface field from generic struct (fix #23556) (#25182) - Fix autofree used vars on return (fix #25196) (#25198) - Fix hash stmt code generation (fix #25184) (#25207) - Expose is_embed in FieldData (#25232) - Fix alias enum used in comptime `$for` (fix #25211) (#25212) - Ensure variable names do not conflict with builtin methods (fix #25063) (#25178)" - Add `@[reused]` attribute to mark methods, reusing the receiver memory on return (needed for autofree) (fix #25221) (#25235) - Fix gen_struct_equality_fn null pointer crash (fix #25237) (#25231) - Allow generic alias enum comptime (fix #25249) (#25251) - Fix big IntegerLiteral LL postfix (fix #25269) (#25275) - Prefix `builtin` APIs with `builtin__` (#25264) - Fix fixed-array const initializer (fix #25291) (#25293) - Fix generic cast to sumtype of empty struct (fix #25263) (#25290) - Fix option variadic arg passing (fix #25261) (#25273) - Support for 64bit int 1 (#25236) - Cgen,parser,markused: add export const support (fix #25300) (#25303) - Fix i64 enum as a map key, when the enum values are too small (fix #25294) (#25310) - Fix parallel cached_type_to_str access (fix #23980) (#23998) - Fix codegen to make mutable sumtype working (fix #23982, part 1, needed for bootstrapping) ( #23988) - Fix arm64 asm operand position; fix arm64 asm imm; support arm64 dot instruction (#24017) - Fix mutable ptr sumtype (#24021) - Fix asm comments of arm32 (#24025) - Allow asserts inside fns, called in const/global initialization, in test files (fix #24029) ( #24031) - Fix codegen for option return unwrapping on last statement (fix #24026) (#24030) - Fix match option with case non option (fix #24047) (fix #24048) (#24051) - Support measuring programs, that use multiple threads in the new profiler column (turn `prof_measured_time` into a thread local, for the supported C compilers) (#24061) - Fix `@[keep_args_alive]` with ptr (fix #23973) (#24058) - Remove unused macro V64_PRINTFORMAT - Fix option array push on unwrapped array (fix #24073) (#24079) - Fix nested array support for the orm (fix #19327) (#24080) - Fix `x in [...]!` operator with fixed arrays (fix #24082) (#24083) - Fix codegen for comptime multiline attr (fix #23964) (#24087) - Fix codegen for selector with embed field option (fix #24084) (#24085) - Fix generic result return (fix #24097) (#24100) - Fix showing the expression, as literal value, in case of `assert s[x..y] == "literal"` (fix #24103) (#24105) - Fix codegen for option unwrapped var passed to generic option type (fix #23972) (#24096) - Fix selector option unwrapping on infix (fix #24108) (#24115) - Sort the paths, used in coutput_test.v - Skip emitting mman.h and pthreads related code, for freestanding builds (#24118) - Add s390x assembly support + test (#24129) - Parser,checker,cgen: fix wrong auto heap deref of auto `index` loop var (fix #24117) (#24124) - Fix non-voidptr to voidptr on `-cstrict` + notice about such usage (fix #24139) (#24143) - Fix multi return with option type (#24144) - Remove obfuscation (`strip` should be used instead); temporary fix for usecache + toml - Fix zero left padding (fix #24199) (#24201) - Fix variadic sumtype args passing (fix #24150) (#24207) - Fix codegen for const to c string (fix #24235) (#24248) - Fix codegen for fixed array init with init using structinit (#24269) - Fix missing braces for const init with castexpr from option unwrapping expr (#24276) - Fix codegen for index expr on for loop with branchstmt (fix #22760) (#24289) - Fix codegen for assigning fixed array on defer var (fix #24300) (#24305) - Fix codegen for multi return with aliased fixed array (fix #24280) (#24295) - Fix codegen for nested selector unwrapping on lhs (fix #24292) (#24293) - Add ppc64le assembly support + test (#24299) - Fix s390x closure thunk (use floating point register) (#24258) - Fix riscv64 closure thunk (use floating point register) (#24315) - Fix codegen for writing on unwrapped selector (fix #24316) (#24323) - Fix codegen for thread.call() on var auto heap (fix #24326) (#24327) - Fix codegen for handling multiple return result type on call (fix #24341) (#24344) - Fix codegen for nested selector option ptr (fix #24339) (#24345) - Fix arm64 closure + remove stub in test (#24332) - Workaround tcc aarch64 bug (fix #24331) (#24354) - Fix riscv32 closure (#24355) - Fix codegen for anon option fn struct field init (fix #24392) (#24400) - Fix `if mut var != none {` for optional interface values (fix #24351) (#24410) - Fix interface `unsafe {nil}` comparison and initialization (fix #24374) (#24411) - Ast,cgen,parser,pref: support loongarch64 inline assembly, add test (#24440) - Fix array init with interface element type (fix #24442) (#24454) - Fix const declaration dependant mapping when using update_expr (fix #24437) (#24455) - Fix comptimecall with map receiver (fix #24448) (#24449) - Fix assign from `for mut var in arr {` to pointer (fix #24432) (#24456) - Workaround tcc aarch64 fn call bug (fix #24473) (#24477) - Workaround tcc aarch64 spawn call bug (fix #24482) (#24483) - Fix map of fixed array value in if guard (fix #24488) (#24496) - Fix codegen for assigning `nil` or `0` to option ptr field (fix #24447) (fix #24500) (#24502) - Fix codegen for array of option element auto eq `a == [?int(none)]` (#24504) - Fix codegen inconsistency handling `nil` param to arg expecting ptr (fix #24491) (#24503) - Fix pattern generated by `const_init_or_block.vv` in `vlib/v/gen/c/coutput_test.v`, when VFLAGS=-no-parallel is used - Fix tmp var redeclaration on const inited later (fix #24521) (fix #24517) (#24524) - Fix generic name handling for struct generic (fix #24530) (#24565) - Fix initialize error object in or_block (fix #24529) (#24576) - Improve the readability of `switch() {` statements, generated by `match() {` ones (#24618) - Reduce v.c size by ~4% by removing comments and using shorter literals - Fix enumval str() call on stringinterliteral (fix #24702) (#24705) - Fix type_default for option type, when the default expr is `none` (fix #23318) (#23320) - Remove double string cloning (#23331) - Fix type_default for array init >= 8 items (spotted while building the vhamll project) (#23334) - Fix codegen for alias struct embed (fix #23347) (#23353) - Fix codegen for sumtype casting on selector on as cast with non pointer field (fix #23387) ( #23391) - Fix generic alias option assigning (fix #23382) (#23393) - Fix codegen for selector on shared var with embed (fix #23378) (#23394) - Fix codegen for nested selectorexpr on unwrapped option (fix #23406) (#23409) - Cache return_stmt()'s node.exprs[0] and node.types[0] (#23408) - Fix codegen for indexing generic map (fix #23376) (#23402) - Support `-d trace_unused_by_main` and `-d trace_skip_unused_just_unused_fns`, to find out potentially obsolete functions that are not used at all in a project - Fix shared array indexing (fix #23410) (#23413) - Fix shared array fixed initializing with `-cstrict` (fix build of chip8-v project) (#23414) - Fix codegen for array fixed comparison on MatchExpr (fix #23403) (#23415) - Fix struct init for anon struct field on C structs (fix #23421) (#23422) - Fix shared array slice (fix #23426) (#23427) - Fix array of sumtype initialization with var string (fix #23429) (#23432) - Fix codegen for ifguard indexing array of option (fix #23438) (#23439) - Fix assigning option of array index (fix #23451) (#23455) - Fix compilation for a project using a lot of json, threads, embeds + parallel-cc (#23467) - Fix cgen error for `instance.t.wait()` on default 0 initialized thread field `t` (fix #23390) #23392 - Fix array decomposing on variadic call (found while working on solving #23474) (#23476) - Fix option var nested unwrapping from sumtype (fix #23478) (#23485) - Fix option unwrapping on heap var (#23489) - Fix codegen for indexing anon_fn (fix #23493) (#23495) - Fix nested option selector unwrapping (fix #23500) (#23497) - Fix interface casting in anon fn (fix #23530) (#23533) - Fix codegen for spawn with interface on submodule (fix #23471) (#23517) - Parser,ast,cgen: support nested unions with `field union {`, to improve interoperability with C ( similar to `field struct {`) (#23539) - Fix unwrapping option interface field (fix #23540) (#23541) - Fix codegen for assign from unsafe fn returning fixed array (fix #23546) (#23548) - Fix codegen for a fixed array init with different node types (fix #23545) (#23547) - Fix return on last statement of return IfExpr (fix #23550) (#23551) - Fix auto str which expects ptr for ptr type (fix #23552) (#23553) - Fix codegen for assigning from infixexpr with generic operand (fix #23560) (#23561) - Fix codegen for array's .grow_cap and .grow_len methods for generic arrays (fix #23566) (#23568) - Fix codegen for const fixed array initialization with another const as item (fix #23565) (#23572) - Fix codegen for unwrapping option comptime var (fix #23590) (#23591) - Fix hash functions for `map[Enum]Value`, and `enum Enum as u64 {` (fix #23630) (#23632) - Fix unwrap option ptr selector (fix #23631) (#23638) - Fix codegen for `for` or-block (fix #23625) (#23644) - Fix codegen for option value on `map_set` (fix #23650) (#23652) - Fix codegen for option sumtype with option variant (fix #23653) (#23656) - Remove commented code blocks using `if true {` - Reduce interpolations when a method is not found in Table.find_method/2; merge rand.constants back to rand.v (#23660) - Fix `$if typeof[T]().idx`, `$if typeof[T]().unaliased_typ` checking (#23665) - Fix codegen for sumtype cast from option variants on map_set (fix #23654) (#23669) - Fix codegen for a const assigned a fixed array, initialized with unsafe exprs (fix #23674) ( #23676) - Fix `@[sql: serial]` and `@[serial]` are not the same (fix #23346) (#23678) - Improve support for `v -path bootstrap_alternative_backend/ run simple.v` (#23679) - Fix codegen for array fixed on if and match expr (fix #23577, fix #23589) (#23682) - Add support for a `#postinclude` directive - Fix #preinclude, add test case for #postinclude too - Fix codegen for returning an initialised fixed array (fix #23693) (#23700) - Use `global_g.out << g.out` instead of `global_g.out.write(g.out) or { panic(err) }` - Fix issues found with the stricter sanitizers in clang-18 on Ubuntu 24.04 (#23710) - Fix codegen for nested if on return (fix #23723) (#23729) - Fix sumtype smartcasted var as inherited var (fix #23716) (#23731) - Fix map with an Enum as key type, with size < 4 bytes on tcc (fix #23714) (#23738) - Fix codegen for match with sumtype ptrptr (fix #23776) (#23785) - Fix aggregate var handling on match branch (fix #23768) (#23787) - Fix gowrapper codegen for receiver ptrptr (fix #23798) (#23800) - Fix regression, preventing the use of `-gc none -d no_main -no-builtin -no-preludes` to compile C style V programs - Fix array fixed assignment for `@[keep_args_alive]` (partial fix for #23804) (#23805) - Fix nested option fixed array (fix #23708) (#23845) - Fix codegen for match on return (fix #23661) (#23851) - Fix casting primitive type to alias, where option alias is expected (fix #23859) (#23860) - Fix interface method list ordering to make test buildable with `g++` (fix #23701) (#23870) - Make `./v -prod -cstrict -cc gcc-11 test vlib/math/` pass cleanly (workaround a problem in V's cgen, that -cstrict discovered) - Fix codegen for global array passed as mut (fix #23873) (#23881) - Fix msvc build filename, remove temp files (#23890) - Improve the stability of generated code for auto string methods - Fix codegen for array of anon struct (fix #23896) (#23907) - Make sure to call the overridden `pub fn (mut a []string) free() {` method, NOT the generic `fn (a &array) free() {` one. (#23911) - Fix generic container init (fix #23910) (#23912) - Fix codegen for generic structinit and generic array return (fix #23916) (#23943) - Implement alias operator overloading for generic struct parent type (fix #23965) (#23967) - Add `T.key_type`, `typeof(expr).key_type`, `T.value_type`, `typeof(expr).value_type`, `T.element_type`, `typeof(expr).element_type` for getting `Map[K]V` and `[]T` types (fix #23914) ( #23962) - Builtin,markused,pref,cgen: improve markused for small programs - Fix codegen for fixed array contains - `[1,2]! in a` (fix #22559) (#22579) - Improve fixed array literal in operation and index calls (#22590) - Add codegen for auto free methods for interface type (#22555) - Add test for #22586 (#22600) - Parser,ast,cgen: do is_builtin sym marking during parse time just *once*, to save multiple checks later (#22580) - Cache the results of g.base_type/1 (#22613) - Add caching to contains_ptr return (#22605) - Add .write2/2 and .writeln2/2 methods to reduce consecutive write calls (#22610) - Optimise the generated code for returning literal values and option/result values (#22622) - Optimize literal string comparison (string__eq -> vmemcmp) (#22614) - Fix selector indexexpr with fntype on assignment (fix #22635) (#22637) - Fix anon fn with `&` prefix (fix #22628) (#22638) - Fix struct field init with fixed array using index (fix #22616) (#22641) - Fix interface conversion codegen race issue (fix #22640, #17943) (#22655) - Fix waiter funcs declarations (fix #22640) (#22649) - Improve the assert informations (fix #22666) (#22668) - Fix dump of alias to option fn type (fix #22670) (#22676) - Fix array append map value with or expr (fix #22674) (#22678) - Ensure proper saving/restoring of cgen `map[k] := fn ()` state, when assigning anonymous fns (fix #22705) (#22707) - Implement methods sort_with_compare()/sorted_with_compare() for fixed arrays (#22702) - Implement methods reverse()/reverse_in_place() for fixed arrays (#22712) - Fix ptr field encoding for `json` (fix #22717) (#22720) - Fix `[1, 2, 3]!.map(it * 2)` (#22722) - Fix `assert [1, 2, 3]!.contains(2)` (#22725) - Fix `assert [1, 2, 3]!.index(2) == 1` (#22727) - Fix spawn with non-pointer receiver (fix #22718) (#22719) - Fix `assert [1, 2, 3]!.reverse() == [3, 2, 1]!` (#22745) - Fix codegen for `-no-builtin` flag (when used separately from `-d no_main`) (#22765) - Apply the `a in [x,y,z]` optimisation for `ast.IndexExpr` and `ast.SelectorExpr` again (#22767) - Fix codegen to emit callexpr one time for `in` expr optimization (#22764) - Fix c codegen formatting for return match (#22768) - Avoid generation of empty `or` blocks for `f() or {}` (#22775) - Fix struct field name using c keyword `typeof` (fix #22779) (#22782) - Remove unused code generated for unwrapping temp var from callexpr (detect unused return value from CallExpr), fix parser bugs (#22769) - Enable if guard to add `err` var on else branch, after last `else if` (fix #22784) (#22786) - Fix option struct default value init with `-cstrict` (spotted in #22783) (#22802) - Fix codegen for fn fixed array param w/ size defined by const (fix #22811) (#22812) - Fix wrong type resolution on infix (#22804) - Fix default `T{}` when `T` is ref type + dereferencing issue when comparing int alias to int (fix #22795) (#22807) - Fix generation of a missing return in `return if cond { x } else { return missing }` (fix #22838) (#22839) - Fix generic static method call return type resolution (#22865) - Fix array fixed code generation for more than 1 dimension (fix #22866) (#22876) - Fix codegen for `$if` in an if expression, when compiled with `-g` (fix #22873) (#22888) - Make errors more informative (resolve empty panics) (related: #21184) (#22898) - Generate json array line on uniform indent lvl (#22899) - Fix codegen for returning a fixed array as a result (fix #22894) (#22896) - Fix codegen for alias type interface methods (fix #22901) (#22902) - Fix codegen for assigning aliased fixed array (fix #22907) (#22909) - Fix codegen for returning option aliased fixed array (fix #22910, fix #22911) (#22912) - Fix aliases of fixed array infix expression (fix #22925) (#22928) - Fix aliases of fixed array append to array (fix #22926) (#22929) - Fix option unwrap for fields of interface type (fixes #22930) (#22931) - Fix aliased fixed array option fn call (fix #22927) (#22934) - Move the `msvc compiler does not support inline assembly` to cgen (so it will only get triggered, when ASM blocks are still present, in what is passed to cgen) - Fix dump fixed array on array append (fix #22935) (#22940) - Fix enum value string interpolation, like its declared enum underlying type (fix #22938) (#22945) - Allow unwrapping of `x as string` expr, when `x` is a `?string` value (#22953) - Fix codegen for result/option propagation out of fn context (fix #22961) (#22963) - Fix codegen for option on concatexpr (fix #22951) (#22964) - Reduce code for returning and extra whitespaces on `return` (#22967) - Allow unwrapping of `foo.bar as string`, where `foo.bar` is `?string` (fix #22960) (#22973) - Add thread timing stats too, on `-show-timings -stats` (#22990) - Patch missing `gettid()` on glibc < 2.30 (#22987) - Fix array fixed on update expr and alias type to multi dimension of fixed array (fix #22971) ( #22972) - Fix sumtype with embedded struct of option field (fix #22984) (#22996) - Fix autostr for interface with circular type (fix #23022) (#23026) - Fix array.delete_many() codegen (fix #23024) (#23025) - Fix callexpr or-expr codegen on const decl (fix #23029) (#23043) - Fix struct update embed expr for fixed arrays (fix #22999) (#23040) - Fix update expr with embed fixed array with multiple dimensions (fix #23048) (#23049) - Fix cast interface value in match expr (#23068) - Prevent too long lines in array initialisations (#23074) - Fix smartcast codegen for msvc (#23084) - Fix option codegen for accept IError value (fix #23076) (#23085) - Fixed for in loop with generic fixed array (fix #23075) (#23101) - Fix printing fn call of returning c struct value (fix #23104) (#23106) - Fix array fixed comparison from fn return (fix #23071) (#23114) - Fix array map to fixed array (fix #23116) (#23118) - Fix codegen for returning different option alias type (fix #23087) (#23125) - Fix for in for interface type (fix #23119) (#23127) - Fix codegen for generic selector expr (fix #22974) (#23132) - Fix different option alias type as fn arg (fix #23086) (#23131) - Fix codegen for returning option reference from indexexpr (fix #23133) (#23139) - Fix array fixed auto str on `-cstrict` (#23144) - Fix codegen for array append on indexexpr (fix #23156) (#23160) - Fix assert for alias to fixed array (fix #23149) (#23161)" - Fix auto eq for fixed array (fix #23149) (#23169) - Fix fixed array option cast with `none` (fix #23164) (#23168) - Fix selector call with reserved c name (fix #23170) (#23175) - Parser,checker,cgen,fmt: fix array fixed option initialization (`none`) (complete #23164) (#23176) - Fix option fn with voidptr arg (fix #23170 for !=tcc too) (#23179) - Fix missing validation for selector unwrapping + fix default `return none` for unwrapping (#23183) - Fix assign optional aliases of fixed array (fix #23185) (#23188) - Fix struct field init with optional fixed array (fix #23193, fix #23195) (#23199) - Reduce RAM usage, by avoiding a .str() call, for the final string builder, containing the final C program, used to write it to a file (#23226) - Fix struct ref field with no ref structinit (#21932) - Define a flexible vint_t type (32 bit int on 32 bit systems, 64 bit otherwise) - Fix generic sumtype with repeated concrete type (#21948) - Fix array.map with closure var fn (#22002) - Fix generation of closures from methods on aliases (#22004) - Reduce indentation level for generated defer statements - Fix selector with interface var (#22006) - Fix free method generation for option struct (#22060) - Fix fixed array with default init (#22059) - Fix for loop with array fixed returned from fn (#22069) - Fix free method for option fields (#22070) - Fix auto free method for option map (fix #22081) (#22094) - Return early from autofree related functions, when -autofree is not used - Fix shared object method call (fix #22121) (#22125) - Fix array fixed initialization from map indexing (fix #22133) (#22149) - Fix generic options with reserved ident (#22164) - Fix struct field with default optional value (fix #11119) (#22167) - Fix array of fns index call with embeded array index (fix #17381) (#22198) - Fix match with mut cond variable (#22207) - Fix code generated for indexexpr with complex assigning (#22203) - Fix interface type generation for generic struct (fix #22186) (#22189) - Fix wrong type of vint_t and const riscv64 (#22251) - Fix code for C ident when ptr is expected (#22259) - Fix C name mangling with inherited closure vars (fix #22262) (#22263) - Fix codegen for alias to charptr passed as ptr (fix #9679) (#22271) - Fix codegen for option fntype used in a match (fix #22278) (#22280) - Fix option cast from fntype (fix #22283, #22284) (#22285) - Fix codegen for method call on rangeexpr (fix #12610) (#22291) - Fix operation overload for type aliases of fixed arrays (fix #22297) (#22304) - Fix codegen for assign from unsafeexpr resulting fixed array (fix #22301) (#22309) - Fix variadic arg var passed to another call which expects variadic (fix #22315) (#22317) - Fix aliases of array insert(...)/prepend(...) (fix #22323) (#22324) - Fix codegen for interface method call which returns a fixed array (fix #22326) (#22331) - Add `asm` to c_reserved, fixes compilation of `struct Abc { @asm int }` (#22340) - Fix interface method call after smartcast (fix #17056) (#22335) - Fix codegen for address of range (fix #18528) (#22336) - Fix printing of floating point values in asserts (#21538) - Fix array fixed initialization on struct from call (#21568) - Put the `Interface(unsafe{nil})` change for now behind -experimental (#21593) - Fix indexexpr with orexpr (fix #21591) (#21592) - Fix generic struct init when it is a reference &T (fix #21594) (#21596) - Fix generated code for handling fn call with result/option return on match conditional (#21608) - Fix missing call to a function returning option, when called inside a print (fix #21616) (#21623) - Support a `-d no_bool` option, for cgen compatibility with the C23 language standard (since `bool` is a builtin type and a keyword in it) (#21637) - Fix or expr with non option fn call return (fix #21660) (#21661) - Generate pragmas for gcc-14, to make it more relaxed by default. Support `-no-relaxed-gcc14` for turning them off. (#21680) - Fix spawn code generated when calling conditional function (fix #19352) (#21681) - Fix comptime generic arg resolution (allow several different struct fields in generic functions using comptime) (fix #18110) (#21682) - Fix dumping array of reference (#21694) - Implement g.trace_last_lines/2 to help debugging cgen problems - Support inc cond for c style for loop with alias types (#21708) - Fix fn call with mut reference args (fix #21265) (#21719) - Fix auto dereference mut variable in if expr (fix #21309) (#21720) - Fix smartcasting a reference to a sumtype value (#21730) - Fix assert checking fn option ret with `none` (#21726) - Fix generics map with the reference argument (#21737) - Fix shortcircuiting of infix and/or expressions (#21740) - Simplify in infix_expr_and_or_op() (#21745) - Fix reference variable str() method call (#21753) - Fix scope command when `$dbg` breakpoint is on or-expr (fix #21772) (#21747) - Fix array fixed empty struct code generated on clang (fix #21761) (#21764) - Allow alias to array fixed to be initialized like `[n]int{}` (#21785) - Fix comptime call argument auto conversion for indexexpr (fix #15232) (#21796) - Fix const name without main prefix in `-translated` mode (#21789) - Fix closure variable with optional reference params (fix #21827) (#21829) - Fix auto str for fn struct member (#21825) - Fix option string struct member init with autofree (#21859) - Fix fn mut argument of sumtype reference (#21874) - Fix generic type init syntax for primitive types (#21872) - Fix missing `&` in string representation of `map[X]&Y` (#21890) - Fix optional closure direct call (#21892) - Fix wrong missing unsafe block checking when calling generic functions with @[unsafe] attr ( #21898) - Fix typeof(var.typ) with comptime $for variables (#21901) - Fix enum with const value (#21919) - Fix generic option/result reference return (#21922) - Enable autofree for option (#21051) - Force C struct types which does not implement str() to be passed as ptr (#21054) - Improve diagnostic information for ORM queries with invalid types - Allow static call on generic type (#21071) - Fix code generation for a struct field, having a type of fixed array of options `field [5]?Type` ( #21082) - Add the `_M_ARM64` macro to endianness check (#21109) - Fix return code when returning interface result type (fix #21115) (#21130) - Fix const initialized with array (#21131) - Fix infix array heap comparison (#21145) - Fix C struct sumtype support (#21129) - Add `autofree` comptime check (#21197) - Fix comptime `$if !autofree {` (#21218) - Allow `for mut v in [12, 13, 14] { v+= 2 }` (#21237) - Allow op overload for type with generic parent (#21262) - Optimize .map(), .any(), .filter() and .all() when using closure (#21256) - Fix `none` passed to a generic option cast expression (fix #21215) (#21276) - Fix `-fsanitize=undefined` used with `[]int{}.sort()` (#21331) - Fix `myarr [1]C.mytype` fixed array fields, for `pub type C.mytype = voidptr` (#21266) - Fix comptime ref argument passing (#21335) - Use the real C line number instead of `#line 1000000 ...` in the C footer with `-g` (#21388) - Fine tune the line count reset for the C footer (fix off by 1 error in 00dd0bf) - Fix array.delete_last call generation (#21439) - Fix option ptr unwrapping (#21415) - Fix C struct option alias printing (#21496) - Handle auto deref var for index when the array element is an interface or a sumtype (#21491) - Fix C struct init when it has default expr (#21510) - Fix sumtype field naming (when they are the same as a C keyword) (#21527) - Fix multidimensional fixed array size expression evaluation (fix #20311) (#20458) - Fix fixed array handling with operator overloading call (fix #20467) (#20469) - Fix C code, generated for generic option fixed array return type (fix #20465) (#20479) - Fix fixed array handling, on generic result return, and on or block (#20492) - Fix generated code for fixed array cast (fix #20454) (#20480) - Change `x.filter(cond).len > 0` to `x.any(cond)`, and `x.filter(cond) == 0` to `x.all(!cond)` ( #20513) - Fix code generation wrong, when '?foo.array or {}' as a 'for-in' condition (fix #20528) (#20542) - Add a necessary clone, when the closure param is string/array with -autofree (fix #20498) (#20557) - Fix wrong cgen, when auto_heap var, is used as a closed over arg in a closure (fix #20208) ( #20566) - Initialize closures in shared library mode (#20630) - Fix interface generic smartcast (#20609) - Support inter-dependent function types (#20638) - Write the profile file out, even upon CTRL-C or kill (#20677) - Fix as cast as selector (fix #20710) (#20718) - Fix method call checking against `none` (fix #20711) (#20717) - Fix interface on multi return func (fix #20720) (#20721) - Fix premature variable release by autofree (#20731) - Fix return with option on orexpr (#20728) - Fix auto str for map with ptr str (#20741) - Remove `ull` suffix, which looks like the cause for the first scanner error in PR#20726 (#20750) - Fix comptime smartcast as receiver on method call (#20749) - Fix unwrap on or-expr, when calling f() ?Type (fix #20756) (#20758) - Builtin,coroutines,cgen: fix using coroutines with boehm GC, by using a stack pointer corrector ( #20771) - Fix interface casting (#20789) - Fix auto_eq for option eq operator overload (#20795) - Fix from_string fn generation missing mod name (#20807) - Fix const fixed array initialization handling (#20812) - Fix unwrapped option selector assigning (#20816) - Fix map methods call with generic types (fix #20827) (#20829) - Fix codegen for a.index/1, where a is []Fn (#20849) - Fix thread return type generation (fix #20836) (#20850) - Fix code generated for anon struct default value (fix #20839) (#20851) - Fix comptime selector of interface (#20876) - Fix multiple fixed array variable init (fix #20895) (#20902) - Ast,checker,cgen: fix generics function with embedded structs, ensure correct link generation in cgen (#20900) - Fix returning option call in non-option fn (#20943) - Fix global initializer of fixed array on gcc (#20934) - Fix comptime `is` condition when using interface (#20952) - Fix const fixed array init with index (#20950) - Fix generic map inferring key and value types (#20959) - Fix missing scope enclosing for const init which needs temp variables (#20973) - Fix fixed array return on fn with option generic return (#20974) - Fix code generated to comptime passed to generic arg (#20994) - Fix match for alias (#21028) - Add ability to mark a global as `@[hidden]` (#21035) - Fix _str name generated for C struct which define str() method (#21042) - Fix for/in codegen when iterating over C structs (#21052) - Fix generic fn returning fixed array (#19885) - Fix arrays alias built-in methods call(fix #19896) (#19910) - Fix generic array initialization (fix #19903) (#19916) - Fix option sumtype auto deref (#19919) - Ast, checker, cgen: fix interface embedded methods call(fix #16496) (#19936) - Fix ref and deref when an interface is used as a function parameter (fix #19947) (#19966) - Fix auto str for interface struct member which implements str method (#19970) - Fix generics call with interface arg (fix #19976) (#20002) - Fix lambda initialization on option struct field (fix #19474) (#19995) - Fix live mode on windows (#20041) - Fix the static from_string method of Enum across mods(fix #20050) (#20068) - Fix `@[if xyz?] fn init() {}`, add tests (#20096) - Fix assignment to the elements of an array of fixed arrays (#20133) - Fix mutable comptimeselector usage (fix #20027) (#20134) - Fix generics chans select (#20159) - Fix string interp with zero characters (fix #20199) (#20200) - Fix interface eq method with option and ref (fix #19441) (#20201) - Fix infix expr in method of mut receiver variable (#20225) - Fix cgen for thread wrappers, when spawning fns with with anon-fn array args and mut interfaces ( fix #19425) (#20241) - Fix fixed array return when returning fixed array initialization (#20262) - Fix function generated code, when returning from match (#20263) - Fix in expression with mut and ref (fix #20268) (#20271) - Fix initialization of const string arrays on msvc (fix #20287) (#20289) - Fix code generation when 'in array init' is used as an if condition (fix #20300) (#20302) - Escape table names (fix #20313) (#20322) - Add missing clear method for generic maps (#20340) - Fix auto unwrapping option fn type (#20332) - Fix option initialization with default struct initialization to not be `none` (#20349) - Fix auto str for arr options with possible circular reference (#20354) - Fix code generation when the function returns mut fixed array (fix #20366) (#20367) - Fix printing fixed array of options (#19479) - Fix struct field of fixed array init (fix #19483) (#19487) - Fix struct init with multi option fn type (#19491) - Ast, native, cgen: add support for `$if native {}` (#19500) - Fix maps with i32 keys - Fix for c stmt with option or result calls (#19641) - Fix infix op when handling comptime selector (#19691) - Fix array contains method with interface(fix #19670) (#19675) - Reduce expense in repetitively called functions by using consts (#19732) - Fix closure parameter judgment when var cross assign inside anon fn(fix #19734) (#19736) - Only generate free in wrapper for spawn and not go (#19780) - Fix g.obf_table data missing(fix #19695) (#19778) - Fix closure variable in smartcast (#19796) - Fix printing struct with thread field (#19320) - Fix the logic around the definition of VNORETURN and VUNREACHABLE (less warnings on FreeBSD) ( #19316) - Add support for `-d trace_cgen_stmt`, document it in CONTRIBUTING.md - Fix printing smartcast interface variable (fix #18886) (#19372) - Fix interface with multiple embedded fields (#19377) - Fix channel of interface (fix #19382) (#19383) - Fix fixed array of option type default (#19397) - Fix interface with option field (#19434) - Fix promoting an alias typed value, to a sumtype of the alias's base type (fix #19407) (#19423) - Remove the special plan9 support code, treat it instead as a posix system in cheaders.v (#19445) - Fix printing slice of fn call string (#19450) - Fix `type VType = &C.CType` (#19452) - Fix array of fns index call with direct_array_access mode (#19460) - Fix selector code to use interface method table on closure when needed (#18736) - Fix nested or expr call (fix #18803) (#18807) - Ensure that `<<` and `>>` has higher precedence in the generated C code, than arithmetic operations (diff between C and V precedences) (#18814) - Fix cross assign with aliased array (#18830) - Fix generated code for returning generic result/option to comptime var (#18834) - Fix option map with fn type value (#18849) - Fix returning an option tuple - `fn f() ?(int,int) { return g() }` (#18851) - Fix printing multiple fixed array (fix #18866) (#18879) - Fix infix expr with number overflow (fix #18905) (#18936) - Remove \r for consistency (#18962) - Allow dump(unsafe{nil}) and dump(voidptr(123)) in the same program - Implement fixed array of threads wait() (#19032) - Fix an error with ptr interpolation (fix #19048) (#19049) - Fix spawn call fn struct field(fix #18862) (#19096) - Fix bootstrapping on older macOS Catalina - Fix alias of array method call(fix #19125) (#19129) - Simplifications and clean up. - Fix mixed fixed array and array initializing (#19246) - Fix array sort with fn call parameter (fix #19220) (#19221) - Fix generic struct with option fn field (#19218) - Fix comptime assign with generic result return type (#19192) - Fix match with comptime if expr in branch (#19189) #### JavaScript backend - Simplify comptime if; catch up with cgen (fix #25295) (#25313) - Fix array type checking in sum type match expressions (fix #24237 ) (#24259) - js: fix callbacks in structure parameters (fix #24260) (#24324) - Fix array initialization with "index" and "it" (fix #24397) (#24429) - Cannot assign unsafe nil values (fix #24407, #24436) (#24458) - Fix alias type initalization (fix #24475) (#24480) - Fix casting (fix #24512) (#24519) - Alias types are not properly resolved (fix #24486) (fix #24507) (#24514) - Implement Map.keys() and Map.values() methods (fix #24209) (#24608) - Fix string.runes method (fix #20500) (#24609) - Fix direct map key access and map.len (fix #24616, fix #24605) (#24620) - Fix map to string fails on rune keys (fix #24637) (#24638) - Fix maps being always constructed using string keys (fix #24607) (fix #24671) (#24673) - Fix slightly incorrect JS (esbuild was broken on master) (fix #23711) (#24676) - Fix javascript backend treating u32 as i32 (fix #20499) (#20618) - Fix u16 cast handling in the JS backend (#20620) - Make program_test.v not flaky anymore, so that it is more sensitive to early errors. Fix compilation error for u16.v . Make u32.out match the current reality (the bug will be filed separately) - Fix inconsistent output (u32) in JS backend (#20691) #### vfmt - Force conversion of []Type{init: it} -> []Type{init: index} (#26201) - Fix `if x := g() { x } else { return }` adding newline after `return` (fix #24908) (#24945) - Fix eating the attribute from `@[deprecated] pub type Alias = int` (fix #24968), workaround -usecache bug (#24969) - Fix call expr with single line comment in or expr (fix #24659) (#25159) - Fix comment line number in file with crlf line separator (fix #23524) (#25163) - Add support for 64bit int with `-new_int` (part 2) (#25298) - Convert `"hello".str` => `c"hello"` (fix #24635) (#24652) - Fix formatting for an option array of anon structs (fix #23841) (#23844) - Fix comment handling on ending of struct decl (fix #23947) (#23948) - Add support for comments inside `sql db { ... }` blocks (fix #22601) (#22602) - Fix formatting fixed array size of struct member (#22815) - Fix formating non-unsafe blocks with break line (fix #22900) (#22903) - Fix shared receiver formatting (fix #23151) (#23153) - Allow align threshold to be parametrized in calls to add_new_info (#21942) - Fix and simplify align of struct fields (#21995) - Fix alignment of enumeration types (#21999) - Fix enum fields with one empty line (#22007) - Fix fmt of enum fields with empty line (#22015) - Fix alignment of struct init fields (#22025) - Keep empty newlines in between interface fields/methods (#22040) - Fix interface fields or methods with empty newlines (#22046) - Fix enum/struct_decl/struct_init fields with empty newlines (#22051) - Fix interface fields/methods alignment (#22055) - Remove the prefixed module name of const names, that are in the same module (related #22183) ( #22185) - Fix import selective with interface implements (fix formatting part of #22200) (#22209) - Add a test for fn with c binding type args (#22212) - Fix formating a file in an oscillating manner (fix #22223, fix #22026) (#22232) - Allow single line `defer {}`, just like `or {}` - Don't break `it` variable name in match expression function calls (#21600) - Exit with error code if encountering diffs with `-diff` flag (#21603) - Add fn_with_mut_ref_params_keep.vv (#21711) - Implement wrapping function's super long arguments (fix #15545, fix #21643) (#21782) - Keep manual newlines after fn parameters in fn declarations, do not auto wrap (#21795) - Update determining of struct field comments (#21066) - Inform about invalid interop function bodies instead of removing them (#21070) - Parse methods on JS interfaces, write JS method bodies (#21088) - Improve module detection when formatting imports (#21134) - Don't change paths when formatting imports (#21148) - Use fixed size array for max_len const (#21140) - Simplify const name formatting (#21143) - Improve import processing, add test (#21172) - Fix duplicates remove import comments (#21177) - Extend import import alias reference map for submodules (#21200) - v.fmt: drop newline in end comments for const (#20672) - Fix alias array no cast init (#20898) - Fix removal of used selective and alias imports in modules in `$VMODULES` dirs (#20977) - Improve submodule type alias lookup; fix formatting of modules in `$VMODULES` (#20989) - Fix type names for casts (#21036) - Insert auto imports after shebang (#21038) - Fix autoimport with shebang and comments above other imports (#21050) - Fix formatting for imports of submodule from module `src` dir (#21060) - tools.fmt: extend exit codes to allow spotting unformatted files next to internal errors (#21058) - Fix parsing of interface with comment above `mut:` keyword (#21062) - vfmt: automate transition from the old `[attribute]` to the new `@[attribute]` syntax (#19912) - vfmt: remove empty `__global()` (#20004) - Remove additional line breaks after call_expr before params struct args (#19795) - Fix map value alignment when using keys with uft8 symbols (#19689) - Align ternary expressions in const blocks (#19721) - Respect range index expressions in match branches (#19684) - Respect raw strings in `$embed_file(r'/some/path')` expressions (#19753) - Fix formatting of struct field with default value and new attr syntax (#19683) - Recognize or blocks in call args (#19690) #### Tools - ci: run `v doc` with VJOBS=1 on the CI, to make remote diagnosing of failures easier - Remove unused `sw := time.new_stopwatch()` call - Add support for VTEST_SHOW_CMD=1 in `v test .` too - ci: use VJOBS=1 for the `v test cmd/tools/vdoc` step too, to ease diagnosing remote CI failures - ci: bump cross-platform-actions/action from 0.29.0 to 0.30.0 (#25666) - Fix showing the *failed* compilation output with `v -silent test .` - ci: bump all `timeout-minutes: 15` to `timeout-minutes: 20` to reduce false positives due to network timeouts (mostly for the Termux job) - Note about `v help check-md` when `v check-md .` fails - ci: skip invalid_utf8_string.vv in compiler_errors_test.v for msvc - ci: reduce annotation noise, remove dead code - ci: skip the multistage v->v2->v3 -usecache checks for now (reduce false positives on the CI for unrelated PRs, until the root cause is fixed) - ci: add new job `sanitize-address-clang-without-gc` that passes `-gc none` through VFLAGS (#25780) - Support ``` VTEST_SHOW_LONGEST_BY_RUNTIME=5 \ VTEST_SHOW_LONGEST_BY_COMPTIME=5 \ VTEST_SHOW_LONGEST_BY_TOTALTIME=5 \ v test . ``` - Print total time at the *end* of the `v test-all` output to ease visual comparisons in separate shells, without scrolling - Use unbuffer_stdout in TestSession.test, to ensure consistent output on the CI jobs - v.builder: remove the obsolete check for V_NO_C_ERROR_INFO (VQUIET=1 replaced it in 2023); add VQUIET to the `-q` description - Make `v search` failures easier to diagnose (on the CI) - Support `v download -o some/folder/local.toml TOML_URL`, in addition to --target-folder - Add `--sha3-256` support for checksumming the content that `v download` saves - Add a watchdog timer in test_if_v_test_system_works.v to speedup the failure of stuck CI jobs - Use local `vtest build:` tags to eliminate the need for the skip_fsanitize_too_slow list in vtest-self.v - ci,vpm: make dependency_test.v more robust, and easier to diagnose remotely - ci: set VTMP too in set_test_env/1, to avoid cloning conflicts during parallel test executions - v.builder: do not produce `If the code is in a folder with multiple .v files` for temp V REPL files, to improve messages for `'asdas'.starts_wiz('xyz')` - Add a `-new-transformer` task to `v test-all`. Remove `-skip-unused` flags (it is the default for ~1 year). - Improve development experience for `v -W -silent test-self vlib` (especially on CIs); *always* show compilation errors for failures - Support `VTEST_KEEP_SESSION=1 ./v test vlib/math` - vet: use new annotation syntax ([] -> @[]) (#26026) - ci: bump cross-platform-actions/action from 0.31.0 to 0.32.0 (#26074) - Make the `is_sqlite3_present` check more robust (work with the system packaged sqlite library again too) - v.vmod,tools: support a repo_branch property in v.mod files, in addition to the existing repo_url property, to allow for backlinks to repos that use `main` instead of `master` as their core branch - Make the output of `v should-compile-all` more immediately useful in CI jobs (turn off stdout buffering) - Add support for `// vtest vflags: -w` in `_test.v` files, to allow `v -W test .` later, for files, that have known warnings - ci: make sure the generator for vlang/docs can be compiled with latest V (prevent silent doc update stops, after breaking changes) - Add cmd/tools/gg_split_memdump_to_frames.vsh to ease working with memdump.bin files generated by gg programs (split by frames) - Add find_doc_comments_with_no_dots.v - Improve summary output of find_doc_comments_with_no_dots.v - Skip _test.v and _test.c.v files in find_doc_comments_with_no_dots.v - ci: add report-missing-dots-in-doc-comments job - ci: mark tcp_test.v and unix_socket_test.v as flaky (they still fail sporadically on the CI, although very rarely now) - ci: add `-prealloc` self compilation checks on more platforms (#24891) - docs,ci: check more vlib modules in the report-missing-dots-in-doc-comments job (#24928) - ci: add a watchdog timer thread to ringbuffer_test.v, to make sure the program exits in a reasonable time (~10s). Let the test be retried 2 times in a row if it fails. - ci: bump cross-platform-actions/action from 0.28.0 to 0.29.0 (#24952) - ci: retry session_app_test.v 2 times, since it is network dependent, and sometimes (rarely) fails - v.help: document the new `-force-bounds-checking` option - Improve alignment for `v repeat "program" "program_that_is_over_10x_faster"` - ci: add checks for compilation of vlang/gui to v_apps_and_modules_compile_ci.yml - ci: retry 2 times vlib/net/http/server_test.v to avoid false positives for unrelated commits/PRs - ci: force changes to vlib/x/json2 to trigger the full sanitized checks (the implementation there uses unsafe blocks and vmemcmp/3...) - ci: workaround -usecache issue afte 2d87ac4 - ci: add a performance-compare-with-master job - Fix `return""` in vdoc html output (fix #24979) - ci,tools: implement support for VREPEAT_SILENT=1 and `v repeat -S`, to only show the summary of the runs, without the progress lines - ci: fix the performance-compare-with-master job, when run on PRs (#25014) - ci: trigger updates to the module docs, even if just only the static files for the doc generator are changed - ci: make sure to always compare with the latest commit on the main V repo's master branch, when running .github/workflows/compare_pr_to_master.v - ci: compare the sizes of small programs like hello_world.v, but generated with `-cc gcc` too - ci: improve the alignment of the results of file size comparisons in compare_pr_to_master.v - Improve the output of `./v doc -m -f html vlib/` - Use `Copying` instead of `Generating` for the static resources in `./v doc -m -f html vlib/` - ci: bump actions/download-artifact from 4 to 5 (#25051) - v.help: document the `-is_o option` (in `v help build-c`) and add a test for it (#25052) - ci: add experimental support for building V and testing on a Termux docker container (#25059) - ci: use retry.sh for the `pkg install` in termux_ci.yml to reduce false positives. - ci: update vlang/gui commit its latest e5cc33fe816fef33d718cb1b91f66d6bd38fb4a4 - ci: bump actions/checkout from 4 to 5 (#25095) - ci: retry 3 times vdoc_file_test.v - ci: add a build_on_ubuntu_25_ci.yml script, for testing bootstrapping with GCC 14.2.0 (#25109) - ci: define TERMUX_VERSION in .github/workflows/termux_ci.yml instead of using `-os termux`, to make the emulation closer to a real Termux (#25128) - ci: reduce timeout-minutes for CI jobs that are normally fast to help detect anomalies earlier ( #25129) - ci: add a disable_azure_mirror.sh script, and use it before `apt update` to reduce the recent timeouts during installing dependencies (#25147) - ci: bump timeout-minutes to 15 in termux_ci.yml - ci: bump actions/setup-java from 4 to 5 (#25153) - ci: retry vlib/v/eval/interpret_test.v 2 times - ci: bump retry time from 10 to 15 minutes (reduce false positives for slow dependency installations on the CI) - ci: change the azure mirror URL in /etc/apt/sources.list too - ci: use `awalsh128/cache-apt-pkgs-action@v1.5.3` instead of a manual `apt update/apt install` step, to leverage caching more (#25256) - ci: check if `awalsh128/cache-apt-pkgs-action@v1.5.3` works on master (#25257) - ci: extract .github/actions/cache-apt-packages-action/action.yml, use it in puzzle_vibes_ci.yml - Let test_os_process.v use `unbuffer_stdout()` to make the output more reliable - os,tools: make easier analyzing process_test.v failures on the CI - ci: fix build conditions that had `sanitize-memory-clang?` instead of `sanitize-memory-clang` - ci: skip running the `s390 CI` job for simple doc/yml changes (#24160) - ci: fix shell script issues reported by actionlint (#24168) - Remove the `src` subdir from projects, created by `v new` (#24236) - Add support for `// vtest build: !os_id_ubuntu?` tags in the _test.v files, detected by `v test` - ci: fix `v -o v2 -usecache cmd/v` after ad5b829 - Fix vrepl for `import mod { f }` (#24340) - ci: debug hub_docker_ci.yml issue (try 1, disable cache, run linters) - ci: debug hub_docker_ci.yml issue (try 2, add concurrency group, add a persistent single builder `gh-builder`) - ci: debug hub_docker_ci.yml issue (try 3, restore the cache-from:/cache-to: lines) - ci: fix hub_docker_ci.yml issue - comment out the cache-from:/cache-to: lines again - Support vreduce timeout, vreduce custom run command (#24359) - Rewrite `v timeout`, support killing the child process on timeout by default (#24367) - Use breadth first search in vreduce (#24369) - Vreduce fix var names (#24373) - Fix `v timeout 2 sleep 5` - Fix `./v -d network test cmd/tools/vpm` - ci: reduce false positives for cover_test.v and vdoc_test.v - Save the modified content more frequently in `v reduce`, fix timeout leaks (#24405) - Reduce padding for `v doc` produced html nodes too - ci: reduce the noise in check annotations for github PR reviews, due to the new warning in option_test.c.v - Improve show_ancient_deprecations.v, by ignoring false positives for deprecation tags in // comments - Check for Git repository in `v doctor` (packaged V versions often lack a .git/ folder) (fix #24419) (#24420) - vlib,tools: add an `arrays.diff` module, implement a simple platform independent tool `v diff file1.txt file2.txt` using it (#24428) - ci: bump creyD/prettier_action from 4.3 to 4.5 (#24439) - ci: use `v retry` to reduce the false positives for retrieving the dependencies for vinix too - ci: show `hg version` too, to ease the diagnosing of install_version_test.v failures - Let cmd/tools/vpm/install_test.v use a .hg/hgrc file too - repl: fix typeof(a) with warning (fix #24499) (#24515) - Make `v doctor` show CFLAGS and LDFLAGS too (if set) - Make `v search ui` work again through the vpm site (fix #23966) (#24535) - ci: fix unused var warning in cmd/tools/vpm/common.v - ci: prevent future changes to cmd/tools/vpm/common.v, that introduce warnings/notices to pass in PRs - x.benchmark: align the output of BenchmarkResult.print/0 - Ease diagnosing CI failures of vtimeout_test.v - ci: make sure that only one copy of native_test.v is executed at once, when run through `v test vlib` (fix #24505) - Ignore .db and .sqlite files by default in `v watch` (such DB files are very likely to change during prototyping) - .gitignore: ignore .db and .sesskey files as well - ci: bump creyD/prettier_action from 4.5 to 4.6 (#24687) - Make `v doc -f md module` output useful by default (#24737) - ci: fix native_backend_ci.yml concurrency group setting (prevent jobs for different commits on master to cancel each other) - Fix overflow detected in the sanitized runs on the CI (#24064) - ci: reduce code duplication in linux_ci.vsh - ci, vc: use the full V repo commit hash, when generating vlang/vc commit messages - Support `v should-compile-all folder/`, where `folder/` contains project subfolders (containing v.mod files and multiple top level .v files) - Improve `v should-compile-all .` with support for compiling .wasm.v and .js.v files; skip `module name` files, compile projects that have .glsl files - Improve `v bug` report wording - v.help: improve message formatting (#23363) - Restore `emcc --version` diagnostic in `v doctor`, when emcc is present - ci: fix `v -W build-tools` (#23368) - ci: force all tools to build without warnings/notices in tools_ci.yml (#23371) - Fix `v buf file.v`, when run in a folder != vroot - Improve output of `v bug file.v`, fix `v bug /long/abs/path/file.v` too - ci: make show_manual_release_cmd.vsh use a fixed weekly.YYY.WW format for the weekly release tags - ci: make easier the debugging of the `docker-alpine-musl-gcc` job (#23399) - vvet: fix for `v vet folder/` + new features (track long fns, empty fns and repeated code), enabled by the new -F and -r flags (#23405) - v.help: add a message for `v help crun` (#23431) - Make cmd/tools/vretry_test.v independent from the presence of git (fix issue #23398) - ci: add compile_herolib.sh, use it to make sure it keeps working (related #23467) (#23469) - ci: fix toml-module-pass-external-test-suites after the CI image runner upgraded jq to version 1.7, by downloading and using the release version of jq-1.6 - ci: fix failure of the check-markdown job - vet: add an `-I` option to notice fns, with the potential to be inlined (#23534) - ci: update last known good commit hash for herolib to ca8799af39228a5678a7be81128c5b0c342c9efc - Make `v check-md .` print the actual length of lines too, when reporting errors/warnings about them (#23606) - Restore previous behavior of `v download` (show progress on stdout, when it is connected to an interactive terminal; hide log stdout->stderr notice) - ci: fix `CI=name ./v -d network test cmd/tools/vpm/` ; update the image runners in vpm_ci.yml ( #23628) - Add `v reduce program.v`, in order to make smaller reproductions (`rpdc.v` files), before filing cgen bugs (#23636) - Add a small utility script `cmd/tools/vrun`, to make it easier to use .vsh scripts on systems, with `/usr/bin/env` still not supporting `-S` - Describe a more direct way to use a `v run` shebang in cmd/tools/vrun - Fix show_manual_release_cmd.vsh, use .strftime(%V) for calculating the proper default week number - Improve the `v reduce` parser for functions, and add more loops to reduce more (#23694) - Improve `v reduce` output; bump version, warn on failed string_reproduces/3, but continue to run ( #23697) - Fix warnings in `v reduce` (#23709) - Move `cmd/tools/vdoc/doc` to `cmd/tools/vdoc/document`, so that it can be imported from other programs through `-path`, without conflicting with the top level `doc/` folder in the main repo ( #23733) - ci: avoid duplicating work by removing the remaining `-skip-unused` tasks, since that is the new default (#23746) - ci: use distinct names for the jobs, for easier filtering/searching in the Github's UI - ci: fix job names in cmd/tools/modules/testing/common.v as well - ci: fix github job names in cmd/tools/vtest-self.v - ci: update the remaining runners from ubuntu-20.04 to ubuntu-22.04 and ubuntu-24.04 (#23754) - ci: rebuild V with `v -g self` in .github/workflows/native_backend_ci.yml, to improve remote diagnosis of panics in PRs - ci: use `-silent` for the longer test runs (suppress most OK lines, to reduce scrolling on failure) - .gitignore: ignore the project settings file for gf2 (a very nice GUI gdb frontend) - vrepl: fix slow response for empty line input (after just pressing 'enter/return') (fix #23856) ( #23858) - Make `v repeat failing_cmd` show the error output *just once*, but also still measure the time it took to execute - Add --check flag to `v ast` (#23938) - Add `v timeout` to be able to later use `v timeout 5.1 git -C . fetch V_REPO` in `v doctor` and other tools. - Add a custom timeout of 5s for the network using command `git -C . fetch V_REPO` in `v doctor` (it normally takes <1s) (fix #23955) - Support `v doctor -skip-github` to fully skip the fetching step, in places that have limited connectivity (alternative fix/workaround for #23955) - ci: use -silent in more jobs that produce a lot of OK lines normally (for test-cleancode, test-self, build-examples, build-tools) - ci: add benchmark_footprint_json_decode.yml and benchmark_footprint_json_encode.yml (#22592) - Use a `~same~` label, when the results in `v repeat` are not different enough - Allow for fast exiting in compare_pr_to_master.v through Ctrl-C (or any failed command) - ci: fix failing jobs after 4ed9d13 (#22606) - Discard the top 7 results for each 10 runs, from `v repeat` runs, done by compare_pr_to_master.v, to reduce σ on machines with more varied load - Allow for `v repeat -N ./cmd/tools/vtest_test`, by adding a -N/--no_vexe_reset option to `v repeat` - Show more details in compare_pr_to_master.v - ci: fix failing musl jobs after 2684ef9 (#22667) - ci: run `zizmor .github/workflows/paths_ci.yml` and fix reported issues (#22681) - Show the full test output, on known flaky test failure with `v test folder/` (#22716) - Change `v test` to allow for `// vtest hide_retries` so that retry_test.v can hide its own ( deliberate) retries - ci: rename one of the duplicate `main_test.v` files, to reduce false positives (workaround) - Fix `v doctor` output for missing `cc`. Add a diagnostic line checking for `emcc --version` too - ci: run `v fmt -w vlib/v/pref/should_compile.v` - ci: reduce flakyness of cmd/tools/vcover/cover_test.v (workaround for a race condition while updating the OK tasks counter in `v test`) - Improve the diagnostic output of compare_pr_to_master.v - ci: add a problem matcher support, to get error/warning/notice annotations in V CI jobs (#22790) - Bump default `v retry` timeout to 10 minutes, clarify the usage of its `--timeout` option. - ci: fix Build V - ci: silence compilation warning for bench_string_key_in_map_vs_string_value_in_array.v - ci: fix vinix_ci.yml for latest Vinix commits (#22818) - Improve output of compare_pr_to_master.v - Use `v retry` in more places, that do network operations that can fail temporarily (#22836) - Allow for `v download -RD URL/script.vsh`, to download `script.vsh`, then run it locally, then remove it, in a single command - v.help: add topic for `v help retry` - v.help: add help topic for `v help repeat` - ci,v.help: work around -autofree bugs, fix `./v -autofree -o v2 cmd/v` - ci: add .yml file for testing compilation of Larpon's Shy library and the Puzzle Vibes game ( #22874) - ci: check more compile flag combinations in puzzle_vibes_ci.yml - Fix compilation of hw with vnew -> vold, in compare_pr_to_master.v - ci: fix for `v build-tools` - ci: check that more apps/modules do compile with -skip-unused (#22904) - vet: make `v vet` produce a nicer note, including the offending files, instead of `file.v` ( #22957) - ci: extract the VTL&VSL jobs from v_apps_and_modules_compile_ci.yml to vsl_and_vtl_compile_ci.yml - Make oldv aware of when to pass -no-parallel when bootstrapping V from v.c (fix #22990, part 2) - markused: only add .vtest_ functions, *when* compiling _test.v files (#23003) - Improve oldv compatibility for using new stricter C compilers like clang-18, to compile older V versions from 2020 and 2019 - Use -Wno-error=incompatible-pointer-types in oldv, which is more permissive than just -Wno-error=incompatible-function-pointer-types, and works with gcc too, not just clang - Describe more precisely what commands are used by `oldv`, so it can fail early, with a meaningful error message, if they are not present. - ci: fix ROADMAP.md checks (#23059) - vrepl: shrink .repl inputs, so repl_test.v runs faster - ci: update compile_v_with_vtcc.sh, enable its CI task again (#23063) - ci: extract .github/workflows/compile_discordv.sh, enable its CI step again - json2.decoder2: prepare decoder in json2 to be replaced by json2.decode2 (#23078) - Let oldv fail early, when git fails to do network operations or checkouts - ci: fix for `-cc tcc -no-retry-compilation`, do not use more complex constants, but functions in vlib/math/vec/vec2_test.v - ci: fix option_fn_voidptr_test.v after a200c45 - ci: make the CI more robust, by retrying commands and `v download` instead of wget (#23196) - ci: use `v retry -- v setup-freetype` to make the CI more robust against random network failures - ci: change exec name for parallel cc - ci: speed up again sanitizer runs (#23222) - Implement a `-repeats/-R N` option to `v repeat`, to eliminate another need for platform dependent scripting - ci: add hub_docker_ci.yml, for building docker images (triggered manually for now) (#22302) - ci: use `docker compose` instead of `docker-compose` ( see https://github.com/orgs/community/discussions/116610) (#21992) - vrepl: suppress the welcome message, if VQUIET is set (#21941) - Make `v where` ignore .git/ folders (they contain binary files); let `-dir .` work recursively, so that `-dir vlib` works - Sort the match results in the vwhere test, to make it less flaky (#22033) - Add an amalgamate tool and description of usage (#22034) - Add a few missing v command entries and their flags in `v complete` (#22041) - Colorise the output of cmd/tools/show_ancient_deprecations.v, reduce false positives (#22048) - docs: clarify the .precision specification section for string interpolation of floats (#22061) - docs: add a copy code function (top/right copy icon) on doc examples (#22114) - Allow passing parameters to fuzz_v_parser_with_radamsa.sh, so that it could be run in several processes from the same folder - Use separate .autofuzz.log files too for the separate invocations of fuzz_v_parser_with_radamsa.sh - Extract .github/workflows/run_sanitizers.sh to ease local testing with different options - parser,ast: protect against more overflows/panics, by forcing early returns on deeply nested expressions and scopes (#22098) - Improve the output of `v repeat command`, by coloring the `faster/slower` label - Add diagnostic in `v repeat` for invalid combinations of -r, -i and -a flags - Fix `v doc` truncating code blocks, that lack a specific language (fix #22017) - v.util: add get_build_time/0, supporting https://reproducible-builds.org/docs/source-date-epoch/ - Fix `v doc` not converting `` in plain code blocks into encoded html entities in its .html output - ci: run `npx prettier --write **.yml`; ensure it is run on all .yml files, not just the ones in the .github/workflows/ folder - docs: add implements keyword for explicit interface implementations (#22214) - Make fast_job.v more robust (setup a custom PATH) and informative on fast.v failures (compile it with -g) - Make fast.v and fast_job.v more self sufficient - ci: add cache and trigger for pushes, in the Hub docker action (#22314) - Fix spurious ending quote in the output of show_manual_release_cmd.vsh - Dockerfile.alpine: update to alpine:3.20, add more tools like gdb, libunwind, gc, to ease producing and debugging static executable in more situations (#21583) - Add `v download URL` for downloading single files, to avoid curl/wget etc, which are not available uniformly. (#21597) - ci: use shebang with better portability in shell scripts, format shell scripts (#21605) - Don't write vpm logfiles in CI runs (#21649) - ci: make vmodules_overrides_test.v failures more informative - Fix measurements for `./v repeat "./vold -o x project/" "./vnew -o x project/"` - Make the summary output of `v repeat` more informative - Disallow self referencing function alias types like `type FnType = fn(string) FnType` and `type FnType = fn (FnType) string` (#21733) - vrepl: fix method call (fix #21788) (#21792) - ci: restore v_apps_and_modules_compile_ci.yml (#21791) - vrepl: fix output of the fn call (related #21792) (#21800) - vrepl: fix variable name starts with print (#21806) - v.pref: make pref_test.v be less sensitive on the specific C compiler used as a backend (#21813) - vrepl: fix arbitrary script execute (#21818) - ci: disable c2v_ci.yml temporarily, until it is fixed - vrepl: lots of fixes in REPL - Add a TOTAL line, to the output of -show-timings, to minimise the need for external tools on windows (#21847) - doc: fix vup/vself replacement scripts (#21092) - Prevent module updates during `v build-tools`, when VTEST_SANDBOXED_PACKAGING is set (#21094) - ci: update the reference to the v-analyzer repo - ci: retry all setup commands that need network access, till they succeed (so the CI jobs have less false positives) (#21103) - changelog: escape `@NAME` entries, to avoid mentioning unrelated github accounts - Add `v retry apt update`, intended to replace the retry.sh script, for more robust CI jobs ( #21104) - vpm: show the final path where a module is installed, improve color contrast for white on black terminal sessions - vet: print help when passing no files or `--help`/`-help` flag after vet command (#21108) - Fix `v build-tools` (it skipped all tools in subfolders of cmd/tools/ after 6a4f293) (#21120) - .gitignore: ignore generated .NET files in bench/vectors (#21136) - vet: optimize performance for path detection, when vetting files (#21139) - vet: allow to overwrite excluded dirs (#21142) - ci: increase wait time for the xvfb check, to reduce the chance of false positives - Fix `v run cmd/tools/measure/parser_speed.v file.v` - Add `v run cmd/tools/measure/fmt_speed.v file.v` - ci: move build step for VPM site, into apps and modules ci, add concurrency config (#21191) - tools.vpm: debug-log to `$VMODULES/cache/vpm.log` if not running in debug mode (#21192) - vpm: optimize performance by adding filter when cloning (#21216) - vdoc: don't add _docs directory when an out path is specified (#21233) - ci: prefer dedicated tiggers for platform workflows, so sporadic fails can be retried quicker ( #21251) - v.util: improve code related to diff tool specified via environment, add check if the diff tool exists (#21240) - vpm: check for git version before adding `--also-filter-submodules` flag (#21259) - ci: add logging to .github/workflows/retry.sh - Revise `vtest-self.v`: remove dead paths, fix json2 essential test path (#21267) - Add check for unavailable files in vtest (#21272) - ci: reactive app prod builds (#21295) - ci: add a m1 runner for testing the prebuilt zips too - ci: add workflow_run: event in prebuilt.yml - ci: simplify prebuilt.yml, make it usable for manual runs too - vpm: fix regression, so `v install sdl && v run ~/.vmodules/sdl/setup.vsh` works again - ci: fix outdated_test.v (--unshallow is not needed now) - ci: continue testing independent V apps, even if one fails, to get feedback for breaking changes faster (#21302) - ci: optimize apps and modules (#21303) - ci: test `v ~/.vmodules/sdl/setup.vsh`, to prevent future vpm regressions (#21306) - ci: prevent unintended deployment workflow steps (#21313) - Add a 2024.html page to https://fast.vlang.io/ - vdoc: rewrite and extend vdocignore (#21314) - ci: fix the commit labels for the vc repo - Support `v run cmd/tools/oldv.v --show_VC_commit weekly.2024.03` - ci: use latest upstream `discord.v` in apps and modules test (#21322) - vdoc: remove obsolete entries from `.vdocignore` (#21320) - v: update linguist languages, add .vdocignore (#21321) - ci: update deployment workflow (#21323) - Allow for selectively running `v test-self vlib/` and `v test-self cmd/` (#21326) - Rewrite test-self arg handling (#21327) - ci: restore `v install elliotchance.vsql` in v_apps_and_modules_compile_ci.yml - ci: use `v retry -- cmd` to replace `.github/workflows/retry.sh cmd`, where possible in `v_apps_and_modules_compile_ci.yml` (#21336) - ci: update workflow conditions (#21338) - Improve `v symlink -githubci` diagnostic message, when used outside CIs or with sudo (#21340) - ci: update detection of workflow cancellation scenarios (#21342) - Fix compiling vwhere with `-cc gcc -cstrict` (#21347) - ci: remove the separate `-gc boehm` job (since `-gc boehm` is the default now) (#21352) - ci: add a separate cmd/tools testing job (#21344) - Update fast.v and fast_job.v to update docs.vlang.io and fast.vlang.io on each commit to master. - Make fast.v more robust to independent remote changes in vlang/docs - Utilize environment specific files for vsymlink (#21360) - ci: update `binary_artifact.yml` (#21364) - ci: add docker to tools workflow, update ignore paths (#21368) - ci: split up vsl / vtl run, reducing the tool change CI time from ~19min to ~10min (#21372) - ci: fix binary_artifact.yml (#21373) - Refine `check_os_api_parity.v` (#21371) - ci: update native backend ci matrix (#21375) - ci: update symlink ci, add matrix (#21376) - ci: workaround defer codegen failing with nested if blocks and -cstrict in vdoc_file_test.v - ci: update detection of accidentally added gpl licenses (#21384) - ci: set cancel-in-progress to false in bootstrapping_ci.yml to avoid false positives - ci: do trigger bootstrapping_ci.yml periodically, but just on changes - ci: speed up bootstrapping_ci.yml, by using the default tcc when possible - ci: update `bootstrapping_ci.yml` trigger paths (#21394) - ci: pass a good commit to oldv.v in `bootstrapping_ci.yml` (#21393) - Be more verbose when doing `v up` in V folder produced by extracting a .zip release file - Exclude thirdparty/tcc from the git clean operation, that vup does in case of a missing .git folder - Protect from cleaning during `v up`, only ./v , not any matching folder - Use proper ignore/exclude patterns in the git clean, that `v up` does - Use more meaningful names in vup.v - Be verbose, when a git commands that `v up` executes fails - ci: add a v-up-works-ubuntu job, to ensure more robust `v up` runs (#21401) - ci: ensure v master is available when trying to check out its commits to build oldv (#21414) - Rewrite vet error handling (improve parser performance extend vvet) p1 (#21417) - Move dynamic const array check from parser into vet (#21423) - v.help: update help for `fmt` (#21430) - Move array_init_one_val checks from parser into vet (#21422) - Remove `vet_errors` and `vet_notices` from parser (#21424) - ci: temporary fix for gitly compilation - Remove vetting for spaces after / before parens (#21437) - Add `.github/workflows/show_manual_release_cmd.vsh`, to make cross platform testing of the release process easier - ci: merge docker_alpine and docker_ubuntu workflows in `docker_ci.yml` (#21446) - Move now obsolete vlib vet module to cmd vet (#21445) - Use `parse_file`, remove `parse_vet_file` (#21444) - ci: update binary artifact workflow, add matrix (#21378) - ci: add workflow_dispatch: to gen_vc_ci.yml - ci: fix vinix_ci.yml by using `./v symlink -githubci` in vinix_ci.yml - ci: port changes from Vinix's check.yml at 8231e569 to vinix_ci.yml - tools.vet: move error methods to `vvet/errors.v` (#21449) - ci: reduce false negatives for tcp_test.v, retry it 3 times before failing - Improve performance of `v test-cleancode` and `v fmt -inprocess -verify .` (#21450) - Make `./v symlink` work platform independent in CI (part 1) (#21453) - ci: replace .github/workflows/retry.sh usages in the CI with the shorter `v retry --`, move `v test-cleancode` upwards to save time for unformatted PRs (#21452) - Capitalize information output of `v up` (#21464) - ci: use `v symlink` without `-githubci` for regular symlinking (#21455) - ci: add a linter for the .yml workflow files (#21459) - ci: update symlink ci, extend tested cases (#21466) - tools.vet: update diff comparison in `vet_test.v` (#21457) - Call mkdir_all before set_output_path to avoid a vpm panic when ~/.vmodules/cache does not exist ( #21463) - ci: make issue template title consistent, fix linter error regarding labels (#21460) - tools.vet: reduce nesting in `vet_fn_documentation`, skip vetting empty lines (#21465) - Print info to use v symlink instead of `v symlink -githubci` (#21471) - Move _test.v files for vdoc at the same level (#21473) - ci: update the helper script, for getting the most recent sqlite-amalgamation-3380200.zip (#21474) - vdoc: fix handling of .vdocignore files in subdirectories (#21514) - ci: run build-module-docs, when changes to the source of the `v doc` tool happen too - ci: use g++ not g++-11 in misc-tooling (g++-11 can not be found and installed on the CI runner anymore for some reason) - ci: update g++ to g++-10 in other_ci.yml, add workflow_dispatch: trigger for easier local future diagnostic - vdoc: improve vdocignore file handling by walking all .vdocignore sub-paths in IgnoreRules.get, add test (#21521) - ci: run `v fmt -w cmd/tools/vdoc/vdoc_test.v` - ci: make sure that unformatted code in just cmd/ is not allowed - ci: mark again tcp_test.v as flaky (it had 3 unrelated failures on the CI over the last week) - v: vet for empty string conditions (#21529) - tools.vet: add notice for empty strings conditions (#21421) - repl: support executing shell commands on the REPL with `!sh [COMMAND]` (#20496) - repl: fix an issue with `print` and println after the execution of `for` or `if` (fix #20524) ( #20525) - tools: bump too_long_line_length_table to 160, to avoid warnings for just `v check-md doc/docs.md` (most common) - tools: bump too_long_line_length_link to 250, to avoid warnings for very common long links - ci: simplify time_ci.yml, use more descriptive CI job names, for easier judging of CI failures - debug: fix variable dereferencing (#20594) - tools: support setting another SCANNER_MODE=parse_comments in parser_speed.v and scanner_speed.v - testing: fix warning for compiling `./v cmd/tools/vtest.v` - docs: add a section about modules specifics (#20653) - github: add dependabot.yml (#20800) - vtest,pref: add ability to have platform specific _test.v files (#20810) - ci: change spaceface777/cancel-workflow-action to styfle/cancel-workflow-action (#20806) - tools: use the same same skipping logic for the platform specific _test.v files in `v test-self` too (#20815) - tools: make the output of `v check-md .` more informative (#20819) - v.debug: implement tracing hook feature (#20818) - ci: mark db_store_test.v as flaky - ci: add a vtcc step (check that vtcc, continues to be able to compile with v, and v itself can be compiled with vtcc) (#21000) - v.util: simplify vtest (#21013) - vtest-self: add sandboxed packaging case (#21059) - tools: fix already installed detection when running v install --once without args (#19838) - compress.gzip: change the endianness for validation to conform to the gzip file specification (fix #19839) (#19849) - tools: support `v doc -run-examples math`, to ensure that all `// Example: code` doc comments are working (#19852) - Fix `v help` in the prebuilt v executables from the zips in the releases - ci,tools: remove skips for the wasm backend, since binaryen is not required anymore (#19883) - tools.vpm: support again `http` installs, when installing from an url (workaround) (#19914) - tools.vpm: improve version detection of installed modules (#19933) - tools: fix `v up`, by not deleting `./v` when missing a `.git` folder (#19965) - tools.vpm: fix installing of modules with conflicting names, extend tests (#19961) - tools.vpm: evaluate dependencies earlier to fix potential recursive install loop (#19987) - tools.vpm: add support for ssh and hg version installations (#20125) - tools: simplify and remove redundancies in vshader.v (#20161) - ci: add new workflow, for doing the slower tests in vpm specifically with `-d network` (#20177) - tools.vpm: improve detection of already parsed modules (#20223) - scanner: change `-d debugscanner` to `-d trace_scanner` for uniformity with the other tracing options, described in CONTRIBUTING.md - v.pref: support a `-n` option, silencing only notices (#20331) - ci: add vsql to v_apps_and_modules_compile_ci.yml too (#20341) - ci: fix the workflow for Vinix, using the rules in its own .yml file (#20371) - Support -? as alias to -help (implement #20355) (#20358) - vdoc: filter testdata and tests folders by default, reduce filesystem stats calls - all: add support for `@LOCATION`, for more convenient logging/tracing, without needing to combine `@FILE`, `@LINE` at runtime (#19488) - benchmark: add new methods b.record_measure/1 and b.all_recorded_measures/0 (#19561) - ci: update c2v workflow, translate doom on macOS (#19562) - strings: add Bulder.write_decimal/1 method (write a decimal number, without additional allocations) (#19625) - testing: add temporary file hash to prevent accidental collisions with test file binaries (#19710) - ci: compile VTL and VSL in their own CI job, with `VFLAGS=-no-parallel` - tools: fix windows install of an already existing module with vpm (#19761) - tools: use `VPM_NO_INCREMENT` env var to skip dl count increment when testing vpm (#19756) - tools.vpm: improve handling of urls that end with .git (#19758) - tools: fix resolving external dependencies in vpm, add test (#19772) - tools: cleanup and simplify vcreate, for upcoming fixes and features (#19794) - tools: improve error messages, add color coding and debug logging (#19781) - tools: fix `v build-tools`, make `v test` more robust (#19803) - tools: add parse_query to vpm (#19814) - ci: add macos arm64 binary release (#19823) - Require the presence of a `v.mod` file, to install external urls via vpm (#19825) - vcreate: fix `v init` with project names containing dashes (#19619) - bench: a new bench/ directory for language benchmarks - ci: test the pure V math versions without .c.v overrides on the CI too (#19292) - github: add automatically info about voting to all new issues (#19351) - tools: add -E flag to `v test-parser`, that will show the partial source that caused the parser to fail with `-no-builtin -check-syntax file.v` - ci: bring back gitly - github: improve the voting message for issues (#19448) - vcreate: update templates, add `lib` (#19444) - ci: add v-analyzer builds (#18835) - ci: cleanup more the contents of the generated v_linux.zip, v_macos.zip, and v_windows.zip, use -skip-unused - tools: fix vcomplete for zsh (#18950) - tools: support a toc for projects, with single exposing module, in `v doc` (#19001) - Add support for `v should-compile-all -c examples/`, which will delete all the produced executables at the end - vgret: add install commands for ubuntu and arch to doc string (#19247) - fast.v: add favicon to the html produced by fast.v - vpm: implement multithreading (#19208) - Make performance_compare.v more robust and easier to use, by allowing `v run cmd/tools/performance_compare.v` too - Improve oldv windows support, make it use -municode for windows builds, make it support cmd.exe - Make repeated runs of `oldv SAME_COMMIT -c "./v file.v"`, not use the network at all - Help: add link to the TESTS.md at the bottom of `v help test`, run CI checks on help markdown files as well - v.builder: show the number of files, types, modules, when a program is compiled with -stats - Improve the output of parser_speed.v and scanner_speed.v #### Operating System support - ci: fix gcc-windows -std=c99 (#25534) - os: add windows stdin_write() support (#25546) - ci: use `macos-14` instead of `macos-13` (the older runner is being deprecated) (#25670) - v.builder: fix json-errors with a windows path separator (#25680) - ci: fix unsetting of VFLAGS in `v run ci/linux_ci.vsh v_self_compilation_usecache_clang` - ci: stop unsetting VFLAGS completely in ci/linux_ci.vsh and ci/macos_ci.vsh - builtin,os: fix windows execute ANSI encoding result, make msvc error messages readable in a Chinese locale (fix #25727) (#25736) - db.sqlite: update windows version to https://sqlite.org/2025/sqlite-amalgamation-3510000.zip ( #25766) - os.notify: fix struct epoll_event alignment on ARM64/Linux (fix #25778) (#25779) - fasthttp: Linux/epoll support - math: reduce the nested level of expressions, to reduce the chances of stack overflows on windows - net.http,ci,db.sqlite: rewrite .github/workflows/windows-install-sqlite.bat in .vsh, fix vschannel on windows downloading content > 32KB (#25792) - v.builder: bump the default stack size for executables, when compiling with msvc on windows, to 32MB (#25824) - ci: reduce the chances of false positives due to hangs of use_net_and_net_unix_together_test.v on windows - doc: add subsections about using SQLite on windows and about installing the self contained `sqlite` module. - v.builder: switch to using `-std=c99`, instead of `-std=gnu99` to avoid name colisions with C `linux` macros defined by gcc/clang (#25848) - gg: set more sensible and user friendly defaults for the width, height and the title of new windows - thirdparty: update thirdparty-openbsd-amd64_tcc.sh (#25945) - ci: install plain gcc on the OpenBSD jobs - ci: use `gcc` as the name of the compiler instead of `egcc` on OpenBSD - ci: remove the gcc-openbsd job, until OpenBSD people fix their broken conventions on 7.8 - ci: run `v -W -silent test-self vlib` on linux, so deprecations/warnings introduced in PRs, can fail (and be fixed) earlier (#25955) - ci: use VTEST_SHOW_LONGEST_BY_* vars on OpenBSD (#25958) - ci: update to use FreeBSD version 15.0 (#25985) - crypto.ecdsa: update to test and use OpenSSL 3.5 on OpenBSD (#25995) - x.crypto.slhdsa: add support on OpenBSD using OpenSSL 3.5 (#25996) - ci: reduce failure rate for the gcc-windows job, in test_if_v_test_system_works.v - ci: skip use_net_and_net_unix_together_test.v on gcc-windows (many weird timeouts on unrelated PRs) - db.sqlite: fix exec_param_many on linux for the case of a [][]string parameter - v.util: add `-d max_suggestions_limit=140` for v itself, to improve handling of large .v files with many thousands of lines on windows - v.util: bump max_suggestions_limit to 200, to account for windows - ci: extract windows_ci_msvc.yml from windows_ci.yml to enable finer grained workflow/job control - ci: extract and split windows_ci_tcc.yml and windows_ci_gcc.yml from windows_ci.yml for improved job control - docs: add section in README for compilation on OpenBSD (#24775) - crypto.ecdsa: add support for OpenSSL on OpenBSD (#24772) - picoev: add implementation for OpenBSD using kqueue (#24801) - log: fix `Unhandled Exception` on windows 7 (#24803) - ci: migrate the remaining jobs from the deprecated windows-2019 image to windows-2022 (#24825) - os: fix windows get_error_msg() leak (#24899) - runtime: reduce allocations done in runtime.used_memory/0 on linux (#24901) - ci: skip checking vlib/datatypes/lockfree/ringbuffer_test.v on the gcc-windows job for now - runtime: add used_memory() implementation for FreeBSD (#24909) - runtime: add used_memory implementation for OpenBSD (#24918) - ci: skip ringbuffer_test.v in the tcc-windows and msvc-windows jobs too, to avoid flakyness for unrelated commits/PRs. - ci: use FreeBSD version 14.3 after the bump of cross-platform-actions/action to 0.29.0 (#24953) - time: fix timezone test on windows - ci: add a release build for Linux on arm64 to release_ci.yml (#25064) - thirdparty: add `thirdparty-linux-armv7_bdwgc.sh` for building `libgc.a` on ARMv7 CPUs (#25077) - ci: bump retry count for server_test.v to 5 (reduce false positives on windows) - ci: use `v build-tools` without flags for the tools-windows job - os: eliminate warning for `v -cross -o vc/v.c cmd/v` on linux (part 2, see also 037a3b4) - os,sync: enable running `v -cross -o x.c cmd/v` on windows too (part 1, fix V errors) - ci: run .github/workflows/disable_azure_mirror.sh before all `apt update` commands, in ci/linux_ci.vsh, when run in a github CI runner - ci: retry 3 times cmd/tools/vtimeout_test.v on windows, before failing - os,ci: use a conditional include, instead of a platform file, to include libproc.h on macos only - ci: run input_rune_iterator_test.v only on linux for now - builtin: fix thread naming issue on Windows by ignoring RaiseException (0x406D1388) (#25270) - os: implement Process.is_pending() on windows (fix #23990) (#23993) - os: support .set_environment() on windows too (fix #10628) (#23996) - thirdparty: update thirdparty-linux-amd64_tcc.sh, to also record its own full invocation command, and commit the changes automatically - thirdparty: add thirdparty/build_scripts/thirdparty-freebsd-amd64_tcc.sh - ci: reduce false positives for slow runs of the gcc-windows job - gg: fix screen_size() on macos with multiple displays - ci: add riscv64_linux_ci.yml (based on QEMU) as well (#24181) - ci: use `apt update` before `apt install` in cross_ci.yml, to make the linux job more robust - thirdparty: add thirdparty/build_scripts/thirdparty-macos-arm64_tcc.sh for compiling tcc on macos (first draft) - Simplify the implementation of get_linux_os_name in `v doctor` - os.filelock: compile without warnings with gcc on windows - ci: use windows-2025 for the gcc-windows job (since it has gcc 14.2.0) (#24304) - ci: skip option_ptr_unwrap_test.v on windows with msvc (#24320) - os: fix windows rmdir GetLastError() (fix #24356) (#24357) - Enable windows tcc_backtrace() support (#24377) - ci: reduce false positives for init_global_test.v on windows (retry it 2 times) - ci: reduce false positives for orm_func_test.v on windows (retry it 2 times) - os: force using `C.CREATE_NO_WINDOW` on windows in os.raw_execute/1 (fix #24390) (#24418) - Fix v doctor output on FreeBSD ; do not run ldd to get the glibc version (#24427) - runtime: improve free_memory implementation for OpenBSD, by getting the stats from its UVM system (#24431) - runtime: fix cast error in free_memory implementation for OpenBSD (#24445) - Use a `.hg/hgrc` file for install_version_test.v (workaround windows failure) - os: add debugger_present implementation for OpenBSD (fix #23603) (#24490) - veb: reduce veb_max_write_bytes from 16KB to 2KB (fix sending large dynamic responses from veb on macos/freebsd) (fix #24523) (#24522) - os: fix os.File's tell/0 method for windows (fix #24217) (#24218) - net.openssl: replace SSL_get1_peer_certificate by SSL_get_peer_certificate for OpenBSD (#24556) - net.mbedtls: disable AES-NI on OpenBSD with tcc (fix #22239) (#24560) - net.mbedtls: enable MBEDTLS_THREADING_C and MBEDTLS_THREADING_PTHREAD on OpenBSD (#24572) - thirdparty: add thirdparty/build_scripts/thirdparty-openbsd-amd64_tcc.sh for compiling tcc on OpenBSD (#24592) - v.builder: enable -fwrap for C compilation on OpenBSD too (#24585) - v.pkgconfig: add the default `/opt/local/lib/pkgconfig` for MacPorts on macos (#24626) - sync: increase retries for vlib/sync/select_close_test.v to 3, to reduce CI false positives in the gcc-windows job - ci: remove script to build tcc on FreeBSD (obsoleted by thirdparty/build_scripts/thirdparty-freebsd-amd64_tcc.sh) (#24681) - encoding.iconv: add path for iconv library on FreeBSD (#24682) - native: skip linux.vv too, for the sanitized jobs (similar to libc.vv) - ci: migrate from windows-2019 runner to windows-2025 runner in most jobs (github deprecated the 2019 runner) (#24672) - runtime: fix -cstrict compilation (use usize() cast in free_memory) on OpenBSD (#24696) - Remove specific case for FreeBSD in `cmd/tools/vtest_test.v` (#24707) - docs: add section in README for compilation on FreeBSD (#24706) - thirdparty: add script to build libgc on FreeBSD/amd64 (#24717) - builtin: use local static libgc for FreeBSD with tcc (fix #24710) (fix #24683) (#24720) - ci: update and improve FreeBSD CI (#24726) - ci: add CI for OpenBSD (#24732) - gg: fix .char event handling for backspace, delete, tab and enter for linux/x11 (send appropriate .char codes to the apps, similar to macos) - Add aarch64 atomics support in thirdparty/stdatomic/nix/atomic.h (fix #24294) (#24296) - v.trace_calls: now musl has gettid(), there is no need for the shim on newer Alpine etc (#24245) - Avoid os.glob, in favour of os.walk_ext (which works consistently even on windows) - gg: add linux support for `fn screen_size() Size` (fix #23146) (#23326) - Define _GNU_SOURCE on Linux (#23364) - Fix `v doctor` format, fixes for windows, tcc and others (#23361) - picoev: fix for windows apps with veb in a thread, parallel to a webview, that opens a lot of file descriptors (#23492) - v.pref: set `DYLD_FALLBACK_LIBRARY_PATH` on macos, when `-use-coroutines` is used, so that `v run` can work, and the executable can find the downloaded photonwrapper shared library (#23516) - encoding.iconv: add flag for OpenBSD to find iconv include and library (fix #23573) (#23575) - runtime: add free_memory/0 implementation for OpenBSD (fix #23579) (#23583) - Fix `v doctor` output on OpenBSD: get gcc version from egcc; do not run ldd to get the glibc version (fix #23576) (#23578) - make.bat: add note about antivirus programs on windows and compilation slowdowns (#23586) - runtime: add free_memory/0 implementation for FreeBSD too (fix #23581) (#23594) - log,sync: fix macos CI failure when log.ThreadSafeLog is used explicitly in `v download` (#23613) - Let `v test .` show the running _test.v files each minute (set by `VTEST_REPORT_RUNNING_PERIOD_MS`); diagnose stuck windows gcc CI jobs (#23649) - ci: run FreeBSD on a VM in github ci, instead of on the Cirrus service (which stopped working today) (#23692) - cgen,builder: fix windows 32bit dll function name mangle (fix #23689) (#23690) - ci: update linux image runners from `ubuntu-20.04` to `ubuntu-24.04` (#23706) - ci: do not use `VJOBS: 1` in the windows tcc job anymore - make: use .exe only on Windows - ci: reduce the timeouts in windows_ci.yml to 60 minutes (V is now faster, and the runners use faster hardware as well) - native: allow for searching for wine system32/ .dlls, and for adding more paths for .dll lookups, by setting `VNATIVE_PE_DLL_PATH`, to make it easier to diagnose problems with PE generation on non windows platforms (#23756) - ci: skip fibonacci_native.vv on windows for now - sync: support x86_64-alt-linux gcc paths too when tcc is used (needed for ALT Linux) - ci: make freebsd_ci.yml runnable on personal forked repos, that are not named `v` (#23779) - ci: remove the VJOBS=1 restriction for test-cleancode on linux (#23801) - os: fix buffer overflow in os.get_raw_line under Windows (#23816) - ci: move test in pe_test.v to native_test.v (both used `-b native`, competing the creation of the backend executable => CI failures on the gcc-windows job) - Make `v install` avoid using `--filter=blob:none --shallow-submodules --also-filter-submodules` on windows (#23840) - os: fix get_raw_line() on windows (fix #23843) (#23846) - ci: add a limit of 20 minutes to the test-on-freebsd-14-2-x86 CI job - Support `// vtest build: !do_not_test ?`, `// vtest build: !windows && tinyc` to skip files during testing on specific platforms, without having to keep centralised skip lists (#23900) - cgen,dl: remove workaround in `dl`, generate a DllMain() in cgen instead for `-shared` on windows (#23961) - builder: change linuxroot repo URL to https://github.com/vlang/linuxroot - ci: test -os linux cross compilation on macOS - ci: test the cross compilation from macos to linux sooner, show more information - ci: move the macos->linux check even higher, to make easier testing and diagnosing linuxroot update failures - orm: cross compile pg to linux; openssl: make cross compile work - ci: use `macos-14` instead of `macos-12` because of https://github.com/actions/runner-images/issues/10721 - ci: macos_ci.vsh - ci: fmt macos_ci.vsh - ci: use thew new macos_ci.vsh (github) - ci: improve output of macos_ci.vsh - ci: extract `ci/common/runner.v`, use it to simplify ci/macos_ci.vsh even more - ci: fix spurious failures for printing_struct_with_thread_field.vv on windows - net.http: ensure that http.download_file_with_progress/3 works (in a degraded mode), on windows, even without passing `-d no_vschannel` - builder: fix cross compiling from linux to windows, when passing -g/-cg - docs: update the documentation of the @[console] tag, add advice to use `-subsystem windows` instead - Make compare_pr_to_master.v use /opt/homebrew/bin/gtime on macos, and a pure V fallback, not just for windows - ci,thirdparty: enable MBEDTLS_THREADING_PTHREAD and MBEDTLS_THREADING_C only on Linux for now (fix windows CI) - thirdparty: enable MBEDTLS_THREADING_C and MBEDTLS_THREADING_PTHREAD on FreeBSD too - os: use _wputenv instead of _putenv to stay in sync with _wgetenv (fix changing env variables with non ASCII content on windows) (#22920) - ci: avoid false positives for the existing PRs, by comment out the task `V self compilation with -usecache` on macos for now (#23145) - ci: linux_ci.vsh; cgen: parallel-cc fixes - ci: remove extra EOL from linux_ci.yml (#23187) - Fix profile time on windows (#23227) - docs: streamline the installation instructions and notes for Windows and Ubuntu - v.builder: fix errors in cstrict mode on OpenBSD with clang (#22154) - thirdparty: fix compilation of programs using miniz.h on macos - crypto.rand: fix compilation on macos with `-cc tcc -no-retry-compilation -gc none` - thirdparty: fix compilation of thirdparty/mbedtls with tcc on macos m1 - v.pkgconfig: fix parser, when `includedir=` lines, had trailing spaces (fix `-d use_openssl` for openssl 3.3.2 installed through brew on macos) - builtin: fix compilation with tcc on OpenBSD using libgc (#22234) - docs: add FreeBSD in cross compilation section (#22249) - v.builder: enable LTO for clang on OpenBSD (#22247) - thirdparty: fix compilation of programs using miniz.h on OpenBSD (#22254) - net: fix compilation on windows (use casts to int for net.error_eintr etc) - net: use explicit int casts for net.error_eintr etc in the unix implementation too for consistency with the windows one - veb: support sendfile() syscall on FreeBSD (#21541) - os: use 1 instead of C.SW_SHOWNORMAL to workaround a cross compilation issue from linux to windows - v.builder: minimise the amount of linked libs for cross compilation to FreeBSD - v.builder: support downloading the FreeBSD cross compilation files on first use - Add a test for crosscompiling hw, on linux and macos, to FreeBSD (#21553) - vlib: make `./v -Wimpure-v -W test vlib/` pass on Linux (#21554) - os: fix debugger_present() for non Windows OSes (#21573) - ci: extend coverage, move app test from macos_ci to v_apps_and_modules_ci (#21584) - gc: fix tcc on macos - os.font: return the "segoeui.ttf" font, if its file exists on Windows (#21655) - readline: fix s := read_line('Message\nName:') on unix/linux (#21930) - ci: improve test robustness on windows (#21116) - v.pkgconfig: add pkgconfig path `/usr/libdata/pkgconfig` for FreeBSD base packages (#21151) - v.util: add diff tool color support detection (tested on linux and freebsd) (#21244) - v.util.diff: return diff options with the diff command for FreeBSD/OpenBSD (#21271) - v.pkgconfig: fix load_paths with `;` split char on windows (#21291) - Fix vpm on macos, when using the bundled git executable (#21292) - ci: fix the bundled tcc for macos arm64 (#21299) - ci: update the runner for build-macos-arm64 to `macos-14` too, so it runs on M1 - Fix hot code reloading on windows (#21351) - Fix building vpm on the FreeBSD instance, that runs fast.v - Fix `v install` for the FreeBSD instance that updates docs.vlang.io . - ci: use macos-13 for cross_ci.yml to force the old non m1 runner - v.builder: update macos->linux cross compile message (~22MB -> ~77MB) - v.pref: fix new pref test on FreeBSD (#21385) - ci: stop earlier on vc/v.c files, that may break on systems != linux (#21397) - Fix compilation on macos-arm with `-cstrict`; run macos ci also on the arm runner (#21408) - ci: use `v` instead of `./v` in the platform linux/macos/windows/_ci.yml files (#21454) - ci: add a retry to vcreate_init_test.v (it is sporadically flaky on macos) - sync,os,thirdparty: fix cross compilation from macos to windows (#21484) - os: rename os_structs_stat_windows.v to os_structs_stat_windows.c.v to fix `v -Wimpure-v -os windows vlib/os/os_stat_test.v` - Default to `-cc clang` on FreeBSD in `cmd/tools/vtest_test.v` (#21534) - v.builder: allow for `v -shared -os windows file.v` on Linux/macos (fix #20445) (#20453) - Add windows dll support, fix (#20447) (#20459) - sync: add mutex.try*lock functions for FreeBSD too (#20482) - sync: fix FreeBSD implementation of sync functions (#20483) - os: make os.cache_dir() and os.vtmp_dir() more robust to parallel test executions on windows ( #20495) - builder: replace "-rdynamic" for clang on macos with "-Wl,-export_dynamic" (fix #20510) (#20511) - builder: restore ability to use tcc, without fallback to cc on macos - v.builder: use a more uniq prefix for the generated temporary file names, to further reduce the chances of collision and sporadic CI failures on windows (#20551) - encoding.csv: fix bug in RandomAccessReader, spotted on windows with mingw32 (#20571) - builtin: use `#pkgconfig bdw-gc-threaded` where available, instead of `#pkgconfig bdw-gc` (on FreeBSD) - db.pg: add include and lib paths for PostgreSQL on FreeBSD (#20582) - thirdparty: fix `v cmd/tools/vcompress.v` on FreeBSD - os: fix an error in Process.win_spawn_process, not using stdout pipe in a cmd environment on 32bit Windows (#20613) - testing: retry 1 additional time sporadic silent test run failures on macos - builder: add '-lelf' to linker flags on freebsd (fix #20481) (#20643) - GNUmakefile: use standard default RM make variable to fix MSYS2 env on windows (#20701) - x.vweb: add the missing include for C.sendfile to sendfile_linux.c.v - clipboard: fix notice in clipboard_windows.c.v (#20733) - ci: update macos runners to macos-14, to make use of the much faster m1 instances (#20747) - builder: support musl-gcc on macos - builtin: link to user32 to fix boehm GC compilation on Windows with clang released from the LLVM project (fix #20724) (#20767) - pref: download correct photonwrapper.so for linux (#20783) - ci: improve repo CI robustness, by marking dynamic_template_manager_cache_system_test.v as flaky, and only failing db_store_test.v on !windows - tools.vpm: fix remove command on Windows, add test (#20852) - os: don't check rdev equality on FreeBSD, inside vlib/os/os_stat_test.v (#20885) - sync: support more gcc version specific search locations on linux with tcc - os: small cleanup in the FreeBSD branch of os.executable/0: use fixed array for the sysctl params, instead of allocating a dynamic one (#20353) - os: improve os.executable() on OpenBSD (#20356) - v.util.diff: support OpenBSD's default `diff` tool (#20369) - os: fix os.open_file/3 `wb` mode creation of text files containing crlf on Windows (#20101) - os: fix File.tell for files > 2GB on windows, by using C._telli64(f.fd) (#20072) - builtin: use `libgc-threaded` on FreeBSD, to get the threaded version of libgc (#19294) #### Examples - Handle closing of the window in the event manager in examples/viewer (#25522) - ci: add a report-wrong-examples-in-doc-comments job, that runs `./v doc -check-examples -f none vlib/` (#25554) - Make reproduction of failed examples easier (make sure that all the checked sources have an ending \n) - Use math.vec in path_tracing.v and in vyper.v - Support `v -d trace_execution run examples/brainvuck.v mandlebrot.bf` - ci: do not use `-silent` for the `v build-examples` task on windows, to make it easier to diagnose recent gcc-windows timeouts - doc: add an example for reading from a non empty buffered channel, after closing it - Fix and improve vanilla_http_server (#25905) - ci: remove `-silent` from the macos build_examples task too, to make remote diagnosing of CI timeouts easier - Add optional `update_fn: fn (dt f32, ctx &gg.Context)` to gg.Context and gg.Config . Pass consistently the current GG context to *all* callback functions, instead of nil. - Add expanding_rect.v (modeled after the example from https://love2d.org/wiki/love), add generic helpers gg.frgb/3 gg.frgba/4 - tools,examples,veb: fix `v -d trace_before_request run examples/veb/veb_example.v` after feedback from https://youtu.be/IuE6Bo1klK0?t=2100 - Move flag/ .v files 1 level up, to prevent module lookup confusion for unrelated examples - Add a Lorem Ipsum Generator (#26036) - examples,net.ftp,v.builder: remove remaining matches of `rg --multiline --multiline-dotall "continue\n\t+\}\n\t+\}\n\t+return" -B3 -A3 ` - Update lorem.v with a Markov algorithm for better text generation (#26085) - fasthttp: fix the correctness of the minimal server example, when tested with curl (#26072) - v.gen.native: fix `v -os macos -experimental -b native -o hw.macos examples/hello_world.v` on linux - tutorials: remove newline in the example for c2v's cc compilation to `doomv` (#26200) - Make all the labels fit in the default window size header in minesweeper.v - Fix for `v build-tools` and `v build-examples` running on a i686 (the problem was discovered by @tankf33der) - Add examples/sokol/sounds/simple_keyboard_synth.v - builtin,markused: consider println of non string to use .str() method calls too, reduce generated C code for `v -cc gcc examples/hello_world.v` (#24996) - Use a sieve of Eratosthenes in primes.v, to handle bigger inputs more efficiently - vdoc: make -run-examples compatible with all output modes, not just the plaintext one - vdoc: extract vdoc_run_examples_test.v from vdoc_file_test.v - vdoc: implement -unsafe-run-examples and -check-examples support, add tests and document them - builtin,vdoc: fix the examples for the builtin methods, so that `v doc -check-examples -time -f ansi vlib/builtin/` pass - builtin,vdoc: make `v doc -unsafe-run-examples -time -f ansi vlib/builtin/` pass too - vdoc: improve failed example report - vdoc: support `v doc -check-examples -f none vlib/builtin` - bitfield: fix `v doc -unsafe-run-examples -f none vlib/bitfield/` too - arrays.parallel: fix `v doc -unsafe-run-examples -f none vlib/arrays/parallel/` too - arrays: fix `v doc -unsafe-run-examples -f none vlib/arrays/` too - compress.deflate,compress.gzip,compress.zlib,compress.zstd: fix `v doc -unsafe-run-examples -f none vlib/compress/` too - sokol.audio: fix doc comment examples - encoding.base64: fix doc comment examples - math: fix doc comment examples - readline: fix doc comment example by removing it - semver: fix doc comment examples - vdoc: enable example lines that have explicit imports too, fixup the remaining vlib examples, so `v doc -v -unsafe-run-examples -f none vlib/` could be added to the CI - Add euler.v - examples,gg: add examples/gg/grid_of_rectangles.v; add gg.Context.draw_rect_filled_no_context/5 and gg.Context.draw_rect_empty_no_context/5 - veb.auth: update the README.md example (#25245) - builtin: fix `v -W -Wimpure-v examples/hello_world.v` (move ctovstring_impl to builtin.c.v) - Fix rune casting from u32 in rune.v (#25307) - Fix `v -os wasm32_emscripten -o ms.html examples/gg/minesweeper.v` (use os.asset to load the font, avoid the implicit closures for the frame/event callbacks)' - Update rotating_textured_quad.v with instructions on how to compile/run it with emscripten and a browser - Add a small examples/gg/bouncing_balls.v simulation of falling balls - Fetch 30 stories instead of 10 in examples/news_fetcher.v - Add sync_pool.v for easier testing/diagnosing issues with the `sync.pool` implementation on different platforms - Add a `-profile` report column, to show only the func time, *excluding* the accumulated children calls time (usable through `./v -profile - run a.v |sort -nk3` for example) (#24056) - doc: improve Shared and Channels's topics, add more examples (#24155) - orm: fix option type, convert from int to i8, add examples, etc (fix #24211) (#24213) - Fix optional callback parameter and improve examples (fix #24325) (#24336) - Reduce padding for code examples, to fit more examples on the same screen without scrolling - Cleanup unsafe{} blocks that are not needed anymore in examples/sokol/08_sdf/sdf.v - Show the number of pushes in sokoban too - os.asset: add read_text/2 too, use it to simplify the sokoban example - Support directly loading sokoban level files by path - Add more Sokoban levels - Support boxoban style collections of levels files ( from https://github.com/google-deepmind/boxoban-levels/) - Add a simple sudoku solver - Add primes.v, that shows how to get command line arguments, and use loops and functions - Add a small memory game (#24643) - Cleanup memory.v (reduce it to 135 lines) - builtin,os: enable no warnings for gg programs like `v -gc boehm_leak -cg -keepc run examples/gg/minimal.v` (part 1 - before the `gg` loop) (#24749) - Allow for passing arbitrary compiler flags to `v bug`, for example: `v bug -cg -autofree file.v` ( #23335) - examples,builtin,cgen,live: fix windows hot reload with `-cc tcc`, improve the infrastructure, use a V global instead of a C one (fix #23214) (#23350) - Fix unused db.pg import warning for examples/database/psql/customer.v - gg,sokol,examples: add example of overriding _SGL_DEFAULT_MAX_VERTICES in code - Mention also the RAM usage increase in many_thousands_of_circles_overriding_max_vertices.v - gg: enable clean compilation without notices for `./v -check-unused-fn-args examples/tetris/` - Add vascii.v showing a table of the first 128 ASCII characters with their names and codes in dec, oct, hex, bin formats (#23466) - Add a solution to the "1 Billion Row Challenge" (#23458) - examples,io: add sha256sum_with_io_cp.v, make the size of the buffer used by io.cp parametrisable (#23585) - log: add `log.use_stdout()`, use it to silence the transition note for the most commonly used V tools/examples (#23642) - Implement an -s option for `v ast`, to skip all nodes with default values like [], {}, 0, false; with it `v ast -pts examples/hello_world.v | wc -l` is 36 lines - gg: fix `./v -gc none -autofree run examples/tetris/` (avoid `return s1 + s2 + s3`, clone the arrays, passed to the fontstash wrapper) - examples,gg: modify all remaining calls to fons.add_font_mem/3 to use an array.clone() - Add examples/hot_reload/tunnel.v - Add minimal_c_like_program_using_puts.v showing how to produce a much smaller executable on Linux, using clang, mold and sstrip. - Build examples, that start with `module no_main` as well - ci: fix `v build-examples` failure on gcc-windows - Support `module no_main` based examples in `v should-compile-all` - term: make the second example in the README.md compilable as well - Show how to use a v file server for the wasm version of 2048, instead of emrun - sokol: allow for `v -os wasm32_emscripten -o examples/tetris/tetris.html examples/tetris/` (avoid using `-sMODULARIZE`) (#23814) - Fix poll_coindesk_bitcoin_vs_usd_rate.v, use the new v2 API endpoint - math,examples: add examples/sokol/sounds/simple_sin_tone_using_audio_push.v, cleanup math - Add a small breakout game, supporting keyboard and touch controls (#23861) - Cleanup snek.v, by using `math.vec`, the builtin array support, instead of `datatypes`, and by removing casts that are no longer needed - Fix `v -cstrict -cc gcc-11 examples/sokol/particles` and the same but with clang-18 too - Fix more compilation errors with `-cstrict -cc clang-18` for the sokol examples - Fix `VFLAGS='-no-skip-unused -cstrict -cc clang-18' v should-compile-all examples/sokol/` too - Add a small minesweeper game in examples/gg/minesweeper.v - Add a small Sokoban puzzle game with levels (see https://en.wikipedia.org/wiki/Sokoban) - Use textures in the sokoban game, instead of colors - Shorten the periodic output of examples/hot_reload/message.v - Fix (ball->side edge of brick) collision detection in breakout.v - Add subtle light and shadow effects to the breakout game, to give it a little depth (#23885) - Run the update method of breakout on its own frame independent rate - gg,examples: use a timer to limit the rate of updates in breakout, instead of a separate thread, restore ability to run in a browser through emscripten - Make the tetris update rate, independent from the frame rate too - Make the 2048 game update rate, independent from the frame rate as well - Fix panic, discovered by fuzzing examples/2048/2048.v with zzuf on the CI - Add `vanilla_http_server` - a fast, multi-threaded, non-blocking, port and host reuse, thread-safe, epoll server (#23094) - v.build_constraint: support comments too, for example `linux&&gcc // some comment` - Make `v repeat -R 5 -r 10 "v run examples/hello_world.v"` also show the time it took for all runs in each repeat - Add an asteroids game (it is currently < 400 lines of V, using gg) - Remove the generic alias type overloaded operator workaround, after 29e60da - Fix `v should-compile-all examples/` - Fix some of the instructions in `examples/thread_safety/` (#22571) - builder,pref: fix `./v -os linux examples/json.v` on macos (#22651) - Add examples/assets/v.svg and examples/assets/v_16x16.svg - v.comptime: fix compilation of `examples/veb/veb_example.v` with V compiled with tcc on macos - ci: ensure that all examples can still be compiled, by `v` compiled with tcc on macos - Add poll_coindesk_bitcoin_vs_usd_rate.v - Simplify and reorder output of poll_coindesk_bitcoin_vs_usd_rate.v - builtin: fix `v -skip-unused -cc tcc examples/hello_world.v` on *BSD - net.mbedtls: bump mbedtls_ssl_conf_read_timeout value to 550ms (tested with `v run examples/net_t.v`) - Add a cpu_features/ folder, with several examples, using SSE and MMX assembly instructions ( #22645) - v.builder: fix `./v -check -stats examples/hello_world.v` - docs: add a small sumtype match example in the Match section too - Add TextScanner .skip_whitespace/0, .peek_u8/0, .peek_n_u8/0, add examples/mini_calculator_recursive_descent.v (#23001) - Reduce completion friction, when doing the very common `v run examples/hello_world.v` in a shell - Remove drag_n_drop.v from the list of examples, that are checked for visual differences with vgret, since it now uses the default gg font - docs: add more C interop notes and examples (#21965) - cleanup obsolete unsafe{} usages in examples/sokol/sounds - cleanup & fix the sound produced by melody.v - add a simplified bytebeat player to show how to use sokol.audio, and that does not depend on gg - make `rotating_textured_quad.v` compile and run on Android (#21987) - veb: change example description, to avoid repetitive wording (ease debugging of issue#22017) - eval: fix `./v interpret examples/hanoi.v` - add examples/ttf_font/draw_static_text.v, to make it easier to test x.ttf with different fonts, and texts - make draw_static_text.v show the font name too, for easier comparisons - prevent cliping of long font names in draw_static_text.v - docs: add an example on how to use Options/Results, when returning multiple values from a function (#22099) - add examples/gg/draw_unicode_text_with_gg.v, for easy comparison of how different fonts and unicode texts will look, when rendered by gg - add examples/veb/websocket, to show how to use http connection upgrade to a websocket, from a `veb` route (#22128) - migrate vweb examples to veb - fix type in veb_example.v - add `gc_is_enabled()` check to `2048` to prevent crash in Android emulator (#22274) - make `gg/rectangles.v` Android friendly (#22275) - make `gg/stars.v` run on android (#22276) - examples,os: add an os.asset module, use it to simplify code in examples/, by removing `$if android {` checks (#22281) - add a consistent background to flappylearning, shown when the height of the view is very high (on Android) - encoding.xml: make functions public, add documentation, tests, fix attribute parsing for self-closing tags (#19901) - examples: show how to turn on CORS in a vweb server app - examples: serve the wasm mandelbrot project using a v web server (#19937) - examples: increase the resolution of the generated image in examples/wasm/mandelbrot - docs: update null convention in ORM example, since `@[nonull]` is no longer needed (#20286) - docs: add an example of a nullable ORM field (#20292) - example: add a path finding algorithm visualizer using gg (#20060) - examples: add an even smaller gg usage example, demonstrating how to always show the builtin fps counter, and how to avoid importing gx - tests: workaround name conflict, causing false positives with msvc on windows, when both tests were executed at the same time (locked executable) - examples: add more .obj files for 06_obj_viewer (#19406) ================================================ FILE: ci/common/runner.v ================================================ module common import os import log import term import time // exec is a helper function, to execute commands and exit early, if they fail. pub fn exec(command string) { log.info('cmd: ${command}') result := os.system(command) if result != 0 { exit(result) } } // unset is a helper function to unset a specific env variable. pub fn unset(evar string) { log.info('unsetting env variable: ${evar}') os.unsetenv(evar) } // file_size_greater_than asserts that the given file exists, and is at least min_fsize bytes long. pub fn file_size_greater_than(fpath string, min_fsize u64) { log.info('path should exist `${fpath}` ...') if !os.exists(fpath) { exit(1) } log.info('path exists, and should be a file: `${fpath}` ...') if !os.is_file(fpath) { exit(2) } real_size := os.file_size(fpath) log.info('actual file size of `${fpath}` is ${real_size}, wanted: ${min_fsize}, diff: ${real_size - min_fsize}.') if real_size < min_fsize { exit(3) } } const self_command = 'v ' + os.real_path(os.executable()).replace_once(os.real_path(@VEXEROOT), '').trim_left('/\\') + '.vsh' pub const is_github_job = os.getenv('GITHUB_JOB') != '' pub type Fn = fn () pub struct Task { pub mut: f Fn = unsafe { nil } label string } pub fn (t Task) run(tname string) { cmd := '${self_command} ${tname}' log.info('Start ${term.colorize(term.yellow, t.label)}, cmd: `${cmd}`') start := time.now() t.f() dt := time.now() - start log.info('Finished ${term.colorize(term.yellow, t.label)} in ${dt.milliseconds()} ms, cmd: `${cmd}`') println('') } pub fn run(all_tasks map[string]Task) { unbuffer_stdout() log.use_stdout() if os.args.len < 2 { println('Usage: v run macos_ci.vsh ') println('Available tasks are: ${all_tasks.keys()}') exit(0) } task_name := os.args[1] if task_name == 'all' { log.info(term.colorize(term.green, 'Run everything...')) mut failed_tasks := []string{} for tname, t in all_tasks { cmd := '${self_command} ${tname}' log.info('Start ${term.colorize(term.yellow, t.label)}, cmd: `${cmd}`') start := time.now() result := os.system(cmd) dt := time.now() - start if result != 0 { log.error('FAILED ${term.colorize(term.red, t.label)} in ${dt.milliseconds()} ms, cmd: `${cmd}`') failed_tasks << tname } else { log.info('Finished ${term.colorize(term.yellow, t.label)} in ${dt.milliseconds()} ms, cmd: `${cmd}`') } } if failed_tasks.len > 0 { log.error('${failed_tasks.len} task(s) failed: ${failed_tasks}') exit(1) } exit(0) } t := all_tasks[task_name] or { eprintln('Unknown task with name: `${task_name}`') exit(1) } t.run(task_name) } ================================================ FILE: ci/freebsd_ci.vsh ================================================ import os import common { Task, exec } fn v_doctor() { println('### vdoctor') dump(os.getenv('PATH')) exec('v doctor') if common.is_github_job { exec('freebsd-version') exec('sysctl hw.model') exec('sysctl hw.ncpu') exec('sysctl hw.physmem') exec('sysctl hw.usermem') exec('whoami') exec('pwd') exec('ls -la') exec('git log -n1') exec('cc --version') } } fn build_v_with_prealloc() { println('### Build v with prealloc') exec('v -cg -cstrict -o vstrict1 cmd/v') exec('./vstrict1 -o vprealloc -prealloc cmd/v') exec('./vprealloc run examples/hello_world.v') exec('./vprealloc -o v3 cmd/v') exec('./v3 -o v4 cmd/v') exec('./v4 -d debug_malloc -d debug_realloc -o vdebug1 cmd/v') } fn verify_v_test_works() { println('### Verify v test') exec('echo \$VFLAGS') exec('v cmd/tools/test_if_v_test_system_works.v') exec('./cmd/tools/test_if_v_test_system_works') } fn build_fast_script() { println('### Build fast script') exec('cd cmd/tools/fast && v fast.v') } fn check_math() { println('### Test vlib/math') exec('v -silent test vlib/math') println('Test the math module, using only the pure V versions,') println(' without the .c.v overrides.') exec('v -silent -exclude @vlib/math/*.c.v test vlib/math') } fn test_inline_assembly() { println('### Test inline Assembly') exec('v test vlib/v/slow_tests/assembly') } fn check_compress() { println('### Test vlib/compress') exec('v -silent test vlib/compress') } fn run_essential_tests() { if common.is_github_job { println('### Run essential tests') exec('VTEST_JUST_ESSENTIAL=1 v -silent test-self') } else { exec('VTEST_JUST_ESSENTIAL=1 v -progress test-self') } } fn build_examples() { if common.is_github_job { println('### Build examples') exec('v -W build-examples') } else { exec('v -progress build-examples') } } const all_tasks = { 'v_doctor': Task{v_doctor, 'Run v doctor'} 'build_v_with_prealloc': Task{build_v_with_prealloc, 'Build V with prealloc'} 'verify_v_test_works': Task{verify_v_test_works, 'Verify that v test works'} 'build_fast_script': Task{build_fast_script, 'Check that building fast.v works'} 'check_math': Task{check_math, 'Check the `math` module works'} 'check_compress': Task{check_compress, 'Check the `compress` module works'} 'test_inline_assembly': Task{test_inline_assembly, 'Test inline Assembly'} 'run_essential_tests': Task{run_essential_tests, 'Run only the essential tests'} 'build_examples': Task{build_examples, 'Build examples'} } common.run(all_tasks) ================================================ FILE: ci/linux_ci.vsh ================================================ import common { Task, exec } // Shared tasks/helpers fn all_code_is_formatted() { if common.is_github_job { exec('v -silent test-cleancode') } else { exec('v -progress test-cleancode') } } fn verify_v_test_works() { exec('echo \$VFLAGS') exec('v cmd/tools/test_if_v_test_system_works.v') exec('./cmd/tools/test_if_v_test_system_works') } fn test_pure_v_math_module() { exec('v -exclude @vlib/math/*.c.v test vlib/math/') } fn self_tests() { if common.is_github_job { exec('v -W -silent test-self vlib') } else { exec('v -progress test-self vlib') } } fn build_examples() { if common.is_github_job { exec('v -W build-examples') } else { exec('v -progress build-examples') } } fn v_doctor() { exec('v doctor') } fn build_v_with_prealloc() { exec('v -cg -cstrict -o vstrict1 cmd/v') exec('./vstrict1 -o vprealloc -prealloc cmd/v') exec('./vprealloc run examples/hello_world.v') exec('./vprealloc -o v3 cmd/v') exec('./v3 -o v4 cmd/v') exec('./v4 -d debug_malloc -d debug_realloc -o vdebug1 cmd/v') } // TCC job tasks fn install_dependencies_for_examples_and_tools_tcc() { if common.is_github_job { exec('.github/workflows/disable_azure_mirror.sh') } exec('v retry -- sudo apt update') exec('v retry -- sudo apt install --quiet -y libssl-dev sqlite3 libsqlite3-dev valgrind') exec('v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev libegl-dev') // Wayland development libraries for sokol Wayland support exec('v retry -- sudo apt install --quiet -y libwayland-dev libxkbcommon-dev libwayland-egl1-mesa libxkbcommon-x11-dev') // The following is needed for examples/wkhtmltopdf.v exec('v retry -- sudo apt install --quiet -y xfonts-75dpi xfonts-base expect') exec('v retry -- wget --quiet https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-2/wkhtmltox_0.12.6.1-2.jammy_amd64.deb') exec('v retry -- sudo dpkg -i wkhtmltox_0.12.6.1-2.jammy_amd64.deb') } fn test_v_to_c_tcc() { exec('thirdparty/tcc/tcc.exe -version') exec('v -cg -o vtcc cmd/v') // ensure vtcc can build itself twice } fn v_self_compilation_tcc() { exec('v -o v2 cmd/v') exec('./v2 -o v3 cmd/v') exec('./v3 -o v4 cmd/v') } fn v_doctor_tcc() { v_doctor() } fn verify_v_test_works_tcc() { verify_v_test_works() } fn test_pure_v_math_module_tcc() { test_pure_v_math_module() } fn self_tests_tcc() { exec('v -keepc -cc tcc -g self') self_tests() } fn build_examples_tcc() { build_examples() } fn run_submodule_example_tcc() { exec('v -W run examples/submodule') } fn build_tools_tcc() { if common.is_github_job { exec('v -N -W build-tools') } else { exec('v -progress -N -W build-tools') } } fn build_vbinaries_tcc() { exec('v -N -W build-vbinaries') } fn build_benches_tcc() { exec('v should-compile-all vlib/v/tests/bench/') } fn run_vsh_script_tcc() { exec('v run examples/v_script.vsh') } fn test_v_tutorials_tcc() { exec('v tutorials/building_a_simple_web_blog_with_veb/code/blog') } fn build_fast_tcc() { exec('cd cmd/tools/fast && v fast.v') exec('cd cmd/tools/fast && ./fast') } fn v_self_compilation_usecache_tcc() { $if !enable_usecache_test ? { eprintln('> ${@LOCATION} use `-d enable_usecache_test` in VFLAGS to enable this task') return } exec('v wipe-cache') exec('v -usecache examples/hello_world.v') exec('./examples/hello_world') exec('v wipe-cache') exec('v -o v2 -usecache cmd/v') exec('./v2 -o v3 -usecache cmd/v') exec('./v3 version') exec('v wipe-cache') exec('./v3 -o tetris -usecache examples/tetris/tetris.v') exec('rm -f ./examples/hello_world v2 v3 tetris') } fn test_password_input_tcc() { exec('v test examples/password/') } fn test_readline_tcc() { exec('v test examples/readline/') } fn test_leak_detector_tcc() { exec('v -gc boehm_leak -o testcase_leak vlib/v/tests/testcase_leak.vv') exec('./testcase_leak 2>leaks.txt') exec('grep "Found 1 leaked object" leaks.txt') exec('grep -P ", sz=\\s?1000," leaks.txt') } fn test_leak_detector_not_active_tcc() { exec('v -o testcase_leak vlib/v/tests/testcase_leak.vv') exec('./testcase_leak 2>leaks.txt') exec('[ "$(stat -c %s leaks.txt)" = "0" ]') } // GCC job tasks fn all_code_is_formatted_gcc() { all_code_is_formatted() } fn install_dependencies_for_examples_and_tools_gcc() { if common.is_github_job { exec('.github/workflows/disable_azure_mirror.sh') } exec('v retry -- sudo apt update') exec('v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind') exec('v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev') // Wayland development libraries for sokol Wayland support exec('v retry -- sudo apt install --quiet -y libwayland-dev libxkbcommon-dev libwayland-egl1-mesa libxkbcommon-x11-dev wayland-protocols libegl-dev') } fn recompile_v_with_cstrict_gcc() { exec('v -cc gcc -cg -cstrict -o vstrict cmd/v') } fn valgrind_v_c_gcc() { exec('valgrind --error-exitcode=1 v -o v.c cmd/v') } fn run_sanitizers_gcc() { exec('v -o v2 cmd/v -cflags -fsanitize=thread') exec('v -o v3 cmd/v -cflags "-fsanitize=undefined -fno-sanitize=alignment"') exec('UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 ./v2 -o v.c cmd/v') exec('UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 ./v3 -o v.c cmd/v') } fn v_self_compilation_gcc() { exec('v -o v2 cmd/v') exec('./v2 -o v3 cmd/v') exec('./v3 -o v4 cmd/v') } fn v_self_compilation_usecache_gcc() { $if !enable_usecache_test ? { eprintln('> ${@LOCATION} use `-d enable_usecache_test` in VFLAGS to enable this task') return } exec('v wipe-cache') exec('v -usecache examples/hello_world.v') exec('examples/hello_world') exec('v wipe-cache') exec('v -o v2 -usecache cmd/v') exec('./v2 -o v3 -usecache cmd/v') exec('./v3 version') exec('v wipe-cache') exec('./v3 -o tetris -usecache examples/tetris/tetris.v') exec('rm -f ./examples/hello_world v2 v3 tetris') } fn verify_v_test_works_gcc() { verify_v_test_works() } fn test_pure_v_math_module_gcc() { test_pure_v_math_module() } fn self_tests_gcc() { self_tests() } fn self_tests_prod_gcc() { exec('v -o vprod -prod cmd/v') exec('./vprod -silent test-self vlib') } fn self_tests_cstrict_gcc() { exec('VTEST_JUST_ESSENTIAL=1 V_CI_CSTRICT=1 v -cc gcc -cstrict -silent test-self vlib') } fn build_examples_gcc() { build_examples() } fn build_tetris_autofree_gcc() { exec('v -autofree -o tetris examples/tetris/tetris.v') exec('rm -f tetris') } fn build_blog_autofree_gcc() { exec('v -autofree -o blog tutorials/building_a_simple_web_blog_with_veb/code/blog') exec('rm -f blog') } fn build_option_test_autofree_gcc() { exec('v -autofree vlib/v/tests/options/option_test.c.v') } fn v_self_compilation_parallel_cc_gcc() { exec('v -o v2 -parallel-cc cmd/v') exec('rm -f v2') } fn build_modules_gcc() { exec('v build-module vlib/os') exec('v build-module vlib/builtin') exec('v build-module vlib/strconv') exec('v build-module vlib/time') exec('v build-module vlib/term') exec('v build-module vlib/math') exec('v build-module vlib/strings') exec('v build-module vlib/v/token') exec('v build-module vlib/v/ast') exec('v build-module vlib/v/parser') exec('v build-module vlib/v/gen/c') exec('v build-module vlib/v/depgraph') exec('v build-module vlib/os/cmdline') } fn compile_vdoctor_prod_gcc() { exec('v -showcc -cc gcc -prod cmd/tools/vdoctor.v') } fn compile_vup_prod_gcc() { exec('v -showcc -cc gcc -prod cmd/tools/vup.v') } // Clang job tasks fn all_code_is_formatted_clang() { all_code_is_formatted() } fn install_dependencies_for_examples_and_tools_clang() { if common.is_github_job { exec('.github/workflows/disable_azure_mirror.sh') } exec('v retry -- sudo apt update') exec('v retry -- sudo apt install --quiet -y postgresql libpq-dev libssl-dev sqlite3 libsqlite3-dev valgrind') exec('v retry -- sudo apt install --quiet -y libfreetype6-dev libxi-dev libxcursor-dev libgl-dev libxrandr-dev libasound2-dev') // Wayland development libraries for sokol Wayland support exec('v retry -- sudo apt install --quiet -y libwayland-dev libxkbcommon-dev libwayland-egl1-mesa libxkbcommon-x11-dev wayland-protocols libegl-dev') exec('v retry -- sudo apt install --quiet -y clang') } fn recompile_v_with_cstrict_clang() { exec('v -cc clang -cg -cstrict -o vstrict cmd/v') exec('rm -f vstrict') } fn valgrind_clang() { exec('valgrind --error-exitcode=1 v -o v.c cmd/v') exec('rm -f v.c') } fn run_sanitizers_clang() { exec('.github/workflows/run_sanitizers.sh') } fn v_self_compilation_clang() { exec('v -o v2 cmd/v') exec('./v2 -o v3 cmd/v') exec('./v3 -o v4 cmd/v') } fn v_self_compilation_usecache_clang() { $if !enable_usecache_test ? { eprintln('> ${@LOCATION} use `-d enable_usecache_test` in VFLAGS to enable this task') return } exec('v wipe-cache') exec('v -usecache examples/hello_world.v') exec('./examples/hello_world') exec('v wipe-cache') exec('v -o v2 -usecache cmd/v') exec('./v2 -o v3 -usecache cmd/v') exec('./v3 version') exec('v wipe-cache') exec('./v3 -o tetris -usecache examples/tetris/tetris.v') exec('rm -f ./examples/hello_world v2 v3 tetris') } fn verify_v_test_works_clang() { verify_v_test_works() } fn test_pure_v_math_module_clang() { test_pure_v_math_module() } fn self_tests_clang() { self_tests() } fn self_tests_vprod_clang() { exec('v -o vprod -prod cmd/v') exec('./vprod -silent test-self vlib') } fn self_tests_cstrict_clang() { exec('VTEST_JUST_ESSENTIAL=1 V_CI_CSTRICT=1 ./vprod -cstrict -silent test-self vlib') } fn build_examples_clang() { build_examples() } fn build_examples_autofree_clang() { exec('v -N -W -autofree -experimental -o tetris examples/tetris/tetris.v') exec('rm -f tetris') } fn build_modules_clang() { exec('v build-module vlib/os') exec('v build-module vlib/builtin') exec('v build-module vlib/strconv') exec('v build-module vlib/time') exec('v build-module vlib/term') exec('v build-module vlib/math') exec('v build-module vlib/strings') exec('v build-module vlib/v/token') exec('v build-module vlib/v/ast') exec('v build-module vlib/v/parser') exec('v build-module vlib/v/gen/c') exec('v build-module vlib/v/depgraph') exec('v build-module vlib/os/cmdline') } fn native_machine_code_generation_common() { exec('cd cmd/tools && v gen1m.v') exec('cd cmd/tools && ./gen1m > 1m.v') exec('cd cmd/tools && v -backend native -o 1m 1m.v') exec('cd cmd/tools && ./1m && ls -larS 1m*') exec('cd cmd/tools && rm -f ./1m ./1m.v') } fn native_machine_code_generation_gcc() { native_machine_code_generation_common() } fn native_machine_code_generation_clang() { native_machine_code_generation_common() } fn native_cross_compilation_to_macos() { exec('v -os macos -experimental -b native -o hw.macos examples/hello_world.v') common.file_size_greater_than('hw.macos', 8000) exec('rm -f hw.macos') } fn test_inline_assembly() { exec('v test vlib/v/slow_tests/assembly') } // Collect all tasks const all_tasks = { 'build_v_with_prealloc': Task{build_v_with_prealloc, 'Build V with prealloc'} // tcc tasks 'all_code_is_formatted_tcc': Task{all_code_is_formatted, 'All code is formatted (tcc)'} 'install_dependencies_for_examples_and_tools_tcc': Task{install_dependencies_for_examples_and_tools_tcc, 'Install deps for examples/tools (tcc)'} 'test_v_to_c_tcc': Task{test_v_to_c_tcc, 'Test v->c with tcc'} 'v_self_compilation_tcc': Task{v_self_compilation_tcc, 'V self compilation (tcc)'} 'v_doctor_tcc': Task{v_doctor_tcc, 'v doctor (tcc)'} 'verify_v_test_works_tcc': Task{verify_v_test_works_tcc, 'Verify `v test` works (tcc)'} 'test_pure_v_math_module_tcc': Task{test_pure_v_math_module_tcc, 'Test pure V math module (tcc)'} 'self_tests_tcc': Task{self_tests_tcc, 'Self tests (tcc)'} 'build_examples_tcc': Task{build_examples_tcc, 'Build examples (tcc)'} 'run_submodule_example_tcc': Task{run_submodule_example_tcc, 'Run submodule example (tcc)'} 'build_tools_tcc': Task{build_tools_tcc, 'Build V tools (tcc)'} 'build_vbinaries_tcc': Task{build_vbinaries_tcc, 'Build V binaries (tcc)'} 'build_benches_tcc': Task{build_benches_tcc, 'Build benches (tcc)'} 'run_vsh_script_tcc': Task{run_vsh_script_tcc, 'Run a VSH script (tcc)'} 'test_v_tutorials_tcc': Task{test_v_tutorials_tcc, 'Test V tutorials (tcc)'} 'build_fast_tcc': Task{build_fast_tcc, 'Build cmd/tools/fast (tcc)'} 'v_self_compilation_usecache_tcc': Task{v_self_compilation_usecache_tcc, 'V self compilation with -usecache (tcc)'} 'test_password_input_tcc': Task{test_password_input_tcc, 'Test password input (tcc)'} 'test_readline_tcc': Task{test_readline_tcc, 'Test readline (tcc)'} 'test_leak_detector_tcc': Task{test_leak_detector_tcc, 'Test leak detector (tcc)'} 'test_leak_detector_not_active_tcc': Task{test_leak_detector_not_active_tcc, 'Test leak detector not active (tcc)'} // gcc tasks 'all_code_is_formatted_gcc': Task{all_code_is_formatted_gcc, 'All code is formatted (gcc)'} 'install_dependencies_for_examples_and_tools_gcc': Task{install_dependencies_for_examples_and_tools_gcc, 'Install deps for examples/tools (gcc)'} 'recompile_v_with_cstrict_gcc': Task{recompile_v_with_cstrict_gcc, 'Recompile V with -cstrict and gcc'} 'valgrind_v_c_gcc': Task{valgrind_v_c_gcc, 'Valgrind v.c (gcc)'} 'run_sanitizers_gcc': Task{run_sanitizers_gcc, 'Run sanitizers (gcc)'} 'v_self_compilation_gcc': Task{v_self_compilation_gcc, 'V self compilation (gcc)'} 'v_self_compilation_usecache_gcc': Task{v_self_compilation_usecache_gcc, 'V self compilation with -usecache (gcc)'} 'verify_v_test_works_gcc': Task{verify_v_test_works_gcc, 'Verify `v test` works (gcc)'} 'test_pure_v_math_module_gcc': Task{test_pure_v_math_module_gcc, 'Test pure V math module (gcc)'} 'self_tests_gcc': Task{self_tests_gcc, 'Self tests (gcc)'} 'self_tests_prod_gcc': Task{self_tests_prod_gcc, 'Self tests (-prod) (gcc)'} 'self_tests_cstrict_gcc': Task{self_tests_cstrict_gcc, 'Self tests (-cstrict) (gcc)'} 'build_examples_gcc': Task{build_examples_gcc, 'Build examples (gcc)'} 'build_tetris_autofree_gcc': Task{build_tetris_autofree_gcc, 'Build tetris with -autofree (gcc)'} 'build_blog_autofree_gcc': Task{build_blog_autofree_gcc, 'Build blog tutorial with -autofree (gcc)'} 'build_option_test_autofree_gcc': Task{build_option_test_autofree_gcc, 'Build option_test.c.v with -autofree (gcc)'} 'v_self_compilation_parallel_cc_gcc': Task{v_self_compilation_parallel_cc_gcc, 'V self compilation with -parallel-cc (gcc)'} 'build_modules_gcc': Task{build_modules_gcc, 'Build modules (gcc)'} 'compile_vdoctor_prod_gcc': Task{compile_vdoctor_prod_gcc, 'compile vdoctor with -prod (gcc)'} 'compile_vup_prod_gcc': Task{compile_vup_prod_gcc, 'compile vup with -prod (gcc)'} // clang tasks 'all_code_is_formatted_clang': Task{all_code_is_formatted_clang, 'All code is formatted (clang)'} 'install_dependencies_for_examples_and_tools_clang': Task{install_dependencies_for_examples_and_tools_clang, 'Install deps for examples/tools (clang)'} 'recompile_v_with_cstrict_clang': Task{recompile_v_with_cstrict_clang, 'Recompile V with -cstrict and clang'} 'valgrind_clang': Task{valgrind_clang, 'Valgrind (clang)'} 'run_sanitizers_clang': Task{run_sanitizers_clang, 'Run sanitizers (clang)'} 'v_self_compilation_clang': Task{v_self_compilation_clang, 'V self compilation (clang)'} 'v_self_compilation_usecache_clang': Task{v_self_compilation_usecache_clang, 'V self compilation with -usecache (clang)'} 'verify_v_test_works_clang': Task{verify_v_test_works_clang, 'Verify `v test` works (clang)'} 'test_pure_v_math_module_clang': Task{test_pure_v_math_module_clang, 'Test pure V math module (clang)'} 'self_tests_clang': Task{self_tests_clang, 'Self tests (clang)'} 'self_tests_vprod_clang': Task{self_tests_vprod_clang, 'Self tests (vprod) (clang)'} 'self_tests_cstrict_clang': Task{self_tests_cstrict_clang, 'Self tests (-cstrict) (clang)'} 'build_examples_clang': Task{build_examples_clang, 'Build examples (clang)'} 'build_examples_autofree_clang': Task{build_examples_autofree_clang, 'Build examples with -autofree (clang)'} 'build_modules_clang': Task{build_modules_clang, 'Build modules (clang)'} 'native_machine_code_generation_clang': Task{native_machine_code_generation_clang, 'native machine code generation (clang)'} 'native_machine_code_generation_gcc': Task{native_machine_code_generation_gcc, 'native machine code generation (gcc)'} 'native_cross_compilation_to_macos': Task{native_cross_compilation_to_macos, 'native cross compilation to macos'} 'test_inline_assembly': Task{test_inline_assembly, 'Test inline assembly'} } common.run(all_tasks) ================================================ FILE: ci/macos_ci.vsh ================================================ import common { Task, exec } fn test_symlink() { exec('v symlink') } fn test_cross_compilation() { exec('v -o hw -os linux examples/hello_world.v && ls -la hw && file hw') exec('v -d use_openssl -o ve -os linux examples/veb/veb_example.v && ls -la ve && file ve') } fn build_with_cstrict() { exec('v -cg -cstrict -o vstrict1 cmd/v') } fn all_code_is_formatted() { if common.is_github_job { exec('VJOBS=1 v -silent test-cleancode') } else { exec('v -progress test-cleancode') } } fn run_sanitizers() { exec('v -o v2 cmd/v -cflags -fsanitize=undefined') exec('UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 ./v2 -o v.c cmd/v') } fn build_using_v() { exec('v -o v2 cmd/v') exec('./v2 -o v3 cmd/v') } fn verify_v_test_works() { exec('echo \$VFLAGS') exec('v cmd/tools/test_if_v_test_system_works.v') exec('./cmd/tools/test_if_v_test_system_works') } fn install_iconv() { exec('brew install libiconv') } fn test_pure_v_math_module() { exec('v -silent -exclude @vlib/math/*.c.v test vlib/math/') } fn self_tests() { if common.is_github_job { exec('VJOBS=1 v -silent test-self vlib') } else { exec('v -progress test-self vlib') } } fn build_examples() { if common.is_github_job { exec('v build-examples') } else { exec('v -progress build-examples') } } fn build_examples_v_compiled_with_tcc() { exec('v -o vtcc -cc tcc cmd/v') if common.is_github_job { exec('./vtcc build-examples') } else { exec('./vtcc -progress build-examples') } } fn build_tetris_autofree() { exec('v -autofree -o tetris examples/tetris/tetris.v') } fn build_blog_autofree() { exec('v -autofree -o blog tutorials/building_a_simple_web_blog_with_veb/code/blog') } fn build_examples_prod() { exec('v -prod examples/news_fetcher.v') } fn v_doctor() { exec('v doctor') } fn build_v_with_prealloc() { exec('v -cg -cstrict -o vstrict1 cmd/v') exec('./vstrict1 -d debug_malloc -d debug_realloc -o vdebug1 cmd/v') exec('./vstrict1 -o vprealloc -prealloc cmd/v') // TODO: fix prealloc on macos (the rwmutex implementation for shared maps there seems to require that mutexes are allocated by C.malloc directly, and segfaults for arbitrary memory addresses) // exec('./vprealloc run examples/hello_world.v') // exec('./vprealloc -o v3 cmd/v') // exec('./v3 -o v4 cmd/v') } fn v_self_compilation_usecache() { $if !enable_usecache_test ? { eprintln('> ${@LOCATION} use `-d enable_usecache_test` in VFLAGS to enable this task') return } exec('v -usecache examples/hello_world.v') exec('./examples/hello_world') exec('v -o v2 -usecache cmd/v') exec('./v2 -o v3 -usecache cmd/v') exec('./v3 version') exec('./v3 -o tetris -usecache examples/tetris/tetris.v') } fn v_self_compilation_parallel_cc() { exec('v -o vp -parallel-cc cmd/v') // exec('./v2 -o v3 -usecache cmd/v') exec('./vp version') exec('./vp -o tetris examples/tetris/tetris.v') } fn test_password_input() { exec('v -silent test examples/password/') } fn test_readline() { exec('v -silent test examples/readline/') } fn test_inline_assembly() { exec('v test vlib/v/slow_tests/assembly') } const all_tasks = { 'test_symlink': Task{test_symlink, 'Test symlink'} 'test_cross_compilation': Task{test_cross_compilation, 'Test cross compilation to Linux'} 'build_with_cstrict': Task{build_with_cstrict, 'Build V with -cstrict'} 'all_code_is_formatted': Task{all_code_is_formatted, 'All code is formatted'} 'run_sanitizers': Task{run_sanitizers, 'Run sanitizers'} 'build_using_v': Task{build_using_v, 'Build V using V'} 'verify_v_test_works': Task{verify_v_test_works, 'Verify `v test` works'} 'install_iconv': Task{install_iconv, 'Install iconv for encoding.iconv'} 'test_pure_v_math_module': Task{test_pure_v_math_module, 'Test pure V math module'} 'self_tests': Task{self_tests, 'Self tests'} 'build_examples': Task{build_examples, 'Build examples'} 'build_tetris_autofree': Task{build_tetris_autofree, 'Build tetris with -autofree'} 'build_blog_autofree': Task{build_blog_autofree, 'Build blog tutorial with -autofree'} 'build_examples_prod': Task{build_examples_prod, 'Build examples with -prod'} 'build_examples_v_compiled_with_tcc': Task{build_examples_v_compiled_with_tcc, 'Build examples with V build with tcc'} 'v_doctor': Task{v_doctor, 'v doctor'} 'build_v_with_prealloc': Task{build_v_with_prealloc, 'Build V with prealloc'} 'v_self_compilation_usecache': Task{v_self_compilation_usecache, 'V self compilation with -usecache'} 'v_self_compilation_parallel_cc': Task{v_self_compilation_parallel_cc, 'V self compilation with -parallel-cc'} 'test_password_input': Task{test_password_input, 'Test password input'} 'test_readline': Task{test_readline, 'Test readline'} 'test_inline_assembly': Task{test_inline_assembly, 'Test inline assembly'} } common.run(all_tasks) ================================================ FILE: ci/openbsd_ci.vsh ================================================ import os import common { Task, exec } fn v_doctor() { println('### vdoctor') dump(os.getenv('PATH')) exec('v doctor') if common.is_github_job { exec('uname -mrs') exec('sysctl hw.model') exec('sysctl hw.ncpu') exec('sysctl hw.physmem') exec('sysctl hw.usermem') exec('whoami') exec('pwd') exec('ls -la') exec('git log -n1') exec('cc --version') } } fn build_v_with_prealloc() { println('### Build v with prealloc') exec('v -cg -cstrict -o vstrict1 cmd/v') exec('./vstrict1 -o vprealloc -prealloc cmd/v') exec('./vprealloc run examples/hello_world.v') exec('./vprealloc -o v3 cmd/v') exec('./v3 -o v4 cmd/v') exec('./v4 -d debug_malloc -d debug_realloc -o vdebug1 cmd/v') } fn verify_v_test_works() { println('### Verify v test') exec('echo \$VFLAGS') exec('v cmd/tools/test_if_v_test_system_works.v') exec('./cmd/tools/test_if_v_test_system_works') } fn build_fast_script() { println('### Build fast script') exec('cd cmd/tools/fast && v fast.v') } fn check_math() { println('### Test vlib/math') exec('v -silent test vlib/math') println('Test the math module, using only the pure V versions,') println(' without the .c.v overrides.') exec('v -silent -exclude @vlib/math/*.c.v test vlib/math') } fn check_compress() { println('### Test vlib/compress') exec('v -silent test vlib/compress') } fn test_inline_assembly() { println('### Test inline Assembly') exec('v test vlib/v/slow_tests/assembly') } fn run_essential_tests() { if common.is_github_job { println('### Run essential tests') exec('VTEST_JUST_ESSENTIAL=1 v -silent test-self') } else { exec('VTEST_JUST_ESSENTIAL=1 v -progress test-self') } } fn build_examples() { if common.is_github_job { println('### Build examples') exec('v -W build-examples') } else { exec('v -progress build-examples') } } const all_tasks = { 'v_doctor': Task{v_doctor, 'Run v doctor'} 'build_v_with_prealloc': Task{build_v_with_prealloc, 'Build V with prealloc'} 'verify_v_test_works': Task{verify_v_test_works, 'Verify that v test works'} 'build_fast_script': Task{build_fast_script, 'Check that building fast.v works'} 'check_math': Task{check_math, 'Check the `math` module works'} 'check_compress': Task{check_compress, 'Check the `compress` module works'} 'test_inline_assembly': Task{test_inline_assembly, 'Test inline Assembly'} 'run_essential_tests': Task{run_essential_tests, 'Run only the essential tests'} 'build_examples': Task{build_examples, 'Build examples'} } common.run(all_tasks) ================================================ FILE: cmd/tools/amalgamate.v ================================================ // amalgamate multiple C source files into a single // C source file. See https://sqlite.org/amalgamation.html // for a description of file amalgamation. // // If an input file is not specified, source is read // from stdin. // // If an output file is not specified, source is output // to stdout. module main import flag import os import regex const app_name = 'amalgamate' const app_version = '0.0.1' // pre-compile the include statement regex const re = regex.regex_opt(r'^\s*#\s*include\s*"([^"]+)"')! struct Config { mut: input_files []string output_file string search_dirs []string blacklist []string } struct Context { config Config mut: processed_files []string } fn parse_arguments() Config { mut cfg := Config{} mut parser := flag.new_flag_parser(os.args) parser.skip_executable() parser.application(app_name) parser.version(app_version) parser.arguments_description('[file ...]') parser.description('combine multiple .c and .h files into one.') parser.description('') parser.description('Combine input, coming from either stdin or input files, into one') parser.description('large file. Include statements are processed and the contents') parser.description('copied in place. Only #include "file.h" statements cause their') parser.description('contents to be copied, not #include statements. If no') parser.description('input files are specified, read from stdin.') parser.footer('\nAn example showing multiple blacklisted files and multiple search') parser.footer('directories.') parser.footer('') parser.footer(' amalgamate -o output_file.c -b ignore_me.h \\') parser.footer(' -b ignore_me_2.h -b other/ignore_me.h \\') parser.footer(' -s relative/search/dir -s /absolute/search/dir \\') parser.footer(' file1.c file2.c') parser.footer('') cfg.output_file = parser.string('output', `o`, '', 'output file. If not specified,\n' + flag.space + 'defaults to stdout.\n', val_desc: '') cfg.blacklist = parser.string_multi('blacklist', `b`, 'blacklist a file name. This prevents\n' + flag.space + 'the named file from being included.\n' + flag.space + 'This can be specified more that once.\n', val_desc: '') cfg.search_dirs = parser.string_multi('search_path', `s`, 'add a directory to the search path.\n' + flag.space + 'An include file is searched for in\n' + flag.space + 'the current working directory and\n' + flag.space + 'if not found, the directories in this\n' + flag.space + 'list are searched, in order, until the\n' + flag.space + 'file is found or the search list is\n' + flag.space + 'exhausted. This can be specified\n' + flag.space + 'more that once.\n', val_desc: '' ) cfg.input_files = parser.finalize() or { // this only reports the first unrecognized argument eprintln('${err}\n') eprintln('${parser.usage()}\n') exit(1) } return cfg } fn main() { cfg := parse_arguments() mut ctx := Context{ config: cfg } ctx.amalgamate() or { eprintln('error: ${err}') exit(1) } } fn (mut c Context) amalgamate() ! { mut source := '' if c.config.input_files.len == 0 { // source += '/* ########## stdin */\n' // if there are no input files, read from stdin local_dir := os.getwd() source += c.handle_includes(local_dir, os.get_raw_lines_joined())! // source += '/* ########## stdin end */\n' } else { // read each input file, in order, and // handle all of its includes. for file in c.config.input_files { if file in c.config.blacklist { // skip blacklisted files continue } found_file := c.find_file(file)! if found_file in c.processed_files { // skip over files already read continue } // source += '/* ########## ${file} */\n' c.processed_files << found_file local_dir := os.dir(found_file) file_source_code := os.read_file(found_file)! source += c.handle_includes(local_dir, file_source_code)! // source += '/* ########## ${file} end */\n' } } if c.config.output_file == '' { print(source) } else { os.write_file(c.config.output_file, source)! } return } fn (c Context) find_file(file string) !string { mut full_path := os.real_path(file) if os.is_file(full_path) { return full_path } for dir in c.config.search_dirs { full_path = os.real_path(os.join_path_single(dir, file)) if os.is_file(full_path) { return full_path } } return error('file "${file}" not found') } // handle_includes looks for lines that start with #include // and inserts the lines from the named include file. // // The pattern matches file names for local header files, // not system header files as are denoted by < and >. fn (mut c Context) handle_includes(local_dir string, input_source string) !string { source_lines := input_source.split_into_lines() mut output_lines := []string{} for line in source_lines { start, _ := re.match_string(line) if start >= 0 { file := line[re.groups[0]..re.groups[1]] mut found_file := '' if file in c.config.blacklist { // leave blacklisted files alone if file in c.processed_files { // we don't want a second include output_lines << '\n' } else { output_lines << line c.processed_files << file } continue } if !os.is_abs_path(file) { found_file = c.find_file(os.join_path_single(local_dir, file)) or { // keep looking '' } } if found_file == '' { found_file = c.find_file(file)! } if found_file in c.processed_files { // skip over files already read continue } c.processed_files << found_file file_source_code := os.read_file(found_file)! // output_lines << '/* ########## ${file} begin */\n' output_lines << c.handle_includes(os.dir(found_file), file_source_code)! // output_lines << '/* ########## ${file} end */\n' } else { output_lines << line } } return output_lines.join_lines() + '\n' } ================================================ FILE: cmd/tools/bench/map_clear.v ================================================ import benchmark fn main() { max_iterations := arguments()[1] or { '1_000_000' }.int() assert max_iterations > 0 mut m := { 123: 456 789: 321 } mut volatile sum := u64(0) mut b := benchmark.start() for i in 0 .. max_iterations { m.clear() m[i] = i * 2 sum += u64(m.len) } assert m.len == 1 b.measure('m.clear(), iterations: ${max_iterations}, sum: ${sum}') } ================================================ FILE: cmd/tools/bench/map_clear_runner.vsh ================================================ #!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp import os const time_fmt = '"CPU: %Us\tReal: %es\tElapsed: %E\tRAM: %MKB\t%C"' const flags = os.getenv('FLAGS') unbuffer_stdout() start := os.args[1] or { '1_000_000' }.int() end := os.args[2] or { '10_000_000' }.int() step := os.args[3] or { '500_000' }.int() os.chdir(os.dir(@VEXE))! vcmd := 'v ${flags} cmd/tools/bench/map_clear.v' println('>> start: ${start} | end: ${end} | step: ${step} | workdir: "${os.getwd()}" | flags: "${flags}" | vcmd: "${vcmd}"') assert os.system(vcmd) == 0 println('running...') for i := start; i <= end; i += step { os.system('/usr/bin/time -f ${time_fmt} cmd/tools/bench/map_clear ${i}') == 0 } ================================================ FILE: cmd/tools/bench/wyhash.v ================================================ module main import hash.fnv1a import hash as wyhash import rand import benchmark fn main() { rand.seed([u32(42), 0]) sample_size := 10000000 min_str_len := 20 max_str_len := 40 println('Generating ${sample_size} strings between ${min_str_len} - ${max_str_len} chars long...') mut checksum := u64(0) mut start_pos := 0 mut bgenerating := benchmark.start() mut bytepile := []u8{} for _ in 0 .. sample_size * max_str_len { bytepile << u8(rand.int_in_range(40, 125) or { 40 }) } mut str_lens := []int{} for _ in 0 .. sample_size { str_lens << rand.int_in_range(min_str_len, max_str_len) or { min_str_len } } bgenerating.measure('generating strings') println('Hashing each of the generated strings...') mut bhashing_1 := benchmark.start() start_pos = 0 checksum = 0 for len in str_lens { end_pos := start_pos + len checksum ^= wyhash.wyhash_c(unsafe { &u8(bytepile.data) + start_pos }, u64(len), 1) start_pos = end_pos } bhashing_1.measure('wyhash.wyhash_c | checksum: ${checksum:22}') mut bhashing_2 := benchmark.start() start_pos = 0 checksum = 0 for len in str_lens { end_pos := start_pos + len checksum ^= wyhash.sum64(bytepile[start_pos..end_pos], 1) start_pos = end_pos } bhashing_2.measure('wyhash.sum64 | checksum: ${checksum:22}') mut bhashing_3 := benchmark.start() start_pos = 0 checksum = 0 for len in str_lens { end_pos := start_pos + len checksum ^= fnv1a.sum64(bytepile[start_pos..end_pos]) start_pos = end_pos } bhashing_3.measure('fnv1a.sum64 | checksum: ${checksum:22}') } ================================================ FILE: cmd/tools/builders/c_builder.v ================================================ module main import v.builder.cbuilder // TODO: change bootstrapping to use the C code generated from // `VEXE=v cmd/tools/builders/c_builder -os cross -o c.c cmd/tools/builders/c_builder.v` // See also `cmd/v/v.v` fn main() { cbuilder.start() } ================================================ FILE: cmd/tools/builders/golang_builder.v ================================================ module main import v.builder.golangbuilder fn main() { golangbuilder.start() } ================================================ FILE: cmd/tools/builders/interpret_builder.v ================================================ module main import v.builder.interpreterbuilder fn main() { interpreterbuilder.start() } ================================================ FILE: cmd/tools/builders/js_builder.v ================================================ module main import v.builder.jsbuilder fn main() { jsbuilder.start() } ================================================ FILE: cmd/tools/builders/native_builder.v ================================================ module main import v.builder.nativebuilder fn main() { nativebuilder.start() } ================================================ FILE: cmd/tools/builders/wasm_builder.v ================================================ module main import v.builder.wasmbuilder fn main() { wasmbuilder.start() } ================================================ FILE: cmd/tools/cc_compilation_failed_non_windows.sh ================================================ #!/bin/sh ## this script is used by the makefiles in the top level folder echo echo 'Compilation of v.c failed.' echo 'See https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Linux-and-macOS .' echo false ================================================ FILE: cmd/tools/cc_compilation_failed_windows.sh ================================================ #!/bin/sh ## this script is used by the makefiles in the top level folder echo echo 'Compilation of v.c failed.' echo 'See https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Windows .' echo false ================================================ FILE: cmd/tools/changelog_helper.v ================================================ module main import os const delete_skipped = true const git_log_cmd = 'git log -n 500 --pretty=format:"%s" --simplify-merges' enum Category { checker breaking improvements parser stdlib web orm db native cgen js_backend comptime tools compiler_internals examples vfmt os_support interpreter } const category_titles = '#### Improvements in the language #### V interpreter #### Breaking changes #### Checker improvements/fixes #### Parser improvements #### Compiler internals #### Standard library #### Web #### ORM #### Database drivers #### Native backend #### C backend #### JavaScript backend #### vfmt #### Tools #### Operating System support #### Examples ' struct Line { category Category text string } const log_txt = 'log.txt' struct App { version string // e.g. "0.4.5" total_lines int mut: result string // resulting CHANGELOG.md counter int } const is_interactive = false // Instantly updates CHANGELOG.md without confirming each line fn no_interactive(version string) { } fn main() { mut version := '' if os.args.len == 2 && os.args[1].starts_with('0.') { version = os.args[1] // no_interactive(version) // return } else { println('Usage: v run tools/changelog_helper.v 0.4.5') return } if !os.exists(log_txt) { os.execute(git_log_cmd + ' > ' + log_txt) println('log.txt generated') // println('log.txt generated, remove unnecessary commits from it and run the tool again') // return } mut lines := os.read_lines(log_txt)! // Trim everything before current version, commit "(tag: 0.4.4) V 0.4.4" mut prev_version := get_prev_version(version) println('prev version=${prev_version}') for i, line in lines { if line == ('V ${prev_version}') { lines = lines[..i].clone() break } } os.write_file(log_txt, lines.join('\n'))! mut app := &App{ total_lines: lines.len } // Write categories at the top first app.result = os.read_file('CHANGELOG.md')!.replace_once('V ${version} TODO', 'V ${version}\n' + category_titles) os.write_file('CHANGELOG.md', app.result)! changelog_txt := os.read_file('CHANGELOG.md')!.to_lower() // mut counter := 0 // to display how many commits are left for line in lines { s := line.trim_space() if s == '' { app.counter++ } } // println('${counter} / ${lines.len}') for line in lines { s := line.to_lower() if line != '' && (changelog_txt.contains(s) || changelog_txt.contains(s.after(':'))) { println('Duplicate: "${line}"') // skip duplicate delete_processed_line_from_log(line)! continue } app.process_line(line.trim_space())! } println('writing changelog.md') if !is_interactive { os.write_file('CHANGELOG.md', app.result)! } println('done.') } fn (mut app App) process_line(text string) ! { if text == '' { return } semicolon_pos := text.index(': ') or { println('no `:` in commit, skipping: "${text}"') return } prefix := text[..semicolon_pos] // Get category based on keywords in the commit message/prefix mut category := Category.examples if text.contains('checker:') { category = .checker } else if is_interpreter(text) { category = .interpreter } else if is_examples(text) { category = .examples // println("Skipping line (example) ${text}") // return } else if is_skip(text) { // Always skip cleanups, typos etc println('Skipping line (cleanup/typo)\n${text}\n') if delete_skipped { delete_processed_line_from_log(text)! } return } else if is_os_support(text) { category = .os_support } else if is_cgen(text) { category = .cgen } else if is_js_backend(text) { category = .js_backend } else if is_comptime(text) { category = .comptime } else if is_db(text) { category = .db } else if is_stdlib(text) { category = .stdlib } else if is_orm(text) { category = .orm } else if is_web(text) { category = .web } else if is_tools(text) { category = .tools } else if is_parser(text) { category = .parser } else if is_internal(text) { category = .compiler_internals } else if is_improvements(text) { category = .improvements } else if is_native(text) { category = .native } else if is_vfmt(text) { category = .vfmt } else if text.contains('docs:') || text.contains('doc:') { // Always skip docs delete_processed_line_from_log(text)! return } else { println('Skipping line (unknown category)\n${text}\n') // if delete_skipped { // delete_processed_line_from_log(text)! //} return } println('process_line: cat=${category} "${text}"') // Trim everything to the left of `:` for some commits (e.g. `checker: `) mut s := text // println("PREFIX='${prefix}'") // if true { // exit(0) //} if (semicolon_pos < 15 && prefix in ['checker', 'cgen', 'orm', 'parser', 'v.parser', 'native', 'ast', 'jsgen', 'v.gen.js', 'fmt', 'vfmt', 'tools', 'examples', 'eval']) || (semicolon_pos < 30 && prefix.contains(', ')) { s = '- ' + text[semicolon_pos + 2..].capitalize() } if is_interactive { // Get input from the user print('\033[H\033[J') println('${app.counter} / ${app.total_lines}') // println('\n') println(text) input := os.input('${category}? ') println("INPUT='${input}'") match input { '' { println('GOT ENTER') line := Line{category, s} save_line_interactive(line)! } 'n', '0', 'no' { // Ignore commit println('ignored.') } 's', 'skip' { // Skip println('skipped.') return } 'c', 'change' { // Change category for { print_category_hint() custom_category := os.input('${category} ?').int() if custom_category == 0 { println('wrong category') } else { unsafe { line := Line{Category(custom_category - 1), s} save_line_interactive(line)! } break } } } else {} } app.counter++ } else { line := Line{category, s} app.save_line(line)! } // Don't forget to remove the line we just processed from log.txt delete_processed_line_from_log(text)! } fn (mut app App) save_line(line Line) ! { // println('save line ${line}') app.result = line.write_at_category(app.result) or { return error('') } } fn save_line_interactive(line Line) ! { println('save line interactive ${line}') mut txt := os.read_file('CHANGELOG.md')! txt = line.write_at_category(txt) or { return error('') } os.write_file('CHANGELOG.md', txt)! } const category_map = { Category.checker: '#### Checker improvements' .breaking: '#### Breaking changes' .improvements: '#### Improvements in the' .interpreter: '#### V interpreter' .parser: '#### Parser improvements' .stdlib: '#### Standard library' .web: '#### Web' .orm: '#### ORM' .db: '#### Database drivers' .native: '#### Native backend' .cgen: '#### C backend' .js_backend: '#### JavaScript backend' .comptime: '#### Comptime' .tools: '#### Tools' .compiler_internals: '#### Compiler internals' .examples: '#### Examples' .vfmt: '#### vfmt' .os_support: '#### Operating System' } fn (l Line) write_at_category(txt string) ?string { title := category_map[l.category] title_pos := txt.index(title)? // Find the position of the ### category title pos := txt.index_after('\n', title_pos + 1) or { return none } first_half := txt[..pos] second_half := txt[pos..] if txt.contains(l.text) { // Avoid duplicates (just in case) println("Got a duplicate: '${txt}'") return txt } // Now insert the line in the middle, under the ### category title mut line_text := l.text // Trim "prefix:" for some categories // mut capitalized := false mut has_prefix := true if l.category in [.cgen, .checker, .improvements, .native, .orm, .interpreter] { has_prefix = false if semicolon_pos := line_text.index(': ') { prefix := line_text[..semicolon_pos] println("PREFIX='${prefix}'") if semicolon_pos < 15 { line_text = line_text[semicolon_pos + 2..].capitalize() // capitalized = true } } } if !has_prefix { line_text = line_text.capitalize() } if !line_text.starts_with('- ') { line_text = '- ' + line_text } return first_half + '\n' + line_text + second_half } fn delete_processed_line_from_log(line string) ! { text := os.read_file(log_txt)! new_text := text.replace_once(line, '') os.write_file(log_txt, new_text)! } const db_strings = [ 'db:', 'db.sqlite', 'db.mysql', 'db.pg', 'db.redis', 'pg:', 'mysql:', ] const parser_strings = [ 'parser:', 'ast:', ] const stdlib_strings = [ 'gg:', 'json:', 'json2:', 'time:', 'sync:', 'datatypes:', 'math:', 'math.', 'math.big', 'crypto', 'sokol', 'os:', 'rand:', 'rand.', 'math:', 'toml:', 'vlib:', 'arrays:', 'os.', 'term:', 'sync.', 'builtin:', 'builtin,', 'builtin.', 'strconv', 'readline', 'cli:', 'eventbus:', 'encoding.', 'bitfield:', 'io:', 'io.', 'log:', 'flag:', 'regex:', 'regex.', 'tmpl:', 'hash:', 'stbi:', 'atomic:', 'context:', 'thirdparty', ] fn is_stdlib(text string) bool { return is_xxx(text, stdlib_strings) } fn is_db(text string) bool { return is_xxx(text, db_strings) } const orm_strings = [ 'orm:', ] fn is_orm(text string) bool { return is_xxx(text, orm_strings) } const cgen_strings = [ 'cgen:', 'cgen,', 'v.gen.c:', ] fn is_cgen(text string) bool { return is_xxx(text, cgen_strings) } const js_backend_strings = [ 'js:', 'v.gen.js:', 'jsgen:', ] fn is_js_backend(text string) bool { return is_xxx(text, js_backend_strings) } const internal_strings = [ 'scanner:', 'transformer:', 'markused:', 'builder:', 'pref:', 'v.util', 'v.generic', 'v.comptime', 'table:', ] fn is_internal(text string) bool { return is_xxx(text, internal_strings) } const improvements_strings = [ 'all:', 'v:', 'coroutines:', 'autofree', ] fn is_improvements(text string) bool { return is_xxx(text, improvements_strings) } const examples_strings = [ 'example', ] const skip_strings = [ 'tests', 'readme:', '.md:', 'typos', ' typo', 'cleanup', 'clean up', 'build(deps)', 'FUNDING', ] fn is_examples(text string) bool { return is_xxx(text, examples_strings) } fn is_skip(text string) bool { return is_xxx(text, skip_strings) } const tools_strings = [ 'tools:', 'vpm:', 'ci:', 'github:', 'gitignore', 'benchmark', 'v.help:', 'vtest', 'repl', 'REPL', 'vet', 'tools.', 'GNUmakefile', 'Dockerfile', 'vcomplete', 'vwatch', 'changelog', ] fn is_tools(text string) bool { return is_xxx(text, tools_strings) } fn is_parser(text string) bool { return is_xxx(text, parser_strings) } const web_strings = [ 'vweb', 'veb', 'x.vweb', 'websocket:', 'pico', 'x.sessions', 'picoev:', 'mbedtls', 'net:', 'net.', 'wasm:', 'http:', ] fn is_web(text string) bool { return is_xxx(text, web_strings) } const native_strings = [ 'native:', ] fn is_native(text string) bool { return is_xxx(text, native_strings) } const vfmt_strings = [ 'vfmt:', 'fmt:', ] fn is_vfmt(text string) bool { return is_xxx(text, vfmt_strings) } const os_support_strings = [ 'FreeBSD', 'freebsd', 'OpenBSD', 'openbsd', 'macOS', 'macos', 'Windows', 'windows', 'Linux', 'linux', 'msvc:', ] fn is_os_support(text string) bool { return is_xxx(text, os_support_strings) } fn is_comptime(text string) bool { return text.contains('comptime:') } fn is_interpreter(text string) bool { return text.starts_with('eval:') } fn is_xxx(text string, words []string) bool { for s in words { if text.contains(s) { return true } } return false } fn print_category_hint() { $for val in Category.values { println('${int(val.value) + 1} - ${val.name}; ') } } // For 0.4.12 returns 0.4.11 etc fn get_prev_version(version string) string { parts := version.split('.') if parts.len != 3 { return '' } major := parts[0] minor := parts[1] patch := parts[2].int() return '${major}.${minor}.${patch - 1}' } ================================================ FILE: cmd/tools/check_os_api_parity.v ================================================ module main import os import v.util import v.util.diff import v.pref import v.builder import v.builder.cbuilder import v.ast import term const base_os = pref.get_host_os() const os_list = [pref.OS.linux, .macos, .windows, .freebsd, .openbsd, .solaris, .termux] const skip_modules = [ 'builtin.bare', 'builtin.linux_bare.old', 'builtin.js', 'builtin.wasm', 'strconv', 'strconv.ftoa', 'hash', 'strings', 'crypto.rand', 'os.bare', 'os2', 'szip', 'v.eval', ] const is_verbose = os.getenv('VERBOSE') != '' fn main() { vexe := os.real_path(os.getenv_opt('VEXE') or { @VEXE }) vroot := os.dir(vexe) util.set_vroot_folder(vroot) os.chdir(vroot)! modules := if os.args.len > 1 { os.args[1..] } else { all_vlib_modules() } mut diff_modules := map[string]bool{} other_os_list := os_list.filter(it != base_os) for m in modules { if !is_verbose { eprintln('Checking module: ${m} ...') } api_base := gen_api_for_module_in_os(m, base_os) for other_os in other_os_list { api_os := gen_api_for_module_in_os(m, other_os) if api_base == api_os { continue } diff_modules[m] = true summary := 'Different APIs found for module: `${m}`, between OS base: `${base_os}` and OS: `${other_os}`' eprintln(term.header(summary, '-')) diff_ := diff.compare_text(api_base, api_os) or { continue } println(diff_) eprintln(term.h_divider('-')) } } if diff_modules.len > 0 { eprintln(term.header('Found ${diff_modules.len} modules with different APIs', '=')) for m in diff_modules.keys() { eprintln('Module: ${m}') } exit(1) } } fn all_vlib_modules() []string { mut vlib_v_files := os.walk_ext('vlib', '.v') mut vmodulesmap := map[string]int{} for f in vlib_v_files { if f.contains('/tests/') || f.ends_with('_test.v') { continue } vmodulename := os.dir(f).replace('/', '.').replace('vlib.', '') if vmodulename in skip_modules { continue } vmodulesmap[vmodulename] = vmodulesmap[vmodulename] + 1 } mut modules := vmodulesmap.keys() modules.sort() return modules } fn gen_api_for_module_in_os(mod_name string, os_ pref.OS) string { if is_verbose { eprintln('Checking module: ${mod_name:-30} for OS: ${os_:-10} ...') } os_name := os_.str().to_lower() mpath := os.join_path('vlib', mod_name.replace('.', '/')) tmpname := '/tmp/${mod_name}_${os_name}.c' prefs, _ := pref.parse_args([], ['-os', os_name, '-o', tmpname, '-shared', mpath]) mut b := builder.new_builder(prefs) cbuilder.compile_c(mut b) mut res := []string{} for f in b.parsed_files { for s in f.stmts { if s is ast.FnDecl && s.is_pub { fn_mod := s.modname() if fn_mod == mod_name { fn_signature := b.table.stringify_fn_decl(&s, mod_name, map[string]string{}, false) fline := '${fn_mod}: ${fn_signature}' res << fline } } } } res.sort() return res.join('\n') } ================================================ FILE: cmd/tools/check_retry.vsh ================================================ #!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp // This script is used by cmd/tools/vretry_test.v, to check that the `v retry` // subcommand works as expected, without relying on external commands like // `git`, or on non portable ones like `true`/`false` or `echo`. fn main() { args := arguments()#[1..] println(args) if args == ['too', 'many', 'arguments'] { exit(1) } } ================================================ FILE: cmd/tools/detect_tcc.v ================================================ fn main() { $if tinyc { println('Your `tcc` is working. Good - it is much faster at compiling C source code.') exit(0) } $if !macos { println(' Note: `tcc` was not used, so unless you install it yourself, your backend C compiler will be `cc`, which is usually either `clang`, `gcc` or `msvc`. These C compilers, are several times slower at compiling C source code, compared to `tcc`. They do produce more optimised executables, but that is done at the cost of compilation speed. ') } } ================================================ FILE: cmd/tools/find_doc_comments_with_no_dots.v ================================================ import os fn main() { args := arguments() if args.len < 2 { println('Usage: v run doc_comment_checker.v ...') return } mut fpaths := []string{} for filepath in args[1..] { if os.is_file(filepath) { fpaths << filepath } if os.is_dir(filepath) { fpaths << os.walk_ext(filepath, '.v').filter(!it.ends_with('_test.v') && !it.ends_with('_test.c.v')) } } fpaths.sort() mut ctx := Context{} for filepath in fpaths { ctx.process_fpath(filepath) or { eprintln('error with ${filepath}: ${err}') continue } } println('> Processed ${fpaths.len} .v files, found errors: ${ctx.errors} , in ${ctx.pub_symbols} `pub` declarations, and ${ctx.pub_comment_lines} pub comment lines.') if ctx.errors > 0 { exit(1) } } struct Context { mut: errors int pub_symbols int pub_comment_lines int comments int } fn (mut ctx Context) process_fpath(filepath string) ! { lines := os.read_lines(filepath)! mut prev := 0 for iline, line in lines { if line.starts_with('pub ') { ctx.pub_symbols++ mut comments := []CommentLine{} mut i := 0 for i = int_max(0, iline - 1); i >= prev; i-- { pline := lines[i] if pline.starts_with('// ') { comments << CommentLine{pline, i + 1} } else { prev = iline + 1 break } } if comments.len > 0 { cline := comments.last() fword := cline.comment.all_after('// ').all_before(' ') if !line.contains(fword) { continue } ctx.pub_comment_lines += comments.len if !cline.comment.ends_with('.') { println('${filepath}:${cline.line}: ${cline.comment}') ctx.errors++ } } } } } struct CommentLine { comment string line int } ================================================ FILE: cmd/tools/fuzz/fuzz.sh ================================================ #!/bin/sh cores=$(nproc --all) echo Number of cores: $cores echo Compiling... ./v -cc clang -o cmd/tools/fuzz/map_fuzz cmd/tools/fuzz/map_fuzz.v -prod -cflags "-fsanitize=memory" echo Fuzzing: while true do for ((i=1;i<=cores;++i)) do sleep 0.001 ./cmd/tools/fuzz/map_fuzz & done wait done ================================================ FILE: cmd/tools/fuzz/fuzz_v_parser_with_radamsa.sh ================================================ #!/usr/bin/env bash ## Note: radamsa is a fuzzer, available from https://gitlab.com/akihe/radamsa export VFUZZER=true export OUTPUT_FILE=${1:-x.v} export PARSER_EXECUTABLE=${2:-cmd/tools/measure/parser_speed} echo "Fuzzing parameters | OUTPUT FILE: ${OUTPUT_FILE} | PARSER_EXECUTABLE: ${PARSER_EXECUTABLE}" if [ ! -f $PARSER_EXECUTABLE ]; then v -g -o "${PARSER_EXECUTABLE}" cmd/tools/measure/parser_speed.v fi while true; do radamsa --meta "${OUTPUT_FILE}.autofuzz.log" examples/hello_world.v > "${OUTPUT_FILE}"; echo -ne "OFILE: ${OUTPUT_FILE}"; ./"${PARSER_EXECUTABLE}" ${OUTPUT_FILE} || break; done ================================================ FILE: cmd/tools/fuzz/map_fuzz.v ================================================ import rand import time fn generate_strings(str_len int, arr_len int) []string { mut arr := []string{len: arr_len} for i in 0 .. arr_len { arr[i] = rand.string(str_len) } return arr } fn fuzz1() { amount := 200000 - rand.intn(100000) or { 0 } amount2 := 200000 - rand.intn(100000) or { 0 } len := 25 - rand.intn(10) or { 0 } arr := generate_strings(len, amount) arr2 := generate_strings(len, amount2) mut m := map[string]int{} for i in 0 .. amount { m[arr[i]] = i assert i == m[arr[i]] } for i in 0 .. amount { assert i == m[arr[i]] } for i in 0 .. amount2 { assert 0 == m[arr2[i]] } unsafe { m.free() arr.free() } } fn fuzz2() { mut m := map[string]int{} amount := rand.intn(500000) or { 0 } + 1 len := 25 - rand.intn(10) or { 0 } arr := generate_strings(len, amount) for i, x in arr { m[x] = i } mut i := 0 for key, val in m { assert key == arr[i] assert val == i i++ } unsafe { m.free() arr.free() } } fn fuzz3() { mut m := map[string]int{} amount := rand.intn(500000) or { 0 } + 1 len := 25 - rand.intn(10) or { 0 } arr := generate_strings(len, amount) for i, x in arr { if (i % 10000) == 0 { keys := m.keys() assert keys.len == i assert keys == arr[0..i] } m[x] = i } assert m.keys() == arr assert m.keys().len == amount unsafe { m.free() arr.free() } } fn fuzz4() { amount := rand.intn(500000) or { 0 } len := 25 - rand.intn(10) or { 0 } arr := generate_strings(len, amount) mut m := map[string]int{} for i in 0 .. amount { m[arr[i]] = i } for i in 0 .. amount { m.delete(arr[i]) assert m[arr[i]] == 0 } assert m.len == 0 unsafe { m.free() arr.free() } } fn fuzz5() { amount := rand.intn(500000) or { 0 } + 1 arr := generate_strings(20, amount) mut m := map[string]int{} for i in 0 .. amount { m[arr[i]] = i assert (arr[i] in m) == true } for i in 0 .. amount { m.delete(arr[i]) assert (arr[i] !in m) == true assert m.len == amount - i - 1 } assert m.len == 0 unsafe { m.free() arr.free() } } fn fuzz6() { mut m := map[string]int{} amount := rand.intn(500000) or { 0 } + 1 len := 25 - rand.intn(10) or { 0 } arr := generate_strings(len, amount) for i, x in arr { m[x]++ m[x] += i assert m[x] == i + 1 } for i, x in arr { assert m[x] == i + 1 } unsafe { m.free() arr.free() } } fn main() { seed := u32(time.ticks()) println('seed: ${seed.hex()}') rand.seed([seed, seed]) fuzz1() fuzz2() fuzz3() fuzz4() fuzz5() fuzz6() } ================================================ FILE: cmd/tools/gen1m.v ================================================ fn main() { for i in 0 .. 100000 { println(' fn foo${i}() { x := ${i} mut a := 1 + x a += 2 print(a) a = 0 a = 1 } ') } // println('fn main() {foo1()} ') println('fn main() { println("1m DONE") } ') } ================================================ FILE: cmd/tools/gen_vc.v ================================================ module main import os import log import flag import time import veb import net.urllib // This tool regenerates V's bootstrap .c files // every time the V master branch is updated. // if run with the --serve flag it will run in webhook // server mode awaiting a request to http://host:port/genhook // available command line flags: // --work-dir gen_vc's working directory // --purge force purge the local repositories // --serve run in webhook server mode // --port port for http server to listen on // --log-to either 'file' or 'terminal' // --log-file path to log file used when --log-to is 'file' // --dry-run dont push anything to remote repo // --force force update even if already up to date // git credentials const git_username = os.getenv('GITUSER') const git_password = os.getenv('GITPASS') // repository // git repo const git_repo_v = 'github.com/vlang/v' const git_repo_vc = 'github.com/vlang/vc' // local repo directories const git_repo_dir_v = 'v' const git_repo_dir_vc = 'vc' // gen_vc // name const app_name = 'gen_vc' // version const app_version = '0.1.3' // description const app_description = "This tool regenerates V's bootstrap .c files every time the V master branch is updated." // assume something went wrong if file size less than this const too_short_file_limit = 5000 // create a .c file for these os's const vc_build_oses = [ 'nix', // all nix based os 'windows', ] // default options (overridden by flags) // gen_vc working directory const work_dir = '/tmp/gen_vc' // dont push anything to remote repo const dry_run = false // server port const server_port = 7171 // log file const log_file = '${work_dir}/log.txt' // log_to is either 'file' or 'terminal' const log_to = 'terminal' // errors const err_msg_build = 'error building' const err_msg_make = 'make failed' const err_msg_gen_c = 'failed to generate .c file' const err_msg_cmd_x = 'error running cmd' struct GenVC { // logger // flag options options FlagOptions mut: logger &log.Log = unsafe { nil } // true if error was experienced running generate gen_error bool } // webhook server struct WebhookServer { mut: gen_vc &GenVC = unsafe { nil } // initialized in init_server } struct Context { veb.Context } // storage for flag options struct FlagOptions { work_dir string purge bool serve bool port int log_to string log_file string dry_run bool force bool } fn main() { log.use_stdout() mut fp := flag.new_flag_parser(os.args.clone()) fp.application(app_name) fp.version(app_version) fp.description(app_description) fp.skip_executable() show_help := fp.bool('help', 0, false, 'Show this help screen\n') flag_options := parse_flags(mut fp) if show_help { println(fp.usage()) exit(0) } fp.finalize() or { eprintln(err) println(fp.usage()) return } // webhook server mode if flag_options.serve { mut server := &WebhookServer{} veb.run_at[WebhookServer, Context](mut server, port: flag_options.port)! } else { // cmd mode mut gen_vc := new_gen_vc(flag_options) gen_vc.init() gen_vc.generate() } } // new GenVC fn new_gen_vc(flag_options FlagOptions) &GenVC { mut logger := &log.Log{} logger.set_level(.debug) if flag_options.log_to == 'file' { logger.set_full_logpath(flag_options.log_file) } return &GenVC{ options: flag_options logger: logger } } // WebhookServer init pub fn (mut ws WebhookServer) init_server() { mut fp := flag.new_flag_parser(os.args.clone()) flag_options := parse_flags(mut fp) ws.gen_vc = new_gen_vc(flag_options) ws.gen_vc.init() // ws.gen_vc = new_gen_vc(flag_options) } pub fn (mut ws WebhookServer) index() { eprintln('WebhookServer.index() called') } // gen webhook pub fn (mut ws WebhookServer) genhook() veb.Result { // request data // println(ws.vweb.req.data) // TODO: parse request. json or urlencoded // json.decode or net.urllib.parse ws.gen_vc.generate() // error in generate if ws.gen_vc.gen_error { return ctx.json('{status: "failed"}') } return ctx.json('{status: "ok"}') } pub fn (ws &WebhookServer) reset() { } // parse flags to FlagOptions struct fn parse_flags(mut fp flag.FlagParser) FlagOptions { return FlagOptions{ serve: fp.bool('serve', 0, false, 'run in webhook server mode') work_dir: fp.string('work-dir', 0, work_dir, 'gen_vc working directory') purge: fp.bool('purge', 0, false, 'force purge the local repositories') port: fp.int('port', 0, server_port, 'port for web server to listen on') log_to: fp.string('log-to', 0, log_to, "log to is 'file' or 'terminal'") log_file: fp.string('log-file', 0, log_file, "log file to use when log-to is 'file'") dry_run: fp.bool('dry-run', 0, dry_run, 'when specified dont push anything to remote repo') force: fp.bool('force', 0, false, 'force update even if already up to date') } } fn (mut gen_vc GenVC) init() { // purge repos if flag is passed if gen_vc.options.purge { gen_vc.purge_repos() } } // regenerate fn (mut gen_vc GenVC) generate() { // set errors to false gen_vc.gen_error = false // check if gen_vc dir exists if !os.is_dir(gen_vc.options.work_dir) { // try create os.mkdir(gen_vc.options.work_dir) or { panic(err) } // still doesn't exist... we have a problem if !os.is_dir(gen_vc.options.work_dir) { gen_vc.logger.error('error creating directory: ${gen_vc.options.work_dir}') gen_vc.gen_error = true return } } // cd to gen_vc dir os.chdir(gen_vc.options.work_dir) or {} // if we are not running with the --serve flag (webhook server) // rather than deleting and re-downloading the repo each time // first check to see if the local v repo is behind master // if it isn't behind there's no point continuing further if !gen_vc.options.serve && os.is_dir(git_repo_dir_v) { gen_vc.cmd_exec('git -C ${git_repo_dir_v} checkout master') // fetch the remote repo just in case there are newer commits there gen_vc.cmd_exec('git -C ${git_repo_dir_v} fetch') git_status := gen_vc.cmd_exec('git -C ${git_repo_dir_v} status') if !git_status.contains('behind') && !gen_vc.options.force { gen_vc.logger.warn('v repository is already up to date.') return } } // delete repos gen_vc.purge_repos() // clone repos gen_vc.cmd_exec('git clone --filter=blob:none https://${git_repo_v} ${git_repo_dir_v}') gen_vc.cmd_exec('git clone --filter=blob:none https://${git_repo_vc} ${git_repo_dir_vc}') // get output of git log -1 (last commit) git_log_v := gen_vc.cmd_exec('git -C ${git_repo_dir_v} log -1 --format="commit %H%nDate: %ci%nDate Unix: %ct%nSubject: %s"') git_log_vc := gen_vc.cmd_exec('git -C ${git_repo_dir_vc} log -1 --format="Commit %H%nDate: %ci%nDate Unix: %ct%nSubject: %s"') // date of last commit in each repo ts_v := git_log_v.find_between('Date:', '\n').trim_space() ts_vc := git_log_vc.find_between('Date:', '\n').trim_space() // parse time as string to time.Time last_commit_time_v := time.parse(ts_v) or { panic(err) } last_commit_time_vc := time.parse(ts_vc) or { panic(err) } // git dates are in users local timezone and v time.parse does not parse // timezones at the moment, so for now get unix timestamp from output also t_unix_v := git_log_v.find_between('Date Unix:', '\n').trim_space().int() t_unix_vc := git_log_vc.find_between('Date Unix:', '\n').trim_space().int() // last commit hash in v repo last_commit_hash_v := git_log_v.find_between('commit', '\n').trim_space() last_commit_hash_v_short := last_commit_hash_v[..7] // subject last_commit_subject := git_log_v.find_between('Subject:', '\n').trim_space().replace("'", '"') // log some info gen_vc.logger.debug('last commit time (${git_repo_v}): ' + last_commit_time_v.format_ss()) gen_vc.logger.debug('last commit time (${git_repo_vc}): ' + last_commit_time_vc.format_ss()) gen_vc.logger.debug('last commit hash (${git_repo_v}): ${last_commit_hash_v}') gen_vc.logger.debug('last commit subject (${git_repo_v}): ${last_commit_subject}') // if vc repo already has a newer commit than the v repo, assume it's up to date if t_unix_vc >= t_unix_v && !gen_vc.options.force { gen_vc.logger.warn('vc repository is already up to date.') return } // try build v for current os (linux in this case) gen_vc.cmd_exec('make -C ${git_repo_dir_v}') v_exec := '${git_repo_dir_v}/v' // check if make was successful gen_vc.assert_file_exists_and_is_not_too_short(v_exec, err_msg_make) // build v.c for each os for os_name in vc_build_oses { c_file := if os_name == 'nix' { 'v.c' } else { 'v_win.c' } v_flags := if os_name == 'nix' { '-os cross' } else { '-os ${os_name}' } // try generate .c file gen_vc.cmd_exec('${v_exec} ${v_flags} -o ${c_file} ${git_repo_dir_v}/cmd/v') // check if the c file seems ok gen_vc.assert_file_exists_and_is_not_too_short(c_file, err_msg_gen_c) // embed the latest v commit hash into the c file gen_vc.cmd_exec('sed -i \'1s/^/#define V_COMMIT_HASH "${last_commit_hash_v_short}"\\n/\' ${c_file}') // move to vc repo gen_vc.cmd_exec('mv ${c_file} ${git_repo_dir_vc}/${c_file}') // add new .c file to local vc repo gen_vc.cmd_exec('git -C ${git_repo_dir_vc} add ${c_file}') } // check if the vc repo actually changed git_status := gen_vc.cmd_exec('git -C ${git_repo_dir_vc} status') if git_status.contains('nothing to commit') { gen_vc.logger.error('no changes to vc repo: something went wrong.') gen_vc.gen_error = true } // commit changes to local vc repo gen_vc.cmd_exec_safe("git -C ${git_repo_dir_vc} commit -m '[v:master] ${last_commit_hash_v_short} - ${last_commit_subject}'") // push changes to remote vc repo gen_vc.cmd_exec_safe('git -C ${git_repo_dir_vc} push https://${urllib.query_escape(git_username)}:${urllib.query_escape(git_password)}@${git_repo_vc} master') } // only execute when dry_run option is false, otherwise just log fn (mut gen_vc GenVC) cmd_exec_safe(cmd string) string { return gen_vc.command_execute(cmd, gen_vc.options.dry_run) } // always execute command fn (mut gen_vc GenVC) cmd_exec(cmd string) string { return gen_vc.command_execute(cmd, false) } // execute command fn (mut gen_vc GenVC) command_execute(cmd string, dry bool) string { // if dry is true then dont execute, just log if dry { return gen_vc.command_execute_dry(cmd) } gen_vc.logger.info('cmd: ${cmd}') r := os.execute(cmd) if r.exit_code < 0 { gen_vc.logger.error('${err_msg_cmd_x}: "${cmd}" could not start.') gen_vc.logger.error(r.output) // something went wrong, better start fresh next time gen_vc.purge_repos() gen_vc.gen_error = true return '' } if r.exit_code != 0 { gen_vc.logger.error('${err_msg_cmd_x}: "${cmd}" failed.') gen_vc.logger.error(r.output) // something went wrong, better start fresh next time gen_vc.purge_repos() gen_vc.gen_error = true return '' } return r.output } // just log cmd, dont execute fn (mut gen_vc GenVC) command_execute_dry(cmd string) string { gen_vc.logger.info('cmd (dry): "${cmd}"') return '' } // delete repo directories fn (mut gen_vc GenVC) purge_repos() { // delete old repos (better to be fully explicit here, since these are destructive operations) mut repo_dir := '${gen_vc.options.work_dir}/${git_repo_dir_v}' if os.is_dir(repo_dir) { gen_vc.logger.info('purging local repo: "${repo_dir}"') gen_vc.cmd_exec('rm -rf ${repo_dir}') } repo_dir = '${gen_vc.options.work_dir}/${git_repo_dir_vc}' if os.is_dir(repo_dir) { gen_vc.logger.info('purging local repo: "${repo_dir}"') gen_vc.cmd_exec('rm -rf ${repo_dir}') } } // check if file size is too short fn (mut gen_vc GenVC) assert_file_exists_and_is_not_too_short(f string, emsg string) { if !os.exists(f) { gen_vc.logger.error('${err_msg_build}: ${emsg} .') gen_vc.gen_error = true return } fsize := os.file_size(f) if fsize < too_short_file_limit { gen_vc.logger.error('${err_msg_build}: ${f} exists, but is too short: only ${fsize} bytes.') gen_vc.gen_error = true return } } ================================================ FILE: cmd/tools/gg_split_memdump_to_frames.vsh ================================================ #!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp module main import os import log fn write_chunk(n int, min_size int, original string, start int, end int) { size := end - start if size < min_size { return } frame_file := 'frame_${n:06}.bin' log.warn('writing ${frame_file}, from start: ${start:9}, to end: ${end:9} | size: ${size:9} >= ${min_size:9}, memuse: ${gc_memory_use()}') os.write_file(frame_file, original#[start..end]) or { log.error(err.str()) } } fn main() { log.info('Start.') fpath := os.args[2] or { 'memdump.bin' } separator := os.args[3] or { '@@ gg_memory_trace_frame' } min_size := os.args[1] or { '${separator.len}' }.int() log.info('Splitting chunk min_size (arg 1): ${min_size}, file (arg 2): ${fpath}, by string separator (arg 3): `${separator}` ...') log.info('Memory use before reading: ${gc_memory_use()}') original := os.read_file(fpath)! log.info('file size: ${original.len}') log.info('Memory use after reading: ${gc_memory_use()}') mut n := 0 for start := 0; start < original.len; { gc_collect() idx := original.index_after_(separator, start + separator.len) // ensure that we advance each time if idx < 0 { write_chunk(n, min_size, original, start, original.len) break } write_chunk(n, min_size, original, start, idx) start = idx n++ } log.info('Memory use after processing: ${gc_memory_use()}') log.info('Done.') } ================================================ FILE: cmd/tools/git_pre_commit_hook.vsh ================================================ #!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp import os import term // This script can be used to ensure that all committed V files are vfmt-ed automatically. // By default, once setup, it will run `v fmt -w` on them, before committing them. // To use the script in your V project, you need to be in the main folder // of your project, then do the equivalent of: // ```sh // cp /PATH/TO_YOUR/V/cmd/tools/git_pre_commit_hook.vsh .git/hooks/pre-commit // chmod 755 .git/hooks/pre-commit // ``` // // You could also use `vgit-fmt-hook` tool to install/update/remove and get // status for this hook. // This tool copies the git hook VSH script in .git/hooks/pre-commit // // Note: you can use this command: // `git config --bool --add hooks.stopCommitOfNonVfmtedVFiles true` // ... to make it just *prevent* the committing of unformatted .v files, // i.e. stop the committing, if they are not, but *without modifying them* // automatically (you will then need to run `v fmt -w` on them manually). // // Note 2: Git supports skipping the hooks, by passing the `--no-verify` option. // That can be used to commit some .v files that are not formatted, without removing // the hook. fn main() { // This hook cares only about the changed V files, that will be committed, as reported by git itself: changed := os.execute('git diff --cached --name-only --diff-filter=ACMR -- "*.v" "*.vsh" "*.vv"') all_changed_vfiles := changed.output.trim_space().split('\n') // _input.vv files are NOT formatted on purpose. // There is no point in verifying them, or ruining them over with `v fmt -w`. // Just filter them out, but still report to the user, that they will not be formatted: vfiles := all_changed_vfiles.filter(!it.ends_with('_input.vv')) input_vfiles := all_changed_vfiles.filter(it.ends_with('_input.vv')) if input_vfiles.len > 0 { eprintln('>>> ${input_vfiles.len} `_input.vv` files found, that *will NOT be* formatted.') for ifile in input_vfiles { eprintln(' ${ifile}') } } if changed.output == '' || vfiles.len == 0 { eprintln('>>> 0 changed V files, that may need formatting found.') exit(0) } configured_stop_committing := os.execute('git config --bool hooks.stopCommitOfNonVfmtedVFiles') if configured_stop_committing.output.trim_space().bool() { verify_result := os.execute('${os.quoted_path(@VEXE)} fmt -verify ${vfiles.join(' ')}') if verify_result.exit_code != 0 { eprintln(verify_result.output) } exit(verify_result.exit_code) } else { eprintln('The V pre commit hook will format ${vfiles.len} V file(s):') // vfmt off for vfile in vfiles { eprintln(' ${term.bold('${vfile}')}') } // vfmt on all_vfiles_on_a_line := vfiles.map(os.quoted_path(it)).join(' ') os.system('${os.quoted_path(@VEXE)} fmt -w ${all_vfiles_on_a_line}') os.system('git add ${all_vfiles_on_a_line}') } } ================================================ FILE: cmd/tools/install_binaryen.vsh ================================================ #!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp import os import net.http const github_job = os.getenv('GITHUB_JOB') struct JQ { tag_name string } fn main() { root := os.real_path(os.dir(os.getenv_opt('VEXE') or { @VEXE })) os.chdir(root)! // make sure that the workfolder is stable tloc := os.join_path(root, 'thirdparty') loc := os.join_path(tloc, 'binaryen') if os.exists(loc) { eprintln('thirdparty/binaryen exists, will not overwrite') eprintln('delete the folder, and execute again') exit(1) } /* // TODO: add retries here, github requests can fail jq := http.get_text('https://api.github.com/repos/WebAssembly/binaryen/releases/latest') tag := json.decode(JQ, jq)!.tag_name if github_job != '' { dump(jq) dump(tag) } */ tag := 'version_112' name := $if windows { 'x86_64-windows' } $else $if macos { $if arm64 { 'arm64-macos' } $else { 'x86_64-macos' } } $else $if linux { 'x86_64-linux' } $else { eprintln('A premade binary library is not available for your system.') eprintln('Build it from source, following the documentation here: https://github.com/WebAssembly/binaryen/#building') exit(1) } fname := 'binaryen-${tag}' url := 'https://github.com/WebAssembly/binaryen/releases/download/${tag}/${fname}-${name}.tar.gz' saveloc := os.join_path(tloc, '${fname}.tar.gz') if !os.exists(saveloc) { println('Downloading archive: ${saveloc}, from url: ${url} ...') http.download_file(url, saveloc)! // defer { os.rm(saveloc) or {}! } } println('Extracting `${tloc}/${fname}` to `${tloc}/binaryen` ...') cmd := 'tar -xvf ${saveloc} --directory ${tloc}' if os.system(cmd) != 0 { eprintln('`${cmd}` exited with a non zero exit code') exit(1) } println(cmd) println('Moving `${tloc}/${fname}` to `${tloc}/binaryen` ...') os.rename_dir('${tloc}/${fname}', loc)! println('Done. You can now use `v -b wasm file.v` .') } ================================================ FILE: cmd/tools/install_wabt.vsh ================================================ #!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp import os import net.http fn main() { os.chdir(@VEXEROOT)! // make sure that the workfolder is stable tloc := os.join_path(@VEXEROOT, 'thirdparty') loc := os.join_path(tloc, 'wabt') if os.exists(loc) { eprintln('thirdparty/wabt exists, will not overwrite') eprintln('delete the folder, and execute again') exit(1) } tag := '1.0.32' fname := 'wabt-${tag}' mut platform := '' $if windows { platform = 'windows' } $else $if macos { platform = 'macos-14' } $else $if linux { platform = 'ubuntu' } $else { eprintln('A premade binary library is not available for your system.') eprintln('Build it from source, following the documentation here: https://github.com/WebAssembly/wabt/') exit(1) } url := 'https://github.com/WebAssembly/wabt/releases/download/${tag}/${fname}-${platform}.tar.gz' saveloc := os.join_path(tloc, '${fname}.tar.gz') println('>> Url: ${url}') println('>> Archive: ${saveloc}') if !os.exists(saveloc) { println('Downloading archive: ${saveloc}, from url: ${url} ...') http.download_file(url, saveloc)! // defer { os.rm(saveloc) or {}! } } println('Extracting `${tloc}/${fname}` to `${tloc}/wabt` ...') cmd := 'tar -xvf ${saveloc} --directory ${tloc}' if os.system(cmd) != 0 { eprintln('`${cmd}` exited with a non zero exit code') exit(1) } println(cmd) println('Moving `${tloc}/${fname}` to `${tloc}/wabt` ...') os.rename_dir('${tloc}/${fname}', loc)! println('Done. You can now use `v test vlib/wasm` .') } ================================================ FILE: cmd/tools/measure/file_lists/expand.v ================================================ module file_lists import os // expand_files accepts a list of files and folders, and returns a list of all the .v and .vsh files, found in them. // The input list of files, supports recursive `@file.lst` expansion, where each line is treated as another file/folder. pub fn expand_files(files []string) ![]string { mut res := []string{} for file in files { if file == '' { continue } if file.starts_with('@') { lst_path := files[0].all_after('@').trim_space() listed_files := os.read_file(lst_path)!.split('\n').map(it.trim_space()) res << expand_files(listed_files)! continue } if os.is_dir(file) { res << os.walk_ext(file, '.vsh') res << os.walk_ext(file, '.v') continue } if os.exists(file) { res << file } } return res } ================================================ FILE: cmd/tools/measure/fmt_speed.v ================================================ import os import time import v.ast import v.fmt import v.pref import v.parser import v.errors import v.scanner import term import file_lists const skip_tests = os.getenv('SKIP_TESTS').bool() const fuzzer_mode = os.getenv('VFUZZER').bool() const comments_mode = scanner.CommentsMode.from(os.getenv('SCANNER_MODE')) or { scanner.CommentsMode.parse_comments } fn main() { if !fuzzer_mode { dump(comments_mode) } all_files := file_lists.expand_files(os.args#[1..])! process_files(all_files)! } fn hline() { if fuzzer_mode { return } println('----------------------------------------------------------------------------------------------------------------------------------------------------------') } fn theader() { if fuzzer_mode { return } println(' Time Tokens Bytes Lines Bytes/Token Errors FMT.len') } fn process_files(files []string) ! { nthreads := 1 // TODO mut pref_ := pref.new_preferences() pref_.is_fmt = true pref_.skip_warnings = true pref_.output_mode = .silent mut sw := time.new_stopwatch() mut total_us := i64(0) mut total_bytes := i64(0) mut total_tokens := i64(0) mut total_lines := i64(0) mut total_errors := i64(0) mut total_files := i64(0) mut total_fmt_len := i64(0) for f in files { mut table := ast.new_table() if f == '' { continue } if skip_tests && f.ends_with('_test.v') { continue } total_files++ mut p := new_parser(f, comments_mode, table, pref_) ast_file := p.parse() /// // do not measure the scanning, and parsing, but only the formatting: sw.restart() formatted_content := fmt.fmt(ast_file, mut table, pref_, false) f_us := sw.elapsed().microseconds() // eprint(formatted_content) // this should be identical to the output of `v fmt file.v` /// total_us += f_us total_bytes += p.scanner.text.len total_tokens += p.scanner.all_tokens.len total_lines += ast_file.nr_lines total_errors += p.errors.len total_fmt_len += formatted_content.len if !fuzzer_mode { println('${f_us:10}us ${p.scanner.all_tokens.len:10} ${p.scanner.text.len:10} ${ast_file.nr_lines:10} ${(f64(p.scanner.text.len) / p.scanner.all_tokens.len):13.3} ${p.errors.len:10} ${formatted_content.len:8} ${f}') } } hline() theader() hline() speed_mb_s := term.colorize(term.bright_yellow, '${(f64(total_bytes) / total_us):6.3f} MB/s') speed_lines_s := term.colorize(term.bright_yellow, '${(1_000_000 * f64(total_lines) / total_us):10.1f} lines/s') println('${total_us:10}us ${total_tokens:10} ${total_bytes:10} ${total_lines:10} ${(f64(total_bytes) / total_tokens):13.3} ${total_errors:10} ${total_fmt_len:7} FMT speed: ${speed_mb_s}, ${speed_lines_s}, ${nthreads:3} thread(s), ${total_files:5} files.') } fn new_parser(path string, comments_mode scanner.CommentsMode, table &ast.Table, pref_ &pref.Preferences) &parser.Parser { mut p := &parser.Parser{ scanner: scanner.new_scanner_file(path, -1, comments_mode, pref_) or { panic(err) } table: table pref: pref_ scope: &ast.Scope{ start_pos: 0 parent: table.global_scope } errors: []errors.Error{} warnings: []errors.Warning{} } p.set_path(path) return p } ================================================ FILE: cmd/tools/measure/parser_speed.v ================================================ import os import time import v.ast import v.pref import v.parser import v.errors import v.scanner import term import file_lists const skip_tests = os.getenv('SKIP_TESTS').bool() const fuzzer_mode = os.getenv('VFUZZER').bool() const comments_mode = scanner.CommentsMode.from(os.getenv('SCANNER_MODE')) or { scanner.CommentsMode.skip_comments } fn main() { if !fuzzer_mode { dump(comments_mode) } all_files := file_lists.expand_files(os.args#[1..])! process_files(all_files)! } fn hline() { if fuzzer_mode { return } println('---------------------------------------------------------------------------------------------------------------------------------------------------') } fn theader() { if fuzzer_mode { return } println(' Time Tokens Bytes Lines Bytes/Token Errors') } fn process_files(files []string) ! { nthreads := 1 // TODO mut pref_ := pref.new_preferences() pref_.is_fmt = true pref_.skip_warnings = true pref_.output_mode = .silent mut sw := time.new_stopwatch() mut total_us := i64(0) mut total_bytes := i64(0) mut total_tokens := i64(0) mut total_lines := i64(0) mut total_errors := i64(0) mut total_files := i64(0) for f in files { mut table := ast.new_table() if f == '' { continue } if skip_tests && f.ends_with('_test.v') { continue } // do not measure the scanning, but only the parsing: mut p := new_parser(f, comments_mode, table, pref_) if fuzzer_mode { p.scanner.max_eofs = 200 } sw.restart() ast_file := p.parse() f_us := sw.elapsed().microseconds() total_us += f_us total_bytes += p.scanner.text.len total_tokens += p.scanner.all_tokens.len total_lines += ast_file.nr_lines total_errors += p.errors.len if !fuzzer_mode { println('${f_us:10}us ${p.scanner.all_tokens.len:10} ${p.scanner.text.len:10} ${ast_file.nr_lines:10} ${(f64(p.scanner.text.len) / p.scanner.all_tokens.len):13.3} ${p.errors.len:10} ${f}') } total_files++ } hline() theader() hline() speed_mb_s := term.colorize(term.bright_yellow, '${(f64(total_bytes) / total_us):6.3f} MB/s') speed_lines_s := term.colorize(term.bright_yellow, '${(1_000_000 * f64(total_lines) / total_us):10.1f} lines/s') println('${total_us:10}us ${total_tokens:10} ${total_bytes:10} ${total_lines:10} ${(f64(total_bytes) / total_tokens):13.3} ${total_errors:10} Parser speed: ${speed_mb_s}, ${speed_lines_s}, ${nthreads:3} thread(s), ${total_files:5} files.') } fn new_parser(path string, comments_mode scanner.CommentsMode, table &ast.Table, pref_ &pref.Preferences) &parser.Parser { mut p := &parser.Parser{ scanner: scanner.new_scanner_file(path, -1, comments_mode, pref_) or { panic(err) } table: table pref: pref_ scope: &ast.Scope{ start_pos: 0 parent: table.global_scope } errors: []errors.Error{} warnings: []errors.Warning{} } p.set_path(path) return p } ================================================ FILE: cmd/tools/measure/scanner_speed.v ================================================ import os import time import term import v.scanner import file_lists import v.pref const skip_tests = os.getenv('SKIP_TESTS').bool() const fuzzer_mode = os.getenv('VFUZZER').bool() const comments_mode = scanner.CommentsMode.from(os.getenv('SCANNER_MODE')) or { scanner.CommentsMode.skip_comments } fn main() { if !fuzzer_mode { dump(comments_mode) } all_files := file_lists.expand_files(os.args#[1..])! process_files(all_files)! } fn hline() { if fuzzer_mode { return } println('----------------------------------------------------------------------------------------------------------------------------------------------------') } fn theader() { if fuzzer_mode { return } println(' Time Tokens Bytes Lines Bytes/Token Errors') } fn process_files(files []string) ! { nthreads := 1 // TODO mut pref_ := pref.new_preferences() pref_.is_fmt = true pref_.skip_warnings = true pref_.output_mode = .silent mut sw := time.new_stopwatch() mut total_us := i64(0) mut total_bytes := i64(0) mut total_tokens := i64(0) mut total_lines := i64(0) mut total_errors := i64(0) mut total_files := i64(0) for f in files { if f == '' { continue } if skip_tests && f.ends_with('_test.v') { continue } total_files++ sw.restart() s := scanner.new_scanner_file(f, -1, comments_mode, pref_)! f_us := sw.elapsed().microseconds() total_us += f_us total_bytes += s.text.len total_tokens += s.all_tokens.len total_lines += s.nr_lines total_errors += s.errors.len if !fuzzer_mode { println('${f_us:10}us ${s.all_tokens.len:10} ${s.text.len:10} ${s.nr_lines:10} ${(f64(s.text.len) / s.all_tokens.len):13.3f} ${s.errors.len:10} ${f}') } } hline() theader() hline() speed_mb_s := term.colorize(term.bright_yellow, '${(f64(total_bytes) / total_us):6.3f} MB/s') speed_lines_s := term.colorize(term.bright_yellow, '${(1_000_000 * f64(total_lines) / total_us):10.1f} lines/s') println('${total_us:10}us ${total_tokens:10} ${total_bytes:10} ${total_lines:10} ${(f64(total_bytes) / total_tokens):13.3} ${total_errors:10} Scanner speed: ${speed_mb_s}, ${speed_lines_s}, ${nthreads:3} thread(s), ${total_files:5} files.') } ================================================ FILE: cmd/tools/modules/scripting/scripting.v ================================================ module scripting import os import term import time const term_colors = term.can_show_color_on_stdout() pub fn set_verbose(on bool) { // setting a global here would be the obvious solution, // but V does not have globals normally. if on { os.setenv('VERBOSE', '1', true) } else { os.unsetenv('VERBOSE') } } pub fn cprint(omessage string) { mut message := omessage if term_colors { message = term.cyan(message) } print(message) flush_stdout() } pub fn cprint_strong(omessage string) { mut message := omessage if term_colors { message = term.bright_green(message) } print(message) flush_stdout() } pub fn cprintln(omessage string) { cprint(omessage) println('') flush_stdout() } pub fn cprintln_strong(omessage string) { cprint_strong(omessage) println('') flush_stdout() } pub fn verbose_trace(label string, message string) { if os.getenv('VERBOSE').len > 0 { slabel := '${time.now().format_ss_milli()} ${label}' cprintln('# ${slabel:-43s} : ${message}') } } pub fn verbose_trace_strong(label string, omessage string) { if os.getenv('VERBOSE').len > 0 { slabel := '${time.now().format_ss_milli()} ${label}' mut message := omessage if term_colors { message = term.bright_green(message) } cprintln('# ${slabel:-43s} : ${message}') } } pub fn verbose_trace_exec_result(x os.Result) { if os.getenv('VERBOSE').len > 0 { cprintln('# cmd.exit_code : ${x.exit_code.str():-4s} cmd.output:') mut lnum := 1 lines := x.output.split_into_lines() for oline in lines { mut line := oline if term_colors { line = term.bright_green(line) } cprintln('# ${lnum:3d}: ${line}') lnum++ } cprintln('# ----------------------------------------------------------------------') } } fn modfn(mname string, fname string) string { return '${mname}.${fname}' } pub fn chdir(path string) { verbose_trace_strong(modfn(@MOD, @FN), 'cd ${path}') os.chdir(path) or { verbose_trace(modfn(@MOD, @FN), '## failed.') return } } pub fn mkdir(path string) ! { verbose_trace_strong(modfn(@MOD, @FN), 'mkdir ${path}') os.mkdir(path) or { verbose_trace(modfn(@MOD, @FN), '## failed.') return err } } pub fn mkdir_all(path string) ! { verbose_trace_strong(modfn(@MOD, @FN), 'mkdir -p ${path}') os.mkdir_all(path) or { verbose_trace(modfn(@MOD, @FN), '## failed.') return err } } pub fn rmrf(path string) { verbose_trace_strong(modfn(@MOD, @FN), 'rm -rf ${path}') if os.exists(path) { if os.is_dir(path) { os.rmdir_all(path) or { panic(err) } } else { os.rm(path) or { panic(err) } } } } // execute a command, and return a result, or an error, if it failed in any way. pub fn exec(cmd string) !os.Result { verbose_trace_strong(modfn(@MOD, @FN), cmd) x := os.execute(cmd) if x.exit_code != 0 { verbose_trace(modfn(@MOD, @FN), '## failed.') return error(x.output) } verbose_trace_exec_result(x) return x } // run a command, tracing its results, and returning ONLY its output pub fn run(cmd string) string { verbose_trace_strong(modfn(@MOD, @FN), cmd) x := os.execute(cmd) if x.exit_code < 0 { verbose_trace(modfn(@MOD, @FN), '## failed.') return '' } verbose_trace_exec_result(x) if x.exit_code == 0 { return x.output.trim_right('\r\n') } return '' } // frun runs a command, tracing its results, and returning ONLY its output, or an error, if it failed pub fn frun(cmd string) !string { verbose_trace_strong(modfn(@MOD, @FN), cmd) x := os.execute(cmd) if x.exit_code != 0 { verbose_trace(modfn(@MOD, @FN), '## failed.') verbose_trace(modfn(@MOD, @FN), '## failure code: ${x.exit_code}') verbose_trace(modfn(@MOD, @FN), '## failure output: ${x.output}') return error_with_code('failed cmd: ${cmd}', x.exit_code) } verbose_trace_exec_result(x) return x.output.trim_right('\r\n') } pub fn exit_0_status(cmd string) bool { verbose_trace_strong(modfn(@MOD, @FN), cmd) x := os.execute(cmd) if x.exit_code < 0 { verbose_trace(modfn(@MOD, @FN), '## failed.') return false } verbose_trace_exec_result(x) if x.exit_code == 0 { return true } return false } pub fn tool_must_exist(toolcmd string) { verbose_trace(modfn(@MOD, @FN), toolcmd) where_is_cmd := if os.user_os() == 'windows' { 'where' } else { 'type' } if exit_0_status('${where_is_cmd} ${toolcmd}') { return } eprintln('Missing tool: ${toolcmd}') eprintln('Please try again after you install it.') exit(1) } pub fn used_tools_must_exist(tools []string) { for t in tools { tool_must_exist(t) } } pub fn show_sizes_of_files(files []string) { for f in files { size := os.file_size(f) println('${size} ${f}') // println('${size:10d} ${f}') } } ================================================ FILE: cmd/tools/modules/testing/common.v ================================================ module testing import os import os.cmdline import time import term import benchmark import sync import sync.pool import v.pref import v.util.vtest import v.util.vflags import runtime import rand import strings import v.build_constraint pub const max_header_len = get_max_header_len() pub const host_os = pref.get_host_os() pub const github_job = os.getenv('GITHUB_JOB') pub const runner_os = os.getenv('RUNNER_OS') // GitHub runner OS pub const keep_session = os.getenv('VTEST_KEEP_SESSION') == '1' pub const show_cmd = os.getenv('VTEST_SHOW_CMD') == '1' pub const show_start = os.getenv('VTEST_SHOW_START') == '1' pub const show_longest_by_runtime = os.getenv('VTEST_SHOW_LONGEST_BY_RUNTIME').int() pub const show_longest_by_comptime = os.getenv('VTEST_SHOW_LONGEST_BY_COMPTIME').int() pub const show_longest_by_totaltime = os.getenv('VTEST_SHOW_LONGEST_BY_TOTALTIME').int() pub const is_ci = os.getenv('CI') != '' || os.getenv('GITHUB_JOB') != '' pub const hide_skips = os.getenv('VTEST_HIDE_SKIP') == '1' || (is_ci && os.getenv('VTEST_HIDE_SKIP') != '0') pub const hide_oks = os.getenv('VTEST_HIDE_OK') == '1' || (is_ci && os.getenv('VTEST_HIDE_OK') != '0') pub const fail_fast = os.getenv('VTEST_FAIL_FAST') == '1' pub const fail_flaky = os.getenv('VTEST_FAIL_FLAKY') == '1' pub const test_only = os.getenv('VTEST_ONLY').split_any(',') pub const test_only_fn = os.getenv('VTEST_ONLY_FN').split_any(',') // TODO: this !!!*reliably*!!! fails compilation of `v cmd/tools/vbuild-examples.v` with a cgen error, without `-no-parallel`: // pub const fail_retry_delay_ms = os.getenv_opt('VTEST_FAIL_RETRY_DELAY_MS') or { '500' }.int() * time.millisecond // Note, it works with `-no-parallel`, and it works when that whole expr is inside a function, like below: pub const fail_retry_delay_ms = get_fail_retry_delay_ms() pub const pkgcmd = get_pkgcmd() pub const is_node_present = os.execute('node --version').exit_code == 0 pub const is_go_present = os.execute('go version').exit_code == 0 pub const is_ruby_present = os.execute('ruby --version').exit_code == 0 && os.execute('${pkgcmd} ruby --libs').exit_code == 0 pub const is_python_present = os.execute('python --version').exit_code == 0 && os.execute('${pkgcmd} python3 --libs').exit_code == 0 pub const is_sqlite3_present = get_present_sqlite() pub const all_processes = get_all_processes() pub const header_bytes_to_search_for_module_main = 500 pub const separator = '-'.repeat(max_header_len) + '\n' pub const max_compilation_retries = get_max_compilation_retries() fn get_max_compilation_retries() int { return os.getenv_opt('VTEST_MAX_COMPILATION_RETRIES') or { '3' }.int() } fn get_fail_retry_delay_ms() time.Duration { return os.getenv_opt('VTEST_FAIL_RETRY_DELAY_MS') or { '500' }.int() * time.millisecond } fn get_pkgcmd() string { for cmd in ['pkgconf', 'pkg-config'] { if os.execute('${cmd} --version').exit_code == 0 { return cmd } } return 'false' } fn get_present_sqlite() bool { if os.user_os() == 'windows' { return os.exists(@VEXEROOT + '/thirdparty/sqlite/sqlite3.c') } return os.execute('sqlite3 --version').exit_code == 0 && os.execute('${pkgcmd} sqlite3 --libs').exit_code == 0 } fn get_all_processes() []string { $if windows { // TODO return [] } $else { return os.execute('ps ax').output.split_any('\r\n') } } pub enum ActionMode { compile compile_and_run } pub struct TestSession { pub mut: files []string skip_files []string vexe string vroot string vtmp_dir string vargs string fail_fast bool benchmark benchmark.Benchmark rm_binaries bool = true build_tools bool // builds only executables in cmd/tools; used by `v build-tools' silent_mode bool show_stats bool show_asserts bool progress_mode bool root_relative bool // used by CI runs, so that the output is stable everywhere nmessages chan LogMessage // many publishers, single consumer/printer nmessage_idx int // currently printed message index failed_cmds shared []string reporter Reporter = Reporter(NormalReporter{}) hash string // used as part of the name of the temporary directory created for tests, to ease cleanup exec_mode ActionMode = .compile // .compile_and_run only for `v test` build_environment build_constraint.Environment // see the documentation in v.build_constraint custom_defines []string // for adding custom defines, known only to the individual runners } pub fn (mut ts TestSession) add_failed_cmd(cmd string) { lock ts.failed_cmds { ts.failed_cmds << cmd } } pub fn (mut ts TestSession) show_list_of_failed_tests() { rlock ts.failed_cmds { ts.reporter.list_of_failed_commands(ts.failed_cmds) } } struct MessageThreadContext { mut: file string flow_id string } fn (mut ts TestSession) append_message(kind MessageKind, msg string, mtc MessageThreadContext) { ts.nmessages <- LogMessage{ file: mtc.file flow_id: mtc.flow_id message: msg kind: kind when: time.now() } } fn (mut ts TestSession) append_message_with_duration(kind MessageKind, msg string, d time.Duration, mtc MessageThreadContext) { ts.nmessages <- LogMessage{ file: mtc.file flow_id: mtc.flow_id message: msg kind: kind when: time.now() took: d } } pub fn (mut ts TestSession) session_start(message string) { ts.reporter.session_start(message, mut ts) } pub fn (mut ts TestSession) session_stop(message string) { ts.reporter.session_stop(message, mut ts) } pub fn (mut ts TestSession) print_messages() { mut test_idx := 0 mut print_msg_time := time.new_stopwatch() for { // get a message from the channel of messages to be printed: mut rmessage := <-ts.nmessages ts.nmessage_idx++ // first sent *all events* to the output reporter, so it can then process them however it wants: ts.reporter.report(ts.nmessage_idx, rmessage) if rmessage.kind in [.cmd_begin, .cmd_end, .compile_begin, .compile_end] { // The following events, are sent before the test framework has determined, // what the full completion status is. They can also be repeated multiple times, // for tests that are flaky and need repeating. continue } if rmessage.kind == .sentinel { // a sentinel for stopping the printing thread if !ts.silent_mode && ts.progress_mode { ts.reporter.report_stop() } return } if rmessage.kind != .info { // info events can also be repeated, and should be ignored when determining // the total order of the current test file, in the following replacements: test_idx++ } msg := rmessage.message.replace_each([ 'TMP1', '${test_idx:1d}', 'TMP2', '${test_idx:2d}', 'TMP3', '${test_idx:3d}', 'TMP4', '${test_idx:4d}', ]) is_ok := rmessage.kind == .ok // time_passed := print_msg_time.elapsed().seconds() if time_passed > 10 && ts.silent_mode && is_ok { // Even if OK tests are suppressed, // show *at least* 1 result every 10 seconds, // otherwise the CI can seem stuck ... ts.reporter.progress(ts.nmessage_idx, msg) print_msg_time.restart() continue } if ts.progress_mode { if is_ok && !ts.silent_mode { ts.reporter.update_last_line(ts.nmessage_idx, msg) } else { ts.reporter.update_last_line_and_move_to_next(ts.nmessage_idx, msg) } continue } if !ts.silent_mode || !is_ok { // normal expanded mode, or failures in -silent mode ts.reporter.message(ts.nmessage_idx, msg) continue } } } pub fn (mut ts TestSession) execute(cmd string, mtc MessageThreadContext) os.Result { if show_cmd { ts.append_message(.info, '> execute cmd: ${cmd}', mtc) } return os.execute(cmd) } pub fn (mut ts TestSession) system(cmd string, mtc MessageThreadContext) int { if show_cmd { ts.append_message(.info, '> system cmd: ${cmd}', mtc) } return os.system(cmd) } pub fn new_test_session(_vargs string, will_compile bool) TestSession { mut skip_files := []string{} if will_compile { if runner_os != 'Linux' || !github_job.starts_with('tcc-') { if !os.exists('/usr/local/include/wkhtmltox/pdf.h') { skip_files << 'examples/c_interop_wkhtmltopdf.v' // needs installation of wkhtmltopdf from https://github.com/wkhtmltopdf/packaging/releases } } } skip_files = skip_files.map(os.abs_path) vargs := _vargs.replace('-progress', '') vexe := pref.vexe_path() vroot := os.dir(vexe) hash := '${sync.thread_id().hex()}_${rand.ulid()}' new_vtmp_dir := setup_new_vtmp_folder(hash) if term.can_show_color_on_stderr() { os.setenv('VCOLORS', 'always', true) } mut ts := TestSession{ vexe: vexe vroot: vroot skip_files: skip_files fail_fast: fail_fast show_stats: '-stats' in vargs.split(' ') show_asserts: '-show-asserts' in vargs.split(' ') vargs: vargs vtmp_dir: new_vtmp_dir hash: hash silent_mode: _vargs.contains('-silent') progress_mode: _vargs.contains('-progress') } if keep_session { ts.rm_binaries = false println('> vtmp_dir: ${new_vtmp_dir}') } ts.handle_test_runner_option() return ts } fn (mut ts TestSession) handle_test_runner_option() { test_runner := cmdline.option(os.args, '-test-runner', 'normal') if test_runner !in pref.supported_test_runners { eprintln('v test: `-test-runner ${test_runner}` is not using one of the supported test runners: ${pref.supported_test_runners_list()}') } test_runner_implementation_file := os.join_path(ts.vroot, 'cmd/tools/modules/testing/output_${test_runner}.v') if !os.exists(test_runner_implementation_file) { eprintln('v test: using `-test-runner ${test_runner}` needs ${test_runner_implementation_file} to exist, and contain a valid testing.Reporter implementation for that runner. See `cmd/tools/modules/testing/output_dump.v` for an example.') exit(1) } match test_runner { 'normal' { // default, nothing to do } 'dump' { ts.reporter = DumpReporter{} } 'teamcity' { ts.reporter = TeamcityReporter{} } else { dump('just set ts.reporter to an instance of your own struct here') } } } pub fn (mut ts TestSession) init() { ts.files.sort() ts.benchmark = benchmark.new_benchmark_no_cstep() } pub fn (mut ts TestSession) add(file string) { ts.files << file } pub fn (mut ts TestSession) test() { unbuffer_stdout() // Ensure that .tmp.c files generated from compiling _test.v files, // are easy to delete at the end, *without* affecting the existing ones. current_wd := os.getwd() if current_wd == os.wd_at_startup && current_wd == ts.vroot { ts.root_relative = true } ts.init() mut remaining_files := []string{} for dot_relative_file in ts.files { file := os.real_path(dot_relative_file) if ts.build_tools && dot_relative_file.ends_with('_test.v') { continue } // Skip OS-specific tests if we are not running that OS // Special case for android_outside_termux because of its // underscores if file.ends_with('_android_outside_termux_test.v') { if !host_os.is_target_of('android_outside_termux') { remaining_files << dot_relative_file ts.skip_files << file continue } } os_target := file.all_before_last('_test.v').all_after_last('_') if !host_os.is_target_of(os_target) { remaining_files << dot_relative_file ts.skip_files << file continue } remaining_files << dot_relative_file } remaining_files = vtest.filter_vtest_only(remaining_files, fix_slashes: false) ts.files = remaining_files ts.benchmark.set_total_expected_steps(remaining_files.len) mut njobs := runtime.nr_jobs() if remaining_files.len < njobs { njobs = remaining_files.len } ts.benchmark.njobs = njobs mut pool_of_test_runners := pool.new_pool_processor(callback: worker_trunner) // ensure that the nmessages queue/channel, has enough capacity for handling many messages across threads, without blocking ts.nmessages = chan LogMessage{cap: 10000} ts.nmessage_idx = 0 printing_thread := spawn ts.print_messages() pool_of_test_runners.set_shared_context(ts) ts.reporter.worker_threads_start(remaining_files, mut ts) ts.setup_build_environment() // all the testing happens here: pool_of_test_runners.work_on_pointers(unsafe { remaining_files.pointers() }) ts.benchmark.stop() ts.append_message(.sentinel, '', MessageThreadContext{ flow_id: '-1' }) // send the sentinel printing_thread.wait() ts.reporter.worker_threads_finish(mut ts) ts.reporter.divider() ts.show_list_of_failed_tests() // cleanup the session folder, if everything was ok: if ts.benchmark.nfail == 0 { if ts.rm_binaries { os.rmdir_all(ts.vtmp_dir) or {} } } if os.ls(ts.vtmp_dir) or { [] }.len == 0 { os.rmdir_all(ts.vtmp_dir) or {} } } fn worker_trunner(mut p pool.PoolProcessor, idx int, thread_id int) voidptr { mut ts := unsafe { &TestSession(p.get_shared_context()) } if ts.fail_fast { if ts.failed_cmds.len > 0 { return pool.no_result } } // tls_bench is used to format the step messages/timings mut tls_bench := unsafe { &benchmark.Benchmark(p.get_thread_context(idx)) } if isnil(tls_bench) { tls_bench = benchmark.new_benchmark_pointer() tls_bench.set_total_expected_steps(ts.benchmark.nexpected_steps) p.set_thread_context(idx, tls_bench) } tls_bench.no_cstep = true tls_bench.njobs = ts.benchmark.njobs abs_path := os.real_path(p.get_item[string](idx)) mut relative_file := abs_path mut cmd_options := vflags.tokenize_to_args(ts.vargs) // make sure that `'-W -silent'` becomes `['-W', '-silent']`, while keeping quoted spaces intact mut run_js := false is_fmt := ts.vargs.contains('fmt') is_vet := ts.vargs.contains('vet') produces_file_output := !(is_fmt || is_vet) if relative_file.ends_with('.js.v') { if produces_file_output { cmd_options << ' -b js' run_js = true } } if relative_file.ends_with('.c.v') { if produces_file_output { cmd_options << ' -b c' run_js = false } } if relative_file.contains('global') && !is_fmt { cmd_options << ' -enable-globals' } if ts.root_relative { relative_file = relative_file.replace_once(ts.vroot + os.path_separator, '') } normalised_relative_file := relative_file.replace('\\', '/') file := abs_path mtc := MessageThreadContext{ file: file flow_id: thread_id.str() } // Ensure that the generated binaries will be stored in an *unique*, fresh, and per test folder, // inside the common session temporary folder, used for all the tests. // This is done to provide a clean working environment, for each test, that will not contain // files from other tests, and will make sure that tests with the same name, can be compiled // inside their own folders, without name conflicts (and without locking issues on windows, // where an executable is not writable, if it is running). // Note, that the common session temporary folder ts.vtmp_dir, // will be removed after all tests are done. test_id := '${idx}_${thread_id}' mut test_folder_path := os.join_path(ts.vtmp_dir, test_id) if ts.build_tools { // `v build-tools`, produce all executables in the same session folder, so that they can be copied later: test_folder_path = ts.vtmp_dir } else { os.mkdir_all(test_folder_path) or {} } fname := os.file_name(file) // There are test files ending with `_test.v`, `_test.c.v` and `_test.js.v`. mut fname_without_extension := fname.all_before_last('.v') if fname_without_extension.ends_with('.c') { fname_without_extension = fname_without_extension.all_before_last('.c') } generated_binary_fname := if os.user_os() == 'windows' && !run_js { fname_without_extension + '.exe' } else { fname_without_extension } mut details := get_test_details(file) if details.vflags != '' && !is_fmt { cmd_options << details.vflags } reproduce_options := cmd_options.clone() generated_binary_fpath := os.join_path_single(test_folder_path, generated_binary_fname) if produces_file_output { if ts.rm_binaries { os.rm(generated_binary_fpath) or {} } cmd_options << ' -o ${os.quoted_path(generated_binary_fpath)}' } defer { if produces_file_output && ts.rm_binaries { os.rmdir_all(test_folder_path) or {} } } mut skip_running := '-skip-running' if ts.show_stats { skip_running = '' } reproduce_cmd := '${os.quoted_path(ts.vexe)} ${reproduce_options.join(' ')} ${os.quoted_path(file)}' compile_options := cmd_options.filter(it != '-silent') cmd := '${os.quoted_path(ts.vexe)} ${skip_running} ${compile_options.join(' ')} ${os.quoted_path(file)}' run_cmd := if run_js { 'node ${os.quoted_path(generated_binary_fpath)}' } else { os.quoted_path(generated_binary_fpath) } mut should_be_built := true if details.vbuild != '' { should_be_built = ts.build_environment.eval(details.vbuild) or { eprintln('${file}:${details.vbuild_line}:17: error during parsing the `// v test build` expression `${details.vbuild}`: ${err}') false } $if trace_should_be_built ? { eprintln('${file} has specific build constraint: `${details.vbuild}` => should_be_built: `${should_be_built}`') eprintln('> env facts: ${ts.build_environment.facts}') eprintln('> env defines: ${ts.build_environment.defines}') } } ts.benchmark.step() tls_bench.step() if produces_file_output && !ts.build_tools && (!should_be_built || abs_path in ts.skip_files) { ts.benchmark.skip() tls_bench.skip() if !hide_skips { ts.append_message(.skip, tls_bench.step_message_with_label_and_duration(benchmark.b_skip, normalised_relative_file, 0, preparation: 1 * time.microsecond ), mtc) } return pool.no_result } mut compile_cmd_duration := time.Duration(0) mut cmd_duration := time.Duration(0) if ts.show_stats { ts.append_message(.cmd_begin, cmd, mtc) d_cmd := time.new_stopwatch() mut res := ts.execute(cmd, mtc) if res.exit_code != 0 { eprintln(res.output) } else { println(res.output) } mut status := res.exit_code cmd_duration = d_cmd.elapsed() ts.append_message_with_duration(.cmd_end, '', cmd_duration, mtc) if status != 0 { os.setenv('VTEST_RETRY_MAX', '${details.retry}', true) for retry := 1; retry <= details.retry; retry++ { if !details.hide_retries { ts.append_message(.info, ' [stats] retrying ${retry}/${details.retry} of ${relative_file} ; known flaky: ${details.flaky} ...', mtc) } os.setenv('VTEST_RETRY', '${retry}', true) ts.append_message(.cmd_begin, cmd, mtc) d_cmd_2 := time.new_stopwatch() status = ts.system(cmd, mtc) cmd_duration = d_cmd_2.elapsed() ts.append_message_with_duration(.cmd_end, '', cmd_duration, mtc) if status == 0 { unsafe { goto test_passed_system } } time.sleep(fail_retry_delay_ms) } if details.flaky && !fail_flaky { ts.append_message(.info, ' *FAILURE* of the known flaky test file ${relative_file} is ignored, since VTEST_FAIL_FLAKY is 0 . Retry count: ${details.retry} .\ncmd: ${cmd}', mtc) unsafe { goto test_passed_system } } // most probably compiler error if res.output.contains(': error: ') { ts.append_message(.cannot_compile, 'Cannot compile file ${file}', mtc) } ts.benchmark.fail() tls_bench.fail() ts.add_failed_cmd(reproduce_cmd) return pool.no_result } } else { if show_start { ts.append_message(.info, ' starting ${relative_file} ...', mtc) } ts.append_message(.compile_begin, cmd, mtc) compile_d_cmd := time.new_stopwatch() mut compile_r := os.Result{} for cretry in 0 .. max_compilation_retries { compile_r = ts.execute(cmd, mtc) compile_cmd_duration = compile_d_cmd.elapsed() // eprintln('>>>> cretry: ${cretry} | compile_r.exit_code: ${compile_r.exit_code} | compile_cmd_duration: ${compile_cmd_duration:8} | file: ${normalised_relative_file}') if compile_r.exit_code == 0 { break } random_sleep_ms(50, 100 * cretry) } ts.append_message_with_duration(.compile_end, compile_r.output, compile_cmd_duration, mtc) if compile_r.exit_code != 0 { ts.benchmark.fail() tls_bench.fail() ts.append_message_with_duration(.fail, tls_bench.step_message_with_label_and_duration(benchmark.b_fail, '${normalised_relative_file}\n>> compilation failed:\n${compile_r.output}', cmd_duration, preparation: compile_cmd_duration ), cmd_duration, mtc) ts.add_failed_cmd(reproduce_cmd) return pool.no_result } tls_bench.step_restart() ts.benchmark.step_restart() if ts.exec_mode == .compile { unsafe { goto test_passed_execute } } // mut retry := 1 mut failure_output := strings.new_builder(1024) ts.append_message(.cmd_begin, run_cmd, mtc) d_cmd := time.new_stopwatch() mut r := ts.execute(run_cmd, mtc) cmd_duration = d_cmd.elapsed() ts.append_message_with_duration(.cmd_end, r.output, cmd_duration, mtc) if ts.show_asserts && r.exit_code == 0 { println(r.output.split_into_lines().filter(it.contains(' assert')).join('\n')) } if r.exit_code != 0 { mut trimmed_output := r.output.trim_space() if trimmed_output.len == 0 { // retry running at least 1 more time, to avoid CI false positives as much as possible details.retry++ } if details.retry != 0 { failure_output.write_string(separator) failure_output.writeln(' retry: 0 ; max_retry: ${details.retry} ; r.exit_code: ${r.exit_code} ; trimmed_output.len: ${trimmed_output.len}') } failure_output.writeln(trimmed_output) os.setenv('VTEST_RETRY_MAX', '${details.retry}', true) for retry = 1; retry <= details.retry; retry++ { if !details.hide_retries { ts.append_message(.info, ' retrying ${retry}/${details.retry} of ${relative_file} ; known flaky: ${details.flaky} ...', mtc) } os.setenv('VTEST_RETRY', '${retry}', true) ts.append_message(.cmd_begin, run_cmd, mtc) d_cmd_2 := time.new_stopwatch() r = ts.execute(run_cmd, mtc) cmd_duration = d_cmd_2.elapsed() ts.append_message_with_duration(.cmd_end, r.output, cmd_duration, mtc) if r.exit_code == 0 { unsafe { goto test_passed_execute } } trimmed_output = r.output.trim_space() failure_output.write_string(separator) failure_output.writeln(' retry: ${retry} ; max_retry: ${details.retry} ; r.exit_code: ${r.exit_code} ; trimmed_output.len: ${trimmed_output.len}') failure_output.writeln(trimmed_output) time.sleep(fail_retry_delay_ms) } full_failure_output := failure_output.str().trim_space() if details.flaky && !fail_flaky { ts.append_message(.info, '>>> flaky failures so far:', mtc) for line in full_failure_output.split_into_lines() { ts.append_message(.info, '>>>>>> ${line}', mtc) } ts.append_message(.info, ' *FAILURE* of the known flaky test file ${relative_file} is ignored, since VTEST_FAIL_FLAKY is 0 . Retry count: ${details.retry} .\n comp_cmd: ${cmd}\n run_cmd: ${run_cmd}', mtc) unsafe { goto test_passed_execute } } ts.benchmark.fail() tls_bench.fail() cmd_duration = d_cmd.elapsed() - (fail_retry_delay_ms * details.retry) ts.append_message_with_duration(.fail, tls_bench.step_message_with_label_and_duration(benchmark.b_fail, '${normalised_relative_file}\n${full_failure_output}', cmd_duration, preparation: compile_cmd_duration ), cmd_duration, mtc) ts.add_failed_cmd(reproduce_cmd) return pool.no_result } } test_passed_system: test_passed_execute: ts.benchmark.ok() tls_bench.ok() if !hide_oks { ts.append_message_with_duration(.ok, tls_bench.step_message_with_label_and_duration(benchmark.b_ok, normalised_relative_file, cmd_duration, preparation: compile_cmd_duration ), cmd_duration, mtc) } return pool.no_result } pub fn vlib_should_be_present(parent_dir string) { vlib_dir := os.join_path_single(parent_dir, 'vlib') if !os.is_dir(vlib_dir) { eprintln('${vlib_dir} is missing, it must be next to the V executable') exit(1) } } pub fn prepare_test_session(zargs string, folder string, oskipped []string, main_label string) TestSession { vexe := pref.vexe_path() parent_dir := os.dir(vexe) nparent_dir := parent_dir.replace('\\', '/') vlib_should_be_present(parent_dir) vargs := zargs.replace(vexe, '') eheader(main_label) if vargs.len > 0 { eprintln('v compiler args: "${vargs}"') } mut session := new_test_session(vargs, true) files := os.walk_ext(os.join_path_single(parent_dir, folder), '.v') mut mains := []string{} mut skipped := oskipped.clone() next_file: for f in files { fnormalised := f.replace('\\', '/') // Note: a `testdata` folder, is the preferred name of a folder, containing V code, // that you *do not want* the test framework to find incidentally for various reasons, // for example module import tests, or subtests, that are compiled/run by other parent tests // in specific configurations, etc. if fnormalised.contains('testdata/') || fnormalised.contains('modules/') || fnormalised.contains('preludes/') { continue } $if windows { // skip process/command examples on windows. TODO: remove the need for this, fix os.Command if fnormalised.ends_with('examples/process/command.v') { skipped << fnormalised.replace(nparent_dir + '/', '') continue } } c := os.read_file(fnormalised) or { panic(err) } start := c#[0..header_bytes_to_search_for_module_main] if start.contains('module ') { modname := start.all_after('module ').all_before('\n') if modname !in ['main', 'no_main'] { skipped << fnormalised.replace(nparent_dir + '/', '') continue next_file } } for skip_prefix in oskipped { skip_folder := skip_prefix + '/' if fnormalised.starts_with(skip_folder) { continue next_file } } mains << fnormalised } session.files << mains session.skip_files << skipped return session } pub type FnTestSetupCb = fn (mut session TestSession) pub fn v_build_failing_skipped(zargs string, folder string, oskipped []string, cb FnTestSetupCb) bool { main_label := 'Building ${folder} ...' finish_label := 'building ${folder}' mut session := prepare_test_session(zargs, folder, oskipped, main_label) cb(mut session) session.test() eprintln(session.benchmark.total_message(finish_label)) return session.failed_cmds.len > 0 } pub fn build_v_cmd_failed(cmd string) bool { res := os.execute(cmd) if res.exit_code < 0 { return true } if res.exit_code != 0 { eprintln('') eprintln(res.output) return true } return false } pub fn building_any_v_binaries_failed() bool { eheader('Building V binaries...') eprintln('VFLAGS is: "' + os.getenv('VFLAGS') + '"') vexe := pref.vexe_path() parent_dir := os.dir(vexe) vlib_should_be_present(parent_dir) os.chdir(parent_dir) or { panic(err) } mut failed := false v_build_commands := ['${vexe} -o v_g -g cmd/v', '${vexe} -o v_prod_g -prod -g cmd/v', '${vexe} -o v_cg -cg cmd/v', '${vexe} -o v_prod_cg -prod -cg cmd/v', '${vexe} -o v_prod -prod cmd/v'] mut bmark := benchmark.new_benchmark() for cmd in v_build_commands { bmark.step() if build_v_cmd_failed(cmd) { bmark.fail() failed = true eprintln(bmark.step_message_fail('command: ${cmd} . See details above ^^^^^^^')) eprintln('') continue } bmark.ok() if !hide_oks { eprintln(bmark.step_message_ok('command: ${cmd}')) } } bmark.stop() h_divider() eprintln(bmark.total_message('building v binaries')) return failed } pub fn h_divider() { eprintln(term.h_divider('-')#[..max_header_len]) } // setup_new_vtmp_folder creates a new nested folder inside VTMP, then resets VTMP to it, // so that V programs/tests will write their temporary files to new location. // The new nested folder, and its contents, will get removed after all tests/programs succeed. pub fn setup_new_vtmp_folder(hash string) string { new_vtmp_dir := os.join_path(os.vtmp_dir(), 'tsession_${hash}') os.mkdir_all(new_vtmp_dir) or { panic(err) } os.setenv('VTMP', new_vtmp_dir, true) return new_vtmp_dir } pub struct TestDetails { pub mut: retry int flaky bool // when flaky tests fail, the whole run is still considered successful, unless VTEST_FAIL_FLAKY is 1 // hide_retries bool // when true, all retry tries are silent; used by `vlib/v/tests/retry_test.v` vbuild string // could be `!(windows && tinyc)` vbuild_line int // for more precise error reporting, if the `vbuild` expression is incorrect vflags string // custom compilation flags for the test (enables for example: `// vtest vflags: -w`, for tests that have known warnings, but should still pass with -W) } pub fn get_test_details(file string) TestDetails { mut res := TestDetails{} if !os.is_file(file) { return res } lines := os.read_lines(file) or { [] } for idx, line in lines { if line.starts_with('// vtest retry:') { res.retry = line.all_after(':').trim_space().int() } if line.starts_with('// vtest flaky:') { res.flaky = line.all_after(':').trim_space().bool() } if line.starts_with('// vtest build:') { res.vbuild = line.all_after(':').trim_space() res.vbuild_line = idx + 1 } if line.starts_with('// vtest vflags:') { res.vflags = line.all_after(':').trim_space() } if line.starts_with('// vtest hide_retries') { res.hide_retries = true } } return res } pub fn find_started_process(pname string) !string { for line in all_processes { if line.contains(pname) { return line } } return error('could not find process matching ${pname}') } fn limited_header(msg string) string { return term.header_left(msg, '-')#[..max_header_len] } pub fn eheader(msg string) { eprintln(limited_header(msg)) } pub fn header(msg string) { println(limited_header(msg)) flush_stdout() } fn random_sleep_ms(min_ms int, random_add_ms int) { time.sleep((50 + rand.intn(50) or { 0 }) * time.millisecond) } fn get_max_header_len() int { maximum := 140 cols, _ := term.get_terminal_size() if cols > maximum { return maximum } return cols } fn check_openssl_present() bool { if github_job.ends_with('-windows') { // TODO: investigate the https://github.com/vlang/v/actions/runs/18590919000/job/53005499130 failure in more details return false } $if openbsd { return os.execute('eopenssl35 --version').exit_code == 0 && os.execute('${pkgcmd} eopenssl35 --libs').exit_code == 0 } $else { return os.execute('openssl --version').exit_code == 0 && os.execute('${pkgcmd} openssl --libs').exit_code == 0 } } pub const is_openssl_present = check_openssl_present() // is_started_mysqld is true, when the test runner determines that there is a running mysql server pub const is_started_mysqld = find_started_process('mysqld') or { '' } // is_started_postgres is true, when the test runner determines that there is a running postgres server pub const is_started_postgres = find_started_process('postgres') or { '' } // is_started_redis is true, when the test runner determines that there is a running redis server pub const is_started_redis = find_started_process('redis-server') or { '' } pub fn (mut ts TestSession) setup_build_environment() { facts, mut defines := pref.get_build_facts_and_defines() // add the runtime information, that the test runner has already determined by checking once: if github_job.starts_with('sanitize-') { defines << 'sanitized_job' } if is_started_mysqld != '' { defines << 'started_mysqld' } if is_started_postgres != '' { defines << 'started_postgres' } if is_started_redis != '' { defines << 'started_redis' } if is_node_present { defines << 'present_node' } if is_python_present { defines << 'present_python' } if is_ruby_present { defines << 'present_ruby' } if is_go_present { defines << 'present_go' } if is_sqlite3_present { defines << 'present_sqlite3' } if is_openssl_present { defines << 'present_openssl' } // detect the linux distribution as well when possible: if os.is_file('/etc/os-release') { mut distro_kind := '' if lines := os.read_lines('/etc/os-release') { for line in lines { if line.starts_with('ID=') { distro_kind = line.all_after('ID=') break } } } if distro_kind != '' { defines << 'os_id_${distro_kind}' // os_id_alpine, os_id_freebsd, os_id_ubuntu, os_id_debian etc } } defines << ts.custom_defines $if trace_vbuild ? { eprintln('>>> testing.get_build_environment facts: ${facts}') eprintln('>>> testing.get_build_environment defines: ${defines}') } ts.build_environment = build_constraint.new_environment(facts, defines) } ================================================ FILE: cmd/tools/modules/testing/output.v ================================================ module testing import time pub enum MessageKind { compile_begin // sent right before *each* _test.v file compilation, the resulting status is not known yet, but the _test.v file itself is compile_end // sent right after *each* _test.v file compilation, the message contains the output of that compilation cmd_begin // sent right before *each* _test.v file execution, the resulting status is not known yet, but the _test.v file itself is cmd_end // sent right after *each* _test.v file execution, the message contains the output of that execution ok // success of a _test.v file fail // failed _test.v file, one or more assertions failed skip // the _test.v file was skipped for some reason info // a generic information message, detailing the actions of the `v test` program (some tests could be repeated for example, and the details are sent with an .info status) cannot_compile // when the _test.v file compiled with errors sentinel // send just once after all executions are done; it signals that the reporting/printing thread should stop the loop and exit } pub struct LogMessage { pub: kind MessageKind // see the MessageKind declaration above file string // the _test.v file that the message is about when time.Time // when was the message sent (messages are sent by the execution threads at the *end* of each event) flow_id string // the messages of each thread, producing LogMessage, will have all the same unique flow_id. Messages by other threads will have other flow_id. If you use VJOBS=1 to serialise the execution, then all messages will have the same flow_id. took time.Duration // the duration of the event, that this message describes message string // the actual message text; the result of the event, that the message describes; most reporters could ignore this, since it could be reconstructed by the other fields } pub interface Reporter { mut: session_start(message string, mut ts TestSession) // called once per test session, in the main thread, suitable for setting up supporting infrastructure. session_stop(message string, mut ts TestSession) // called once per test session, in the main thread, after everything else, suitable for summaries, creating .xml reports, uploads etc. worker_threads_start(files []string, mut ts TestSession) // called once per test session, in the main thread, right before all the worker threads start worker_threads_finish(mut ts TestSession) // called once per test session, in the main thread, right after all the worker threads finish report(index int, log_msg LogMessage) // called once per each message, that will be shown (ok/fail/skip etc), only in the reporting thread. report_stop() // called just once after all messages are processed, only in the reporting thread, but before stop_session. // TODO: reconsider, whether the next methods, should be kept for all reporters, or just moved inside the normal reporter, to simplify the interface progress(index int, message string) update_last_line(index int, message string) update_last_line_and_move_to_next(index int, message string) message(index int, message string) divider() // called to show a long ---------- horizontal line; can be safely ignored in most reporters; used in the main thread. list_of_failed_commands(cmds []string) // called after all testing is done, to produce a small summary that only lists the failed commands, so that they can be retried manually if needed, without forcing the user to scroll and find them. } ================================================ FILE: cmd/tools/modules/testing/output_dump.v ================================================ module testing // DumpReporter implements the interface testing.Reporter. // It is used by `v -test-runner dump test .` pub struct DumpReporter { mut: files []string } // pub fn (mut r DumpReporter) worker_threads_start(files []string, mut ts TestSession) { eprintln('> ${@METHOD} | files: ${files}') r.files = files } pub fn (r DumpReporter) worker_threads_finish(mut ts TestSession) { eprintln('> ${@METHOD}') } // pub fn (r DumpReporter) session_start(message string, mut ts TestSession) { eprintln('> ${@METHOD} | message: ${message}') // dump(ts) } pub fn (r DumpReporter) session_stop(message string, mut ts TestSession) { eprintln('> ${@METHOD} | message: ${message}') } // pub fn (r DumpReporter) report(index int, message LogMessage) { eprintln('> ${@METHOD} | index: ${index} | message: ${message}') } pub fn (r DumpReporter) report_stop() { eprintln('> ${@METHOD}') } pub fn (r DumpReporter) progress(index int, message string) { eprintln('> ${@METHOD} | index: ${index} | message: ${message}') } pub fn (r DumpReporter) update_last_line(index int, message string) { eprintln('> ${@METHOD} | index: ${index} | message: ${message}') } pub fn (r DumpReporter) update_last_line_and_move_to_next(index int, message string) { eprintln('> ${@METHOD} | index: ${index} | message: ${message}') } pub fn (r DumpReporter) message(index int, message string) { eprintln('> ${@METHOD} | index: ${index} | message: ${message}') } pub fn (r DumpReporter) divider() { eprintln('> ${@METHOD}') } pub fn (r DumpReporter) list_of_failed_commands(failed_cmds []string) { eprintln('> ${@METHOD} | failed_cmds: ${failed_cmds}') } ================================================ FILE: cmd/tools/modules/testing/output_normal.v ================================================ module testing import os import time import term import strings import runtime pub const empty = term.header(' ', ' ') // TODO: AGAIN --- this !!!*reliably*!!! fails compilation of `v cmd/tools/vbuild-examples.v` with a cgen error, without `-no-parallel`: // pub const report_running_period_ms = os.getenv_opt('VTEST_REPORT_RUNNING_PERIOD_MS') or { '60000' }.int() * time.millisecond pub const report_running_period_ms = get_report_running_period_ms() fn get_report_running_period_ms() time.Duration { return os.getenv_opt('VTEST_REPORT_RUNNING_PERIOD_MS') or { '300_000' }.int() * time.millisecond // 5 minutes by default } // NormalReporter implements the interface testing.Reporter. // It is used by default by `v test .` // It was extracted by the original non customiseable output implementation directly in cmd/tools/modules/testing/common.v pub struct NormalReporter { mut: vroot string runtime time.Duration comptime time.Duration nfiles int njobs int // running shared map[string]LogMessage compiling shared map[string]LogMessage rtimes shared []TaskDuration ctimes shared []TaskDuration } pub fn (mut r NormalReporter) session_start(message string, mut ts TestSession) { r.vroot = ts.vroot.replace('\\', '/') + '/' header(message) r.nfiles = ts.files.len r.njobs = runtime.nr_jobs() spawn r.report_current_running_and_compiling_status_periodically() } fn (r &NormalReporter) report_current_running_and_compiling_status_periodically() { if report_running_period_ms == 0 { return } mut start_t := time.now() mut pi := 0 mut ccompiling := map[string]LogMessage{} mut crunning := map[string]LogMessage{} mut sb := strings.new_builder(1024) for { pi++ time.sleep(report_running_period_ms) t := time.now() rlock r.compiling { ccompiling = r.compiling.clone() } rlock r.running { crunning = r.running.clone() } ckeys := ccompiling.keys() rkeys := crunning.keys() sb.writeln('') sb.writeln(' >>>>> ${t.format_ss_micro()} | period ${pi:2} | started: ${t - start_t:10} ago | vjobs: ${r.njobs} | _test.v files: ${r.nfiles:5} | C: ${ckeys.len:3} | R: ${rkeys.len:3}') for ik, k in ckeys { cval := ccompiling[k] sb.writeln(' >>>>> compiling ${ik + 1:2}/${ckeys.len:-2}, T: ${cval.flow_id:2}, started: ${t - cval.when:10} ago, `${k}`') } for ik, k in rkeys { cval := crunning[k] sb.writeln(' >>>>> running ${ik + 1:2}/${rkeys.len:-2}, T: ${cval.flow_id:2}, started: ${t - cval.when:10} ago, `${k}`') } sb.writeln('') eprint(sb.str()) // write everything at once, to minimise the chance of interference with the normal output of `v test` } } fn (r &NormalReporter) show_longest(label string, limit int, kind TaskKind) { if limit <= 0 { return } println('> Longest ${limit} by ${label}:') mut tasks := []TaskDuration{cap: r.nfiles} match kind { .comptime { rlock r.ctimes { tasks << r.ctimes } } .runtime { rlock r.rtimes { tasks << r.rtimes } } .totaltime { mut tall := []TaskDuration{} rlock r.rtimes { tall << r.rtimes } rlock r.ctimes { tall << r.ctimes } mut mall := map[string]TaskDuration{} for task in tall { if current := mall[task.path] { mall[task.path].duration = current.duration + task.duration continue } mall[task.path] = task } tasks = mall.values() } } tasks.sort(a.duration > b.duration) for tidx, task in tasks { npath := task.path.replace('\\', '/').replace(r.vroot, '') println(' ${tidx + 1:3} | ${task.duration:10s} | ${npath}') if tidx + 1 >= limit { break } } } pub fn (r &NormalReporter) session_stop(message string, mut ts TestSession) { r.show_longest('compilation time', show_longest_by_comptime, .comptime) r.show_longest('run time', show_longest_by_runtime, .runtime) r.show_longest('total time', show_longest_by_totaltime, .totaltime) println('${ts.benchmark.total_message(message)} Comptime: ${r.comptime.microseconds() / 1000} ms. Runtime: ${r.runtime.microseconds() / 1000} ms.') } // the most general form; it may be useful for other reporters // in the normal one, it currently does nothing pub fn (mut r NormalReporter) report(index int, message LogMessage) { // eprintln('> ${@METHOD} index: ${index} | message: ${message}') if message.kind == .compile_begin { lock r.compiling { r.compiling[message.file] = message } } if message.kind == .compile_end { r.comptime += message.took lock r.ctimes { r.ctimes << TaskDuration{message.file, message.took} } lock r.compiling { r.compiling.delete(message.file) } } if message.kind == .cmd_end { lock r.rtimes { r.rtimes << TaskDuration{message.file, message.took} } r.runtime += message.took } if message.kind == .cmd_begin { lock r.running { r.running[message.file] = message } } if message.kind == .cmd_end { lock r.running { r.running.delete(message.file) } } } pub fn (r NormalReporter) report_stop() { // eprintln('> ${@METHOD}') eprintln('') } // progress will show the given message normally // TODO: reconsider if these should be public: pub fn (r NormalReporter) progress(index int, message string) { eprintln(message) } // in progress mode, the last line will be rewritten many times, and does not end with \n // the \n will be printed just once when some progress has been made. pub fn (r NormalReporter) update_last_line(index int, message string) { print('\r${empty}\r${message}') flush_stdout() } pub fn (r NormalReporter) update_last_line_and_move_to_next(index int, message string) { // the last \n is needed, so SKIP/FAIL messages // will not get overwritten by the OK ones eprint('\r${empty}\r${message}\n') } pub fn (r NormalReporter) message(index int, message string) { eprintln(message) } pub fn (r NormalReporter) divider() { h_divider() } // pub fn (r NormalReporter) worker_threads_start(files []string, mut ts TestSession) { // eprintln('> ${@METHOD}') } pub fn (r NormalReporter) worker_threads_finish(mut ts TestSession) { // eprintln('> ${@METHOD}') } pub fn (r NormalReporter) list_of_failed_commands(failed_cmds []string) { for i, cmd in failed_cmds { eprintln(term.failed('To reproduce just failure ${i + 1} run:') + ' ${cmd}') } if failed_cmds.len > 0 { vflags := os.getenv('VFLAGS') if vflags != '' { eprintln(term.failed('VFLAGS was: "${vflags}"')) } } } enum TaskKind { comptime runtime totaltime } struct TaskDuration { mut: path string duration time.Duration } ================================================ FILE: cmd/tools/modules/testing/output_teamcity.v ================================================ module testing // TeamcityReporter implements the interface `testing.Reporter`. // It is used by `v -test-runner teamcity test .` pub struct TeamcityReporter { } pub fn (r TeamcityReporter) session_start(message string, mut ts TestSession) { } pub fn (r TeamcityReporter) session_stop(message string, mut ts TestSession) { } pub fn (r TeamcityReporter) report(index int, message LogMessage) { name := r.get_test_suite_name_by_file(message.file) match message.kind { .cmd_begin { eprintln("##teamcity[testSuiteStarted name='${name}' flowId='${message.flow_id}']") } .cmd_end { eprintln("##teamcity[testSuiteFinished name='${name}' flowId='${message.flow_id}' duration='${message.took}']") } .cannot_compile { eprintln("##teamcity[testFailed name='${name}' message='${message.message}']") } else {} } } pub fn (r TeamcityReporter) get_test_suite_name_by_file(path string) string { file_name := path.replace('\\', '/').split('/').last() return file_name.split('.').first() } pub fn (r TeamcityReporter) report_stop() { } pub fn (r TeamcityReporter) progress(index int, message string) { } pub fn (r TeamcityReporter) update_last_line(index int, message string) { } pub fn (r TeamcityReporter) update_last_line_and_move_to_next(index int, message string) { } pub fn (r TeamcityReporter) message(index int, message string) { } pub fn (r TeamcityReporter) divider() { } pub fn (r TeamcityReporter) worker_threads_start(files []string, mut ts TestSession) { } pub fn (r TeamcityReporter) worker_threads_finish(mut ts TestSession) { } pub fn (r TeamcityReporter) list_of_failed_commands(failed_cmds []string) { } ================================================ FILE: cmd/tools/modules/vgit/vgit.v ================================================ module vgit import os import flag import scripting pub fn check_v_commit_timestamp_before_self_rebuilding(v_timestamp u64) { if v_timestamp >= 1561805697 { return } eprintln('##################################################################') eprintln('# WARNING: v self rebuilding, before 5b7a1e8 (2019-06-29 12:21) #') eprintln('# required the v executable to be built *inside* #') eprintln('# the toplevel compiler/ folder. #') eprintln('# #') eprintln('# That is not supported by this tool. #') eprintln('# You will have to build it manually there. #') eprintln('##################################################################') } pub fn validate_commit_exists(commit string) { if commit != '' { return } cmd := 'git cat-file -t "${commit}" ' // windows's cmd.exe does not support ' for quoting if !scripting.exit_0_status(cmd) { eprintln('Commit: "${commit}" does not exist in the current repository.') exit(3) } } pub fn line_to_timestamp_and_commit(line string) (u64, string) { parts := line.split(' ') return parts[0].u64(), parts[1] } pub fn normalized_workpath_for_commit(workdir string, commit string) string { nc := 'v_at_' + commit.replace('^', '_').replace('-', '_').replace('/', '_') return os.real_path(workdir + os.path_separator + nc) } fn get_current_folder_commit_hash() string { vline := scripting.run('git rev-list -n1 --timestamp HEAD') _, v_commithash := line_to_timestamp_and_commit(vline) return v_commithash } @[noreturn] fn fatal_error(error IError, label string) { eprintln('error: ${label}') eprintln(error) exit(1) } @[noreturn] fn co_fail(error IError, commit string) { fatal_error(error, 'git could not checkout `${commit}`') } @[noreturn] fn net_fail(error IError, what string) { fatal_error(error, 'git failed at `${what}`') } pub fn prepare_vc_source(vcdir string, cdir string, commit string) (string, string, u64) { scripting.chdir(cdir) // Building a historic v with the latest vc is not always possible ... // It is more likely, that the vc *at the time of the v commit*, // or slightly before that time will be able to build the historic v: vline := scripting.run('git rev-list -n1 --timestamp "${commit}" ') v_timestamp, v_commithash := line_to_timestamp_and_commit(vline) scripting.verbose_trace(@FN, 'v_timestamp: ${v_timestamp} | v_commithash: ${v_commithash}') check_v_commit_timestamp_before_self_rebuilding(v_timestamp) scripting.chdir(vcdir) scripting.frun('git checkout --quiet master') or { co_fail(err, 'master') } mut vccommit := '' mut partial_hash := v_commithash[0..7] if '5b7a1e8'.starts_with(partial_hash) { // we need the following, otherwise --grep= below would find a93ef6e, which does include 5b7a1e8 in the commit message ... 🤦‍♂️ partial_hash = '5b7a1e84a4d283071d12cb86dc17aeda9b5306a8' } vcbefore_subject_match := scripting.run('git rev-list HEAD -n1 --timestamp --grep=${partial_hash} ') scripting.verbose_trace(@FN, 'vcbefore_subject_match: ${vcbefore_subject_match}') if vcbefore_subject_match.len > 3 { _, vccommit = line_to_timestamp_and_commit(vcbefore_subject_match) } else { scripting.verbose_trace(@FN, 'the v commit did not match anything in the vc log; try --timestamp instead.') vcbefore := scripting.run('git rev-list HEAD -n1 --timestamp --before=${v_timestamp} ') _, vccommit = line_to_timestamp_and_commit(vcbefore) } scripting.verbose_trace(@FN, 'vccommit: ${vccommit}') scripting.frun('git checkout --quiet "${vccommit}" ') or { co_fail(err, vccommit) } scripting.run('wc *.c') scripting.chdir(cdir) return v_commithash, vccommit, v_timestamp } pub fn clone_or_pull(remote_git_url string, local_worktree_path string) { // Note: after clone_or_pull, the current repo branch is === HEAD === master if os.is_dir(local_worktree_path) && os.is_dir(os.join_path_single(local_worktree_path, '.git')) { // Already existing ... Just pulling in this case is faster usually. scripting.frun('git -C "${local_worktree_path}" checkout --quiet master') or { co_fail(err, 'master') } scripting.frun('git -C "${local_worktree_path}" pull --quiet ') or { net_fail(err, 'pulling') } } else { // Clone a fresh local tree. if remote_git_url.starts_with('http') { // cloning an https remote with --filter=blob:none is usually much less bandwidth intensive, at the // expense of doing small network ops later when using checkouts. scripting.frun('git clone --filter=blob:none --quiet "${remote_git_url}" "${local_worktree_path}" ') or { net_fail(err, 'cloning') } return } mut is_blobless_clone := false remote_git_config_path := os.join_path(remote_git_url, '.git', 'config') if os.is_dir(remote_git_url) && os.is_file(remote_git_config_path) { lines := os.read_lines(remote_git_config_path) or { [] } is_blobless_clone = lines.any(it.contains('partialclonefilter = blob:none')) } if is_blobless_clone { // Note: // 1) cloning a *local folder* with `--filter=blob:none`, that *itself* was cloned with `--filter=blob:none` // leads to *extremely* slow checkouts for older commits later. It takes hours instead of milliseconds, for a commit // that is just several thousands of commits old :( . // // 2) Cloning it *without* the `--filter=blob:none`, leads to `error: unable to read sha1 file of`, later, // when checking out the older commits, depending on the local git client version (tested with git version 2.41.0). // // 3) => instead of cloning, it is much faster, and *bug free*, to just rsync the local repo directly, // at the expense of a little more space usage, which will make the new tree in local_worktree_path, // exactly 1:1 the same, as the one in remote_git_url, just independent from it . copy_cmd := if os.user_os() == 'windows' { 'robocopy /MIR' } else { 'rsync -a' } scripting.frun('${copy_cmd} "${remote_git_url}/" "${local_worktree_path}/"') or { fatal_error(err, 'copying to ${local_worktree_path}') } return } scripting.frun('git clone --quiet "${remote_git_url}" "${local_worktree_path}" ') or { net_fail(err, 'cloning') } } } pub struct VGitContext { pub: cc string = 'cc' // what C compiler to use for bootstrapping cc_options string // what additional C compiler options to use for bootstrapping workdir string = '/tmp' // the base working folder commit_v string = 'master' // the commit-ish that needs to be prepared path_v string // where is the local working copy v repo path_vc string // where is the local working copy vc repo v_repo_url string // the remote v repo URL vc_repo_url string // the remote vc repo URL pub mut: // these will be filled by vgitcontext.compile_oldv_if_needed() commit_v__hash string // the git commit of the v repo that should be prepared commit_vc_hash string // the git commit of the vc repo, corresponding to commit_v__hash commit_v__ts u64 // unix timestamp, that corresponds to commit_v__hash; filled by prepare_vc_source vexename string // v or v.exe vexepath string // the full absolute path to the prepared v/v.exe vvlocation string // v.v or compiler/ or cmd/v, depending on v version make_fresh_tcc bool // whether to do 'make fresh_tcc' before compiling an old V. show_vccommit bool // show the V and VC commits, corresponding to the V commit-ish, that can be used to build V } pub fn (mut vgit_context VGitContext) compile_oldv_if_needed() { vgit_context.vexename = if os.user_os() == 'windows' { 'v.exe' } else { 'v' } vgit_context.vexepath = os.real_path(os.join_path_single(vgit_context.path_v, vgit_context.vexename)) if os.is_dir(vgit_context.path_v) && os.is_executable(vgit_context.vexepath) && !vgit_context.show_vccommit { // already compiled, no need to compile that specific v executable again vgit_context.commit_v__hash = get_current_folder_commit_hash() return } scripting.chdir(vgit_context.workdir) clone_or_pull(vgit_context.v_repo_url, vgit_context.path_v) clone_or_pull(vgit_context.vc_repo_url, vgit_context.path_vc) scripting.chdir(vgit_context.path_v) scripting.frun('git checkout --quiet ${vgit_context.commit_v}') or { co_fail(err, vgit_context.commit_v) } if os.is_dir(vgit_context.path_v) && os.exists(vgit_context.vexepath) && !vgit_context.show_vccommit { // already compiled, so no need to compile v again vgit_context.commit_v__hash = get_current_folder_commit_hash() return } v_commithash, vccommit_before, v_timestamp := prepare_vc_source(vgit_context.path_vc, vgit_context.path_v, 'HEAD') vgit_context.commit_v__hash = v_commithash vgit_context.commit_v__ts = v_timestamp vgit_context.commit_vc_hash = vccommit_before if vgit_context.show_vccommit { println('VHASH=${vgit_context.commit_v__hash}') println('VCHASH=${vgit_context.commit_vc_hash}') exit(0) } if os.exists('cmd/v') { vgit_context.vvlocation = 'cmd/v' } else { vgit_context.vvlocation = if os.exists('v.v') { 'v.v' } else { 'compiler' } } if os.is_dir(vgit_context.path_v) && os.exists(vgit_context.vexepath) { // already compiled, so no need to compile v again return } scripting.chdir(vgit_context.path_v) // Recompilation is needed. Just to be sure, clean up everything first. scripting.run('git clean -xf') if vgit_context.make_fresh_tcc { scripting.run('make fresh_tcc') } // compiling the C sources with a C compiler: mut command_for_building_v_from_c_source := '' mut command_for_selfbuilding := '' mut c_flags := '-std=gnu11 -I ./thirdparty/stdatomic/nix -w' mut c_ldflags := '-lm -lpthread' mut vc_source_file_location := os.join_path_single(vgit_context.path_vc, 'v.c') mut vc_v_cpermissive_flags := '${vgit_context.cc_options} -Wno-error=incompatible-pointer-types -Wno-error=implicit-function-declaration -Wno-error=int-conversion -fpermissive' // after 85b58b0 2021-09-28, -no-parallel is supported, and can be used to force the cgen stage to be single threaded, which increases the chances of successful bootstraps mut vc_v_bootstrap_flags := '' if vgit_context.commit_v__ts >= 1632778086 { vc_v_bootstrap_flags += ' -no-parallel' } vc_v_bootstrap_flags = vc_v_bootstrap_flags.trim_space() scripting.verbose_trace(@FN, 'vc_v_bootstrap_flags: ${vc_v_bootstrap_flags}') scripting.verbose_trace(@FN, 'vc_v_cpermissive_flags: ${vc_v_cpermissive_flags}') scripting.verbose_trace(@FN, 'vgit_context.commit_v__ts: ${vgit_context.commit_v__ts}') if 'windows' == os.user_os() { c_flags = '-std=c99 -I ./thirdparty/stdatomic/win -w' c_ldflags = '' v_win_c_location := os.join_path_single(vgit_context.path_vc, 'v_win.c') if os.exists(v_win_c_location) { vc_source_file_location = v_win_c_location } } if 'windows' == os.user_os() { if vgit_context.commit_v__ts >= 1589793086 && vgit_context.cc.contains('gcc') { // after 53ffee1 2020-05-18, gcc builds on windows do need `-municode` c_flags += '-municode' } // after 2023-11-07, windows builds need linking to ws2_32: if vgit_context.commit_v__ts >= 1699341818 && !vgit_context.cc.contains('msvc') { c_flags += '-lws2_32' } command_for_building_v_from_c_source = c(vgit_context.cc, '${vc_v_cpermissive_flags} ${c_flags} -o cv.exe "${vc_source_file_location}" ${c_ldflags}') command_for_selfbuilding = c('.\\cv.exe', '${vc_v_bootstrap_flags} -cflags "${vc_v_cpermissive_flags}" -o ${vgit_context.vexename} {SOURCE}') } else { command_for_building_v_from_c_source = c(vgit_context.cc, '${vc_v_cpermissive_flags} ${c_flags} -o cv "${vc_source_file_location}" ${c_ldflags}') command_for_selfbuilding = c('./cv', '${vc_v_bootstrap_flags} -cflags "${vc_v_cpermissive_flags}" -o ${vgit_context.vexename} {SOURCE}') } scripting.run(command_for_building_v_from_c_source) build_cmd := command_for_selfbuilding.replace('{SOURCE}', vgit_context.vvlocation) scripting.run(build_cmd) // At this point, there exists a file vgit_context.vexepath // which should be a valid working V executable. } fn c(cmd string, params string) string { // compose a command, while reducing the potential whitespaces, due to all the interpolations of optional flags above return '${cmd} ${params.trim_space()}' } pub struct VGitOptions { pub mut: workdir string = os.temp_dir() // the working folder (typically /tmp), where the tool will write v_repo_url string // the url of the V repository. It can be a local folder path, if you want to eliminate network operations... vc_repo_url string // the url of the vc repository. It can be a local folder path, if you want to eliminate network operations... show_help bool // whether to show the usage screen verbose bool // should the tool be much more verbose } pub fn add_common_tool_options(mut context VGitOptions, mut fp flag.FlagParser) []string { context.workdir = os.real_path(fp.string('workdir', `w`, context.workdir, 'A writable base folder. Default: ${context.workdir}')) context.v_repo_url = fp.string('vrepo', 0, context.v_repo_url, 'The url of the V repository. You can clone it locally too. See also --vcrepo below.') context.vc_repo_url = fp.string('vcrepo', 0, context.vc_repo_url, 'The url of the vc repository. You can clone it ${flag.space}beforehand, and then just give the local folder ${flag.space}path here. That will eliminate the network ops ${flag.space}done by this tool, which is useful, if you want ${flag.space}to script it/run it in a restrictive vps/docker. ') context.show_help = fp.bool('help', `h`, false, 'Show this help screen.') context.verbose = fp.bool('verbose', `v`, false, 'Be more verbose.') if context.show_help { println(fp.usage()) exit(0) } if context.verbose { scripting.set_verbose(true) } if os.is_dir(context.v_repo_url) { context.v_repo_url = os.real_path(context.v_repo_url) } if os.is_dir(context.vc_repo_url) { context.vc_repo_url = os.real_path(context.vc_repo_url) } commits := fp.finalize() or { eprintln('Error: ${err}') exit(1) } for commit in commits { validate_commit_exists(commit) } return commits } ================================================ FILE: cmd/tools/oldv.v ================================================ import os import flag import scripting import vgit const tool_version = '0.0.4' const tool_description = ' Checkout an old version of V and compile it as it was on a specific commit. | This tool is useful when you want to discover when something broke. | It is also useful when you just want to experiment with an older, historic V. | | The VCOMMIT argument can be a git commit object like HEAD or master and so on. | When oldv is used with git bisect, you probably want to use HEAD. For example: | git bisect start | git bisect bad | git checkout known_good_commit | git bisect good | ## git will automatically checkout a middle commit between the bad and the good | cmd/tools/oldv --bisect --command="run commands in oldv folder, to verify if the commit is good or bad | ## Examine the results, and either do: ... | git bisect good | ## ... or do: | git bisect bad | ## Repeat the above steps, each time running oldv with the same command, then mark the result as good | ## or bad until you find the commit where the problem first occurred. | ## When you finish, do not forget to do: | git bisect reset'.strip_margin() struct Context { mut: vgo vgit.VGitOptions vgcontext vgit.VGitContext commit_v string = 'master' // the commit from which you want to produce a working v compiler (this may be a commit-ish too) commit_v_hash string // this will be filled from the commit-ish commit_v using rev-list. It IS a commit hash. path_v string // the full path to the v folder inside workdir. path_vc string // the full path to the vc folder inside workdir. cmd_to_run string // the command that you want to run *in* the oldv repo cleanup bool // should the tool run a cleanup first use_cache bool // use local cached copies for --vrepo and --vcrepo in fresh_tcc bool // do use `make fresh_tcc` is_bisect bool // bisect mode; usage: `cmd/tools/oldv -b -c './v run bug.v'` show_vccommit bool // show the V and VC commits, corresponding to the V commit-ish, that can be used to build V cc string = 'cc' // the C compiler to use for bootstrapping. cc_options string // additional options to pass to the C compiler while bootstrapping. } fn (mut c Context) compile_oldv_if_needed() { c.vgcontext = vgit.VGitContext{ workdir: c.vgo.workdir v_repo_url: c.vgo.v_repo_url vc_repo_url: c.vgo.vc_repo_url cc: c.cc cc_options: c.cc_options commit_v: c.commit_v path_v: c.path_v path_vc: c.path_vc make_fresh_tcc: c.fresh_tcc show_vccommit: c.show_vccommit } c.vgcontext.compile_oldv_if_needed() c.commit_v_hash = c.vgcontext.commit_v__hash if !os.exists(c.vgcontext.vexepath) && c.cmd_to_run.len > 0 { // Note: 125 is a special code, that git bisect understands as 'skip this commit'. // it is used to inform git bisect that the current commit leads to a build failure. exit(125) } } const cache_oldv_folder = os.join_path(os.cache_dir(), 'oldv') const cache_oldv_folder_v = os.join_path(cache_oldv_folder, 'v') const cache_oldv_folder_vc = os.join_path(cache_oldv_folder, 'vc') fn sync_cache() { scripting.verbose_trace(@FN, 'start') if !os.exists(cache_oldv_folder) { scripting.verbose_trace(@FN, 'creating ${cache_oldv_folder}') scripting.mkdir_all(cache_oldv_folder) or { scripting.verbose_trace(@FN, '## failed.') exit(1) } } scripting.chdir(cache_oldv_folder) for reponame in ['v', 'vc'] { repofolder := os.join_path(cache_oldv_folder, reponame) if !os.exists(repofolder) { scripting.verbose_trace(@FN, 'cloning to ${repofolder}') mut repo_options := '' if reponame == 'vc' { repo_options = '--filter=blob:none' } scripting.exec('git clone ${repo_options} --quiet https://github.com/vlang/${reponame} ${repofolder}') or { scripting.verbose_trace(@FN, '## error during clone: ${err}') exit(1) } } scripting.chdir(repofolder) scripting.exec('git pull --quiet') or { scripting.verbose_trace(@FN, 'pulling to ${repofolder}') scripting.verbose_trace(@FN, '## error during pull: ${err}') exit(1) } } scripting.verbose_trace(@FN, 'done') } fn main() { if os.user_os() == 'windows' { scripting.used_tools_must_exist(['git', 'wc', 'make', 'robocopy']) } else { scripting.used_tools_must_exist(['git', 'wc', 'make', 'rsync', 'cc']) } // Resetting VEXE here allows for `v run cmd/tools/oldv.v'. // the parent V would have set VEXE, which later will // affect the V's run from the tool itself. os.setenv('VEXE', '', true) mut context := Context{} context.vgo.workdir = cache_oldv_folder mut fp := flag.new_flag_parser(os.args) fp.application(os.file_name(os.executable())) fp.version(tool_version) fp.description(tool_description) fp.arguments_description('VCOMMIT') fp.skip_executable() context.use_cache = fp.bool('cache', `u`, true, 'Use a cache of local repositories for --vrepo and --vcrepo in \$HOME/.cache/oldv/') if context.use_cache { context.vgo.v_repo_url = cache_oldv_folder_v context.vgo.vc_repo_url = cache_oldv_folder_vc } else { context.vgo.v_repo_url = 'https://github.com/vlang/v' context.vgo.vc_repo_url = 'https://github.com/vlang/vc' } context.cc = fp.string('cc', 0, 'cc', 'Use this C compiler for bootstrapping v.c (defaults to `cc`).') context.cc_options = fp.string('ccoptions', 0, '', 'Use these C compiler options for bootstrapping v.c (defaults to ``).') env_cc_options := os.getenv('OLDV_CCOPTIONS') if env_cc_options != '' { context.cc_options = env_cc_options } context.cleanup = fp.bool('clean', 0, false, 'Clean before running (slower).') context.fresh_tcc = fp.bool('fresh_tcc', 0, true, 'Do `make fresh_tcc` when preparing a V compiler.') context.cmd_to_run = fp.string('command', `c`, '', 'Command to run in the old V repo.\n') context.show_vccommit = fp.bool('show_VC_commit', 0, false, 'Show the VC commit, that can be used to compile the given V commit, and exit.\n') context.is_bisect = fp.bool('bisect', `b`, false, 'Bisect mode. Use the current commit in the repo where oldv is.') should_sync := fp.bool('cache-sync', `s`, false, 'Update the local cache') if !should_sync && !context.is_bisect { fp.limit_free_args(1, 1)! } //// commits := vgit.add_common_tool_options(mut context.vgo, mut fp) if should_sync { sync_cache() println('Cache synced, cache folder: ${cache_oldv_folder} .') exit(0) } if context.use_cache { if !os.is_dir(cache_oldv_folder_v) || !os.is_dir(cache_oldv_folder_vc) { sync_cache() } } if commits.len > 0 { context.commit_v = commits[0] if context.is_bisect { eprintln('In bisect mode, you should not pass any commits, since oldv will use the current one.') exit(2) } } else { context.commit_v = scripting.run('git rev-list -n1 HEAD') } if !context.show_vccommit { scripting.cprintln('################# context.commit_v: ${context.commit_v} #####################') } context.path_v = vgit.normalized_workpath_for_commit(context.vgo.workdir, context.commit_v) context.path_vc = vgit.normalized_workpath_for_commit(context.vgo.workdir, 'vc') if !os.is_dir(context.vgo.workdir) { eprintln('Work folder: ${context.vgo.workdir} , does not exist.') exit(2) } ecc := os.getenv('CC') if ecc != '' { context.cc = ecc } if context.cleanup { scripting.rmrf(context.path_v) scripting.rmrf(context.path_vc) } context.compile_oldv_if_needed() scripting.chdir(context.path_v) shorter_hash := context.commit_v_hash[0..10] scripting.cprintln('# v commit hash: ${shorter_hash} | folder: ${context.path_v}') if context.cmd_to_run.len > 0 { scripting.cprintln_strong('# command: ${context.cmd_to_run:-34s}') cmdres := os.execute_or_exit(context.cmd_to_run) if cmdres.exit_code != 0 { scripting.cprintln_strong('# exit code: ${cmdres.exit_code:-4d}') } scripting.cprint_strong('# result: ') print(cmdres.output) if !cmdres.output.ends_with('\n') { println('') } exit(cmdres.exit_code) } } ================================================ FILE: cmd/tools/performance_compare.v ================================================ import os import flag import scripting import vgit const tool_version = '0.0.6' const tool_description = " Compares V executable size and performance, | between 2 commits from V's local git history. | When only one commit is given, it is compared to master. | ".strip_margin() struct Context { cwd string // current working folder mut: vgo vgit.VGitOptions a string // the full path to the 'after' folder inside workdir b string // the full path to the 'before' folder inside workdir vc string // the full path to the vc folder inside workdir. It is used during bootstrapping v from the C source. commit_before string // the git commit for the 'before' state commit_after string // the git commit for the 'after' state warmups int // how many times to execute a command before gathering stats hyperfineopts string // use for additional CLI options that will be given to the hyperfine command vflags string // other v options to pass to compared v commands } fn new_context() Context { return Context{ cwd: os.getwd() commit_after: 'master' warmups: 4 } } fn (c Context) compare_versions() { // Input is validated at this point... // Cleanup artifacts from previous runs of this tool: scripting.chdir(c.vgo.workdir) scripting.run('rm -rf "${c.a}" "${c.b}" "${c.vc}" ') // clone the VC source *just once per comparison*, and reuse it: scripting.run('git clone --filter=blob:none --quiet "${c.vgo.vc_repo_url}" "${c.vc}" ') println('Comparing V performance of commit ${c.commit_before} (before) vs commit ${c.commit_after} (after) ...') c.prepare_v(c.b, c.commit_before) c.prepare_v(c.a, c.commit_after) scripting.chdir(c.vgo.workdir) if c.vflags.len > 0 { os.setenv('VFLAGS', c.vflags, true) } // The first is the baseline, against which all the others will be compared. // It is the fastest, since hello_world.v has only a single println in it, mut perf_files := []string{} perf_files << c.compare_v_performance('source_hello', [ 'vprod @DEBUG@ -o source.c examples/hello_world.v', 'vprod -o source.c examples/hello_world.v', 'v @DEBUG@ -o source.c examples/hello_world.v', 'v -o source.c examples/hello_world.v', ]) perf_files << c.compare_v_performance('source_v', [ 'vprod @DEBUG@ -o source.c @COMPILER@', 'vprod -o source.c @COMPILER@', 'v @DEBUG@ -o source.c @COMPILER@', 'v -o source.c @COMPILER@', ]) perf_files << c.compare_v_performance('binary_hello', [ 'vprod -o hello examples/hello_world.v', 'v -o hello examples/hello_world.v', ]) perf_files << c.compare_v_performance('binary_v', [ 'vprod -o binary @COMPILER@', 'v -o binary @COMPILER@', ]) println('All performance files:') for f in perf_files { println(' ${f}') } } fn (c &Context) prepare_v(cdir string, commit string) { mut cc := os.getenv('CC') if cc == '' { cc = 'cc' } mut vgit_context := vgit.VGitContext{ cc: cc commit_v: commit path_v: cdir path_vc: c.vc workdir: c.vgo.workdir v_repo_url: c.vgo.v_repo_url vc_repo_url: c.vgo.vc_repo_url } vgit_context.compile_oldv_if_needed() scripting.chdir(cdir) scripting.run('${cdir}/v version') println('Making a v compiler in ${cdir}') scripting.run('./v -cc ${cc} -o v ${vgit_context.vvlocation}') println('Making a vprod compiler in ${cdir}') scripting.run('./v -cc ${cc} -prod -o vprod ${vgit_context.vvlocation}') println('Stripping and compressing cv v and vprod binaries in ${cdir}') scripting.run('cp cv cv_stripped') scripting.run('cp v v_stripped') scripting.run('cp vprod vprod_stripped') scripting.run('strip *_stripped') scripting.run('cp cv_stripped cv_stripped_upxed') scripting.run('cp v_stripped v_stripped_upxed') scripting.run('cp vprod_stripped vprod_stripped_upxed') scripting.run('upx -qqq --lzma cv_stripped_upxed') scripting.run('upx -qqq --lzma v_stripped_upxed') scripting.run('upx -qqq --lzma vprod_stripped_upxed') scripting.show_sizes_of_files(['${cdir}/cv', '${cdir}/cv_stripped', '${cdir}/cv_stripped_upxed']) scripting.show_sizes_of_files(['${cdir}/v', '${cdir}/v_stripped', '${cdir}/v_stripped_upxed']) scripting.show_sizes_of_files(['${cdir}/vprod', '${cdir}/vprod_stripped', '${cdir}/vprod_stripped_upxed']) vversion := scripting.run('${cdir}/v -version') vcommit := scripting.run('git rev-parse --short --verify HEAD') println('V version is: ${vversion} , local source commit: ${vcommit}') if vgit_context.vvlocation == 'cmd/v' { if os.exists('vlib/v/ast/ast.v') { println('Source lines of the compiler: ' + scripting.run('find cmd/v/ vlib/v/ -name "*.v" | grep -v /tests/ | xargs wc | tail -n -1')) } else { println('Source lines of the compiler: ' + scripting.run('wc cmd/v/*.v vlib/compiler/*.v | tail -n -1')) } } else if vgit_context.vvlocation == 'v.v' { println('Source lines of the compiler: ' + scripting.run('wc v.v vlib/compiler/*.v | tail -n -1')) } else { println('Source lines of the compiler: ' + scripting.run('wc compiler/*.v | tail -n -1')) } } fn (c Context) compare_v_performance(label string, commands []string) string { println('---------------------------------------------------------------------------------') println('Compare v performance when doing the following commands (${label}):') mut source_location_a := '' mut source_location_b := '' if os.exists('${c.a}/cmd/v') { source_location_a = 'cmd/v' } else { source_location_a = if os.exists('${c.a}/v.v') { 'v.v ' } else { 'compiler/ ' } } if os.exists('${c.b}/cmd/v') { source_location_b = 'cmd/v' } else { source_location_b = if os.exists('${c.b}/v.v') { 'v.v ' } else { 'compiler/ ' } } timestamp_a, _ := vgit.line_to_timestamp_and_commit(scripting.run('cd ${c.a}/ ; git rev-list -n1 --timestamp HEAD')) timestamp_b, _ := vgit.line_to_timestamp_and_commit(scripting.run('cd ${c.b}/ ; git rev-list -n1 --timestamp HEAD')) // 1570877641 is 065ce39 2019-10-12 debug_option_a := if timestamp_a > 1570877641 { '-cg ' } else { '-debug ' } debug_option_b := if timestamp_b > 1570877641 { '-cg ' } else { '-debug ' } mut hyperfine_commands_arguments := []string{} for cmd in commands { println(cmd) } for cmd in commands { hyperfine_commands_arguments << ' \'cd ${c.b:-34s} ; ./${cmd} \' '.replace_each([ '@COMPILER@', source_location_b, '@DEBUG@', debug_option_b, ]) } for cmd in commands { hyperfine_commands_arguments << ' \'cd ${c.a:-34s} ; ./${cmd} \' '.replace_each([ '@COMPILER@', source_location_a, '@DEBUG@', debug_option_a, ]) } // ///////////////////////////////////////////////////////////////////////////// cmd_stats_file := os.real_path([c.vgo.workdir, 'v_performance_stats_${label}.json'].join(os.path_separator)) comparison_cmd := 'hyperfine ${c.hyperfineopts} ' + '--export-json ${cmd_stats_file} ' + '--time-unit millisecond ' + '--style full --warmup ${c.warmups} ' + hyperfine_commands_arguments.join(' ') // ///////////////////////////////////////////////////////////////////////////// if c.vgo.verbose { println(comparison_cmd) } os.system(comparison_cmd) println('The detailed performance comparison report was saved to: ${cmd_stats_file} .') println('') return cmd_stats_file } fn main() { // allow for `v run cmd/tools/performance_compare.v`, see oldv.v os.setenv('VEXE', '', true) scripting.used_tools_must_exist(['cp', 'rm', 'strip', 'make', 'git', 'upx', 'cc', 'wc', 'tail', 'find', 'xargs', 'hyperfine']) mut context := new_context() mut fp := flag.new_flag_parser(os.args) fp.application(os.file_name(os.executable())) fp.version(tool_version) fp.description(tool_description) fp.arguments_description('COMMIT_BEFORE [COMMIT_AFTER]') fp.skip_executable() fp.limit_free_args(1, 2)! context.vflags = fp.string('vflags', 0, '', 'Additional options to pass to the v commands, for example "-cc tcc"') context.hyperfineopts = fp.string('hyperfine_options', 0, '', 'Additional options passed to hyperfine. ${flag.space}For example on linux, you may want to pass: ${flag.space}--hyperfine_options "--prepare \'sync; echo 3 | sudo tee /proc/sys/vm/drop_caches\'" ') commits := vgit.add_common_tool_options(mut context.vgo, mut fp) context.commit_before = commits[0] if commits.len > 1 { context.commit_after = commits[1] } context.b = vgit.normalized_workpath_for_commit(context.vgo.workdir, context.commit_before) context.a = vgit.normalized_workpath_for_commit(context.vgo.workdir, context.commit_after) context.vc = vgit.normalized_workpath_for_commit(context.vgo.workdir, 'vc') if !os.is_dir(context.vgo.workdir) { eprintln('Work folder: `{context.vgo.workdir}` , does not exist. Use `--workdir /some/path` to set it.') exit(2) } context.compare_versions() } ================================================ FILE: cmd/tools/regress.v ================================================ import os import term import flag const tools_folder = os.real_path(os.dir(os.executable())) const oldvexe = fullpath(tools_folder, 'oldv') const oldv_source = fullpath(tools_folder, 'oldv.v') const vroot = os.real_path(os.dir(os.dir(tools_folder))) const vexe = fullpath(vroot, 'v') fn fullpath(folder string, fname string) string { return os.real_path(os.join_path_single(folder, exename(fname))) } fn exename(n string) string { if n.ends_with('.v') || os.user_os() != 'windows' { return n } return '${n}.exe' } struct Context { mut: old_commit string new_commit string command string } fn main() { mut fp := flag.new_flag_parser(os.args) mut context := Context{} fp.application(os.file_name(os.executable())) fp.version('0.0.2') fp.description('\n Find at what commit a regression occurred. To find when a regression happened (regression_bug.v should fail on master): ./v run cmd/tools/regress.v --old a7019ac --command " ./v run /abs/path/to/regression_bug.v" To find when a feature was implemented (feature.v should succeed on master): ./v run cmd/tools/regress.v --old a7019ac --command "! ./v run /abs/path/to/feature.v"') fp.skip_executable() context.new_commit = fp.string('new', `n`, 'master', 'The new commit, by default: master.') context.old_commit = fp.string('old', `o`, '', 'A known old commit, required (for it, COMMAND should exit with 0).') context.command = fp.string('command', `c`, '', 'A command to execute. Should exit with 0 for the *old* commits.') fp.finalize() or {} if context.old_commit == '' { eprintln('--old COMMIT is required') exit(1) } if context.command == '' { eprintln('--command "COMMAND" is required') exit(2) } if !os.exists(oldvexe) { if 0 != execute('${os.quoted_path(vexe)} -o ${os.quoted_path(oldvexe)} ${os.quoted_path(oldv_source)}') { panic('can not compile ${oldvexe}') } } os.execute('git checkout master') os.execute('git bisect reset') os.execute('git checkout ${context.new_commit}') os.execute('git bisect start') os.execute('git bisect new') os.execute('git checkout ${context.old_commit}') os.execute('git bisect old') println(term.colorize(term.bright_yellow, term.header('', '-'))) execute('git bisect run ${os.quoted_path(oldvexe)} --bisect -c "${context.command}"') println(term.colorize(term.bright_yellow, term.header('', '-'))) os.execute('git bisect reset') os.execute('git checkout master') } fn execute(cmd string) int { eprintln('### ${cmd}') return os.system(cmd) } ================================================ FILE: cmd/tools/report_v_module_folders_without_tests.v ================================================ module main import os const vexe = @VEXE const known_skip_patterns_env = os.getenv('VKNOWN_SKIP_PATTERNS') const known_folder_patterns_that_are_not_module_ones = [ 'vlib/sync/bench', '/tests', '/testdata', '/preludes_js', 'vlib/builtin/js', // TODO: fix compiler panic 'vlib/fontstash', // used by `gg` 'vlib/sokol/sfons', // used by `gg`, and by examples/sokol/fonts.v 'vlib/sokol/sapp', // used by `gg`, and many examples/ 'vlib/sokol/gfx', // used by `gg`, `x.ttf` 'vlib/sokol/sgl', // used by `gg` 'vlib/toml', // toml is well tested, even if the top level folder does not have _test.v files, the ones below do 'vlib/v/', // the compiler itself is well tested ] fn main() { mut places := if os.args.len > 1 { os.args#[1..] } else { eprintln('> check the current folder only by default ...') ['.'] } mut known_skip_patterns := known_folder_patterns_that_are_not_module_ones.clone() if known_skip_patterns_env != '' { known_skip_patterns = known_skip_patterns_env.split(',').filter(it != '') } for path in places { eprintln('> Checking folder: `${path}` ...') mut found := 0 files := os.walk_ext(path, '.v') mut v_files := map[string]int{} mut v_test_files := map[string]int{} for f in files { folder := os.to_slash(os.dir(f)) if known_skip_patterns.any(f.contains(it)) { continue } if f.ends_with('.v') { v_files[folder]++ } if f.ends_with('_test.v') { v_test_files[folder]++ } } eprintln('> Found ${v_files.len:5} potential V module folders (containing .v files).') for folder, n_v_files in v_files { n_test_v_files := v_test_files[folder] if n_v_files > 1 && n_test_v_files == 0 { println('> ${n_test_v_files:5} _test.v files, with ${n_v_files:5} .v files, in folder: ${folder}') compilation := os.execute('${os.quoted_path(vexe)} -shared -W -Wfatal-errors -check ${os.quoted_path(folder)}') if compilation.exit_code != 0 { eprintln('> ${folder} has parser/checker errors!') eprintln(compilation.output) } found++ } } eprintln('> Found ${found} module folders without _test.v files in `${path}` .') } } ================================================ FILE: cmd/tools/show_ancient_deprecations.v ================================================ import os import term import time struct Context { mut: cut_time time.Time deprecations int } fn (mut ctx Context) analyze_line(line string, position_file string, position_line int) { blame_for_time := os.execute('git blame -L${position_line} --porcelain -- ${position_file}') if blame_for_time.exit_code != 0 { return } ts := blame_for_time.output.all_after('committer-time').all_before('\n').trim_space().int() t := time.unix(ts) if ctx.cut_time < t { println(term.colorize(term.gray, '>>> SKIPPING since t: ${t} > ${ctx.cut_time}, ${position_file}:${position_line}: ${line}')) return } ctx.deprecations++ blame_for_context := os.execute('git blame -L${position_line},+5 -- ${position_file}') context := blame_for_context.output.trim_space().split_into_lines() println(term.colorize(term.red, '${position_file}:${position_line}: deprecation: ${ctx.deprecations}, timestamp: ${ts} - ${t}')) for cline in context { println(' ${cline}') } } fn main() { if os.args.len < 2 { eprintln('Usage: v run cmd/tools/show_ancient_deprecations.v [DAYS]') exit(1) } cut_months := os.args[1].int() cut_time := time.now().add(-cut_months * 24 * time.hour) mut ctx := Context{ cut_time: cut_time } println('> Deprecations that happened before ${cut_time}') all_v_files := os.walk_ext('.', '.v') for v_file in all_v_files { if v_file == './vlib/v/fmt/tests/attrs_keep.vv' { println(term.colorize(term.gray, '>>> SKIPPING deprecations attrs formatting test file ${v_file}')) continue } if v_file.starts_with('./vlib/v/checker/tests') && v_file.contains('deprec') { println(term.colorize(term.gray, '>>> SKIPPING deprecations test file ${v_file}')) continue } file_content := os.read_file(v_file)! if !file_content.contains('[deprecated') { continue } lines := file_content.split_into_lines() for line_num := lines.len - 1; line_num > 0; line_num-- { line := lines[line_num].all_before('//') mut is_deprecation_line := false if line.contains('\tif ') { continue } if line.contains('[deprecated:') { is_deprecation_line = true } if line.contains('[deprecated]') { is_deprecation_line = true } if !is_deprecation_line { continue } ctx.analyze_line(line, v_file, line_num + 1) } } println('> Summary: there were ${term.colorize(term.bright_yellow, ctx.deprecations.str())} deprecations found, done before ${term.colorize(term.magenta, cut_time.str())}.') if ctx.deprecations > 0 { exit(1) } } ================================================ FILE: cmd/tools/test_if_v_test_system_works.v ================================================ module main // This program verifies that `v test` propagates errors // and that it exits with code 1, when at least 1 FAIL happen. import os import rand import time const vexe = os.quoted_path(get_vexe_path()) const vroot = os.dir(vexe) const tdir = new_tdir() fn get_vexe_path() string { env_vexe := os.getenv('VEXE') if env_vexe != '' { return env_vexe } me := os.executable() eprintln('me: ${me}') mut vexe_ := os.join_path(os.dir(os.dir(os.dir(me))), 'v') if os.user_os() == 'windows' { vexe_ += '.exe' } return vexe_ } fn new_tdir() string { dir := os.join_path(os.vtmp_dir(), rand.ulid()) os.rmdir_all(dir) or {} os.mkdir_all(dir) or { panic(err) } at_exit(cleanup_tdir) or {} return dir } fn cleanup_tdir() { println('... removing tdir: ${tdir}') os.rmdir_all(tdir) or { eprintln(err) } } type MyResult = string @[noreturn] fn (result MyResult) fail(reason string) { eprintln('> ${reason}, but it does not. Result:\n${result}') exit(1) } fn (result MyResult) has(sub string) MyResult { if !result.contains(sub) { result.fail(' result should have the substring `${sub}`') } return result } fn (result MyResult) matches(gpattern string) MyResult { if !result.match_glob(gpattern) { result.fail('result should match the glob pattern `${gpattern}`') } return result } fn create_test(tname string, tcontent string) !string { tpath := os.join_path(tdir, tname) os.write_file(tpath, tcontent)! eprintln('>>>>>>>> tpath: ${tpath} | tcontent: ${tcontent}') return os.quoted_path(tpath) } fn check_assert_continues_works() ! { os.chdir(tdir)! create_test('assert_continues_option_works_test.v', 'fn test_fail1() { assert 2==4\nassert 2==1\nassert 2==0 }\nfn test_ok(){ assert true }\nfn test_fail2() { assert false }')! result := check_fail('${vexe} -assert continues assert_continues_option_works_test.v') result.has('assert_continues_option_works_test.v:1: fn test_fail1') result.has('assert_continues_option_works_test.v:2: fn test_fail1') result.has('assert_continues_option_works_test.v:3: fn test_fail1') result.has('assert_continues_option_works_test.v:5: fn test_fail2') result.has('> assert 2 == 4').has('> assert 2 == 1').has('> assert 2 == 0') // Check if a test function, tagged with [assert_continues], has the same behaviour, without needing additional options create_test('assert_continues_tag_works_test.v', '@[assert_continues]fn test_fail1() { assert 2==4\nassert 2==1\nassert 2==0 }\nfn test_ok(){ assert true }\nfn test_fail2() { assert false\n assert false }')! tag_res := check_fail('${vexe} assert_continues_tag_works_test.v') tag_res.has('assert_continues_tag_works_test.v:1: fn test_fail1') tag_res.has('assert_continues_tag_works_test.v:2: fn test_fail1') tag_res.has('assert_continues_tag_works_test.v:3: fn test_fail1') tag_res.has('assert_continues_tag_works_test.v:5: fn test_fail2') if tag_res.contains('assert_continues_tag_works_test.v:6: fn test_fail2') { exit(1) } } fn check_ok(cmd string) MyResult { println('> check_ok cmd: ${cmd}') res := os.execute(cmd) if res.exit_code != 0 { eprintln('> check_ok failed.\n${res.output}') exit(1) } return res.output } fn check_fail(cmd string) MyResult { println('> check_fail cmd: ${cmd}') res := os.execute(cmd) if res.exit_code == 0 { eprintln('> check_fail succeeded, but it should have failed.\n${res.output}') exit(1) } return res.output } fn main() { defer { os.chdir(os.wd_at_startup) or {} } unbuffer_stdout() spawn fn () { time.sleep(120 * time.second) eprintln('>>> exiting due to an expired watchdog timer <<<') exit(1) }() println('> vroot: ${vroot} | vexe: ${vexe} | tdir: ${tdir}') os.setenv('VTEST_HIDE_OK', '0', true) ok_fpath := create_test('a_single_ok_test.v', 'fn test_ok(){ assert true }')! if check_ok('${vexe} ${ok_fpath}') != '' { exit(1) } check_ok('${vexe} test ${ok_fpath}').matches('*OK*a_single_ok_test.v*') check_ok('${vexe} test "${tdir}"').matches('*OK*a_single_ok_test.v*') check_ok('${vexe} -stats test "${tdir}"').matches('*OK*a_single_ok_test.v*') fail_fpath := create_test('a_single_failing_test.v', 'fn test_fail(){ assert 1 == 2 }')! check_fail('${vexe} ${fail_fpath}').has('> assert 1 == 2').has('a_single_failing_test.v:1: fn test_fail') check_fail('${vexe} test ${fail_fpath}').has('> assert 1 == 2').has('a_single_failing_test.v:1: fn test_fail') check_fail('${vexe} test "${tdir}"').has('> assert 1 == 2') check_fail('${vexe} -stats test "${tdir}"').has('> assert 1 == 2') rel_dir := os.join_path(tdir, rand.ulid()) os.mkdir(rel_dir)! os.chdir(rel_dir)! relative_path := '..' + os.path_separator + 'a_single_ok_test.v' check_ok('${vexe} test ${os.quoted_path(relative_path)}').has('OK').has('a_single_ok_test.v') check_assert_continues_works()! println('> all done') } ================================================ FILE: cmd/tools/test_os_args.v ================================================ println(arguments()#[1..]) ================================================ FILE: cmd/tools/test_os_process.v ================================================ module main import os import time import os.cmdline enum Target { both stderr stdout alternate } fn s2target(s string) Target { return match s { 'both' { Target.both } 'stderr' { Target.stderr } 'alternate' { Target.alternate } else { Target.stdout } } } struct Context { mut: timeout_ms int period_ms int exitcode int target Target omode Target is_verbose bool show_wd bool show_env bool } fn (mut ctx Context) println(s string) { if ctx.target == .alternate { ctx.omode = if ctx.omode == .stderr { Target.stdout } else { Target.stderr } } if ctx.target in [.both, .stdout] || ctx.omode == .stdout { println('stdout, ${s}') } if ctx.target in [.both, .stderr] || ctx.omode == .stderr { eprintln('stderr, ${s}') } } fn do_timeout(c &Context) { mut ctx := unsafe { c } time.sleep(ctx.timeout_ms * time.millisecond) exit(ctx.exitcode) } fn main() { unbuffer_stdout() mut ctx := Context{} args := os.args[1..] if '-h' in args || '--help' in args { println("Usage: test_os_process [-v] [-h] [-target stderr/stdout/both/alternate] [-show_wd] [-show_env] [-exitcode 0] [-timeout_ms 200] [-period_ms 50] Prints lines periodically (-period_ms), to stdout/stderr (-target). After a while (-timeout_ms), exit with (-exitcode). This program is useful for platform independent testing of child process/standard input/output control. It is used in V's `os` module tests. ") return } ctx.is_verbose = '-v' in args ctx.show_wd = '-show_wd' in args ctx.show_env = '-show_env' in args ctx.target = s2target(cmdline.option(args, '-target', 'both')) ctx.exitcode = cmdline.option(args, '-exitcode', '0').int() ctx.timeout_ms = cmdline.option(args, '-timeout_ms', '200').int() ctx.period_ms = cmdline.option(args, '-period_ms', '50').int() if ctx.target == .alternate { ctx.omode = .stdout } if ctx.is_verbose { eprintln('> args: ${args} | context: ${ctx}') } if ctx.show_wd { ctx.println('WORK_DIR=${os.getwd()}') } if ctx.show_env { all := os.environ() for k, v in all { ctx.println('${k}=${v}') } } spawn do_timeout(&ctx) ctx.println('start') for i := 1; true; i++ { ctx.println('${i}') time.sleep(ctx.period_ms * time.millisecond) } ctx.println('done') time.sleep(100 * time.second) } ================================================ FILE: cmd/tools/translate.v ================================================ // Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license that can be found in the LICENSE file. module main import os import v.util const vexe = os.getenv('VEXE') fn main() { vmodules := os.vmodules_dir() c2v_dir := os.join_path(vmodules, 'c2v') mut c2v_bin := os.join_path(c2v_dir, 'c2v') $if windows { c2v_bin += '.exe' } // Git clone c2v if !os.exists(c2v_dir) { os.mkdir_all(vmodules)! println('C2V is not installed. Cloning C2V to ${c2v_dir} ...') os.chdir(vmodules)! res := os.execute('${os.quoted_path(vexe)} retry -- git clone --filter=blob:none https://github.com/vlang/c2v') if res.exit_code != 0 { eprintln('Failed to download C2V.') exit(1) } } // Compile c2v if !os.exists(c2v_bin) { os.chdir(c2v_dir)! println('Compiling c2v ...') res2 := os.execute('${os.quoted_path(vexe)} -o ${os.quoted_path(c2v_bin)} -keepc -g -experimental .') if res2.exit_code != 0 { eprintln(res2.output) eprintln('Failed to compile C2V. This should not happen. Please report it via GitHub.') exit(2) } } if os.args.len < 3 { eprintln('Wrong number of arguments. Use `v translate file.c` .') exit(3) } passed_args := util.args_quote_paths(os.args[2..]) // println(passed_args) os.chdir(os.wd_at_startup)! c2v_cmd := '${os.quoted_path(c2v_bin)} ${passed_args}' res := os.system(c2v_cmd) if res != 0 { eprintln('C2V command: ${c2v_cmd}') eprintln('C2V failed to translate the C files. Please report it via GitHub.') exit(4) } } ================================================ FILE: cmd/tools/vast/cjson.v ================================================ module main import json.cjson type Node = C.cJSON fn as_n(p &cjson.Node) &Node { return unsafe { &Node(p) } } fn as_c(p &Node) &cjson.Node { return unsafe { &cjson.Node(p) } } @[inline] fn create_object() &Node { return as_n(cjson.create_object()) } @[inline] fn create_array() &Node { return as_n(cjson.create_array()) } @[inline] fn create_string(val string) &Node { return as_n(cjson.create_string(val)) } @[inline] fn create_number(val f64) &Node { return as_n(cjson.create_number(val)) } @[inline] fn create_bool(val bool) &Node { return as_n(cjson.create_bool(val)) } @[inline] fn create_true() &Node { return as_n(cjson.create_true()) } @[inline] fn create_false() &Node { return as_n(cjson.create_false()) } @[inline] fn create_null() &Node { return as_n(cjson.create_null()) } @[inline] fn delete(b voidptr) { unsafe { cjson.delete(b) } } @[inline] fn add_item_to_object(mut obj Node, key string, item &Node) { mut o := unsafe { &cjson.Node(obj) } o.add_item_to_object(key, item) } @[inline] fn add_item_to_array(mut obj Node, item &Node) { mut o := as_c(obj) o.add_item_to_array(item) } fn json_print(mut obj Node) string { mut o := as_c(obj) return o.print() } ================================================ FILE: cmd/tools/vast/test/.gitignore ================================================ demo.json ================================================ FILE: cmd/tools/vast/test/demo.v ================================================ // usage test: v ast path_to_v/cmd/tools/vast/test/demo.v // will generate demo.json // comment for module module main // import module import os import math import time { Time, now } // const decl const a = 1 const b = 3 const c = 'c' // struct decl struct Point { x int mut: y int pub: z int pub mut: name string } // method of Point pub fn (p Point) get_x() int { return p.x } // embed struct struct MyPoint { Point title string } // enum type enum Color { red green blue } // type alias type Myint = int // sum type type MySumType = bool | int | string // function type type Myfn = fn (int) int // interface type interface Myinterfacer { add(int, int) int sub(int, int) int } // main function fn main() { add(1, 3) println(add(1, 2)) println('ok') // comment println arr := [1, 3, 5, 7] for a in arr { println(a) add(1, 3) } color := Color.red println(color) println(os.args) m := math.max(1, 3) println(m) println(now()) t := Time{} println(t) p := Point{ x: 1 y: 2 z: 3 } println(p) my_point := MyPoint{ // x: 1 // y: 3 // z: 5 } println(my_point.get_x()) } // normal function fn add(x int, y int) int { return x + y } // function with defer stmt fn defer_fn() { mut x := 1 println('start fn') defer { println('in defer block') println(x) } println('end fn') } // generic function fn g_fn[T](p T) T { return p } // generic struct struct GenericStruct[T] { point Point mut: model T } // generic interface interface Gettable[T] { get() T } // generic sumtype struct None {} type MyOption[T] = Error | None | T ================================================ FILE: cmd/tools/vast/vast.v ================================================ module main import os import time import flag import v.token import v.parser import v.ast import v.pref import v.errors import v.checker import strings struct Context { mut: is_watch bool is_compile bool is_print bool is_terse bool is_skip_defaults bool check bool hide_names map[string]bool } const context = &Context{} fn main() { if os.args.len < 2 { eprintln('not enough parameters') exit(1) } mut ctx := unsafe { context } mut fp := flag.new_flag_parser(os.args[2..]) fp.application('v ast') fp.usage_example('demo.v generate demo.json file.') fp.usage_example('-w demo.v generate demo.json file, and watch for changes.') fp.usage_example('-c demo.v generate demo.json *and* a demo.c file, and watch for changes.') fp.usage_example('-p demo.v print the json output to stdout.') fp.usage_example('-s demo.v do NOT show the properties having default values, like false for bools, 0 for ints etc.') fp.description('Dump a JSON representation of the V AST for a given .v or .vsh file.') fp.description('By default, `v ast` will save the JSON to a .json file, named after the .v file.') fp.description('Pass -p to see it instead.') ctx.is_watch = fp.bool('watch', `w`, false, 'watch a .v file for changes, rewrite the .json file, when a change is detected') ctx.is_print = fp.bool('print', `p`, false, 'print the AST to stdout') ctx.is_compile = fp.bool('compile', `c`, false, 'watch the .v file for changes, rewrite the .json file, *AND* generate a .c file too on any change') ctx.is_terse = fp.bool('terse', `t`, false, 'terse output, only with tree node names (AST structure), no details') ctx.is_skip_defaults = fp.bool('skip-defaults', `s`, false, 'skip properties that have default values like false, 0, "", etc') ctx.check = fp.bool('check', `k`, false, 'run v.checker as well (it may modify the AST)') hfields := fp.string_multi('hide', 0, 'hide the specified fields. You can give several, by separating them with `,`').join(',') for hf in hfields.split(',') { ctx.hide_names[hf] = true } fp.limit_free_args_to_at_least(1)! rest_of_args := fp.remaining_parameters() for vfile in rest_of_args { file := get_abs_path(vfile) check_file(file) ctx.write_file_or_print(file) if ctx.is_watch || ctx.is_compile { ctx.watch_for_changes(file) } } } fn (ctx Context) skip_empty(child &Node) bool { if ctx.is_skip_defaults { if child == unsafe { 0 } { return true } if child.type == .t_false { return true } if child.type == .t_null { return true } if child.type == .t_number && child.valuedouble == 0.0 { return true } if child.type == .t_string { slen := unsafe { vstrlen_char(child.valuestring) } if slen == 0 { return true } if slen > 7 { s := unsafe { child.valuestring.vstring_with_len(slen) } if s.starts_with('enum:0(') { return true } } } if child.type == .t_array && child.child == unsafe { 0 } { return true } if child.type == .t_object && child.child == unsafe { 0 } { return true } } return false } fn (ctx Context) write_file_or_print(file string) { if ctx.is_print { println(json(file)) } else { println('${time.now()}: AST written to: ' + json_file(file)) } } // generate ast json file and c source code file fn (ctx Context) watch_for_changes(file string) { println('start watching...') mut timestamp := i64(0) for { new_timestamp := os.file_last_mod_unix(file) if timestamp != new_timestamp { ctx.write_file_or_print(file) if ctx.is_compile { file_name := file[0..(file.len - os.file_ext(file).len)] os.system('v -o ${file_name}.c ${file}') } } timestamp = new_timestamp time.sleep(500 * time.millisecond) } } // get absolute path for file fn get_abs_path(path string) string { if os.is_abs_path(path) { return path } else if path.starts_with('./') { return os.join_path(os.getwd(), path[2..]) } else { return os.join_path(os.getwd(), path) } } // check file is v file and exists fn check_file(file string) { if os.file_ext(file) !in ['.v', '.vv', '.vsh'] { eprintln('the file `${file}` must be a v file or vsh file') exit(1) } if !os.exists(file) { eprintln('the v file `${file}` does not exist') exit(1) } } // generate json file with the same file name fn json_file(file string) string { ast_json := json(file) // support .v and .vsh file file_name := file[0..(file.len - os.file_ext(file).len)] json_file := file_name + '.json' os.write_file(json_file, ast_json) or { panic(err) } return json_file } // generate json string fn json(file string) string { // use as permissive preferences as possible, so that `v ast` // can print the AST of arbitrary V files, even .vsh or ones // that require globals: mut pref_ := &pref.Preferences{} pref_.fill_with_defaults() pref_.enable_globals = true pref_.is_fmt = true mut t := Tree{ root: create_object() table: ast.new_table() pref: pref_ } // parse file with comment mut ast_file := parser.parse_file(file, mut t.table, .parse_comments, t.pref) if context.check { mut the_checker := checker.new_checker(t.table, pref_) the_checker.check(mut ast_file) } t.root = t.ast_file(ast_file) // generate the ast string s := json_print(mut t.root) return s } // the ast tree struct Tree { pref &pref.Preferences = unsafe { nil } mut: table &ast.Table = unsafe { nil } root Node // the root of tree } // add item to object node @[inline] fn (mut node Node) add(key string, child &Node) { if context.hide_names.len > 0 && key in context.hide_names { return } if context.is_terse { return } if context.skip_empty(child) { return } add_item_to_object(mut node, key, child) } // add item to object node @[inline] fn (mut node Node) add_terse(key string, child &Node) { if context.hide_names.len > 0 && key in context.hide_names { return } if context.skip_empty(child) { return } add_item_to_object(mut node, key, child) } // add item to array node @[inline] fn (mut node Node) add_item(child &Node) { if context.skip_empty(child) { return } add_item_to_array(mut node, child) } // string type node fn (t Tree) string_node(val string) &Node { return create_string(val) } // number type node fn (t Tree) number_node(val int) &Node { return create_number(val) } // bool type node fn (t Tree) bool_node(val bool) &Node { if val { return create_true() } else { return create_false() } } // null type node fn (t Tree) null_node() &Node { return create_null() } // type node fn (t Tree) type_node(typ ast.Type) &Node { if typ == 0 { return create_null() } else { type_name := t.table.get_type_name(typ) return create_string(strings.repeat(`&`, typ.nr_muls()) + type_name) } } // token type node fn (t Tree) token_node(tok_kind token.Kind) &Node { return t.string_node('token:${int(tok_kind)}(${tok_kind.str()})') } // enum type node fn (t Tree) enum_node[T](value T) &Node { return t.string_node('enum:${int(value)}(${value})') } // for [][]comment fn (t Tree) two_dimension_comment(node [][]ast.Comment) &Node { mut comments := create_array() for n in node { mut comment_array := create_array() for c in n { comment_array.add_item(t.comment(c)) } comments.add_item(comment_array) } return comments } // ast file root node fn (t Tree) ast_file(node ast.File) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('ast.File')) obj.add_terse('path', t.string_node(node.path)) obj.add('path_base', t.string_node(node.path_base)) obj.add_terse('nr_lines', t.number_node(node.nr_lines)) obj.add_terse('nr_bytes', t.number_node(node.nr_bytes)) obj.add_terse('mod', t.mod(node.mod)) obj.add_terse('imports', t.imports(node.imports)) obj.add('global_scope', t.scope(node.global_scope)) obj.add('scope', t.scope(node.scope)) obj.add('errors', t.errors(node.errors)) obj.add('warnings', t.warnings(node.warnings)) obj.add('notices', t.notices(node.notices)) obj.add_terse('auto_imports', t.array_node_string(node.auto_imports)) mut symbol_obj := create_object() for key, val in node.imported_symbols { symbol_obj.add_terse(key, t.string_node(val)) } obj.add_terse('imported_symbols', symbol_obj) obj.add_terse('generic_fns', t.array_node_generic_fns(node.generic_fns)) obj.add_terse('embedded_files', t.array_node_embed_file(node.embedded_files)) obj.add_terse('global_labels', t.array_node_string(node.global_labels)) obj.add_terse('is_test', t.bool_node(node.is_test)) obj.add_terse('stmts', t.stmts(node.stmts)) return obj } // embed files fn (t Tree) embed_file(node ast.EmbeddedFile) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('EmbeddedFile')) obj.add_terse('rpath', t.string_node(node.rpath)) obj.add('apath', t.string_node(node.apath)) obj.add('compression_type', t.string_node(node.compression_type)) obj.add('is_compressed', t.bool_node(node.is_compressed)) obj.add('len', t.number_node(node.len)) obj.add('bytes', t.array_node_u8(node.bytes)) return obj } // ast module node fn (t Tree) mod(node ast.Module) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('Module')) obj.add_terse('name', t.string_node(node.name)) obj.add('short_name', t.string_node(node.short_name)) obj.add_terse('attrs', t.array_node_attr(node.attrs)) obj.add('pos', t.pos(node.pos)) obj.add('name_pos', t.pos(node.name_pos)) obj.add_terse('is_skipped', t.bool_node(node.is_skipped)) return obj } fn (t Tree) scope(scope &ast.Scope) &Node { mut obj := create_object() if unsafe { scope == nil } { return obj } obj.add_terse('ast_type', t.string_node('Scope')) obj.add_terse('parent', t.string_node(ptr_str(scope.parent))) mut children_arr := create_array() for s in scope.children { mut children_obj := create_object() children_obj.add_terse('parent', t.string_node(ptr_str(s.parent))) children_obj.add('start_pos', t.number_node(s.start_pos)) children_obj.add('end_pos', t.number_node(s.end_pos)) children_arr.add_item(children_obj) } obj.add_terse('children', children_arr) obj.add('start_pos', t.number_node(scope.start_pos)) obj.add('end_pos', t.number_node(scope.end_pos)) obj.add_terse('objects', t.objects(scope.objects)) obj.add_terse('struct_fields', t.array_node_scope_struct_field(scope.struct_fields)) return obj } fn (t Tree) scope_struct_field(node ast.ScopeStructField) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('ScopeStructField')) obj.add_terse('struct_type', t.type_node(node.struct_type)) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('orig_type', t.type_node(node.orig_type)) obj.add('pos', t.pos(node.pos)) obj.add_terse('smartcasts', t.array_node_type(node.smartcasts)) return obj } fn (t Tree) objects(so map[string]ast.ScopeObject) &Node { mut obj := create_object() for key, val in so { obj.add_terse(key, t.scope_object(val)) } return obj } fn (t Tree) scope_object(node ast.ScopeObject) &Node { obj := match node { ast.EmptyScopeObject { create_object() } ast.ConstField { t.const_field(node) } ast.GlobalField { t.global_field(node) } ast.Var { t.var(node) } ast.AsmRegister { t.asm_register(node) } } return obj } fn (t Tree) imports(nodes []ast.Import) &Node { mut import_array := create_array() for node in nodes { import_array.add_item(t.import_module(node)) } return import_array } fn (t Tree) errors(errors_ []errors.Error) &Node { mut errs := create_array() for e in errors_ { mut obj := create_object() obj.add_terse('message', t.string_node(e.message)) obj.add_terse('file_path', t.string_node(e.file_path)) obj.add('pos', t.pos(e.pos)) obj.add('reporter', t.enum_node(e.reporter)) errs.add_item(obj) } return errs } fn (t Tree) warnings(warnings []errors.Warning) &Node { mut warns := create_array() for w in warnings { mut obj := create_object() obj.add_terse('message', t.string_node(w.message)) obj.add_terse('file_path', t.string_node(w.file_path)) obj.add('pos', t.pos(w.pos)) obj.add('reporter', t.enum_node(w.reporter)) warns.add_item(obj) } return warns } fn (t Tree) notices(notices []errors.Notice) &Node { mut notice_array := create_array() for n in notices { mut obj := create_object() obj.add_terse('message', t.string_node(n.message)) obj.add_terse('file_path', t.string_node(n.file_path)) obj.add('pos', t.pos(n.pos)) obj.add('reporter', t.enum_node(n.reporter)) notice_array.add_item(obj) } return notice_array } // stmt array node fn (t Tree) stmts(stmts []ast.Stmt) &Node { mut stmt_array := create_array() for s in stmts { stmt_array.add_item(t.stmt(s)) } return stmt_array } fn (t Tree) stmt(node ast.Stmt) &Node { match node { ast.Module { return t.mod(node) } ast.Import { return t.import_module(node) } ast.ConstDecl { return t.const_decl(node) } ast.FnDecl { return t.fn_decl(node) } ast.StructDecl { return t.struct_decl(node) } ast.EnumDecl { return t.enum_decl(node) } ast.InterfaceDecl { return t.interface_decl(node) } ast.HashStmt { return t.hash_stmt(node) } ast.ComptimeFor { return t.comptime_for(node) } ast.GlobalDecl { return t.global_decl(node) } ast.DeferStmt { return t.defer_stmt(node) } ast.TypeDecl { return t.type_decl(node) } ast.GotoLabel { return t.goto_label(node) } ast.GotoStmt { return t.goto_stmt(node) } ast.AssignStmt { return t.assign_stmt(node) } ast.Return { return t.return_(node) } ast.ForCStmt { return t.for_c_stmt(node) } ast.ForStmt { return t.for_stmt(node) } ast.ForInStmt { return t.for_in_stmt(node) } ast.BranchStmt { return t.branch_stmt(node) } ast.AssertStmt { return t.assert_stmt(node) } ast.ExprStmt { return t.expr_stmt(node) } ast.Block { return t.block(node) } ast.SemicolonStmt { return t.semicolon_stmt(node) } ast.SqlStmt { return t.sql_stmt(node) } ast.AsmStmt { return t.asm_stmt(node) } ast.NodeError { return t.node_error(node) } ast.EmptyStmt { return t.empty_stmt(node) } ast.DebuggerStmt { return t.debugger_stmt(node) } } return t.null_node() } fn (t Tree) import_module(node ast.Import) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('Import')) obj.add_terse('source_name', t.string_node(node.source_name)) obj.add_terse('mod', t.string_node(node.mod)) obj.add_terse('alias', t.string_node(node.alias)) obj.add_terse('syms', t.array_node_import_symbol(node.syms)) obj.add('comments', t.array_node_comment(node.comments)) obj.add('next_comments', t.array_node_comment(node.next_comments)) obj.add('pos', t.pos(node.pos)) obj.add('mod_pos', t.pos(node.mod_pos)) obj.add('alias_pos', t.pos(node.alias_pos)) obj.add('syms_pos', t.pos(node.syms_pos)) return obj } fn (t Tree) import_symbol(node ast.ImportSymbol) &Node { mut obj := create_object() obj.add_terse('name', t.string_node(node.name)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) pos(p token.Pos) &Node { mut obj := create_object() obj.add('line_nr', t.number_node(p.line_nr)) obj.add('last_line', t.number_node(p.last_line)) obj.add('pos', t.number_node(p.pos)) obj.add('len', t.number_node(p.len)) return obj } fn (t Tree) comment(node ast.Comment) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('Comment')) obj.add('text', t.string_node(node.text)) obj.add('is_multi', t.bool_node(node.is_multi)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) const_decl(node ast.ConstDecl) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('ConstDecl')) obj.add_terse('is_pub', t.bool_node(node.is_pub)) obj.add_terse('is_block', t.bool_node(node.is_block)) obj.add_terse('fields', t.array_node_const_field(node.fields)) obj.add_terse('attrs', t.array_node_attr(node.attrs)) obj.add('end_comments', t.array_node_comment(node.end_comments)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) lambda_expr(node ast.LambdaExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('LambdaExpr')) obj.add_terse('params', t.array_node_ident(node.params)) obj.add_terse('pos_expr', t.pos(node.pos_expr)) obj.add_terse('expr', t.expr(node.expr)) obj.add_terse('pos_end', t.pos(node.pos_end)) obj.add('scope', t.number_node(int(node.scope))) obj.add('func', t.number_node(int(node.func))) obj.add_terse('is_checked', t.bool_node(node.is_checked)) obj.add_terse('typ', t.type_node(node.typ)) return obj } fn (t Tree) const_field(node ast.ConstField) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('ConstField')) obj.add_terse('mod', t.string_node(node.mod)) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('expr', t.expr(node.expr)) obj.add_terse('is_pub', t.bool_node(node.is_pub)) obj.add_terse('is_markused', t.bool_node(node.is_markused)) obj.add_terse('typ', t.type_node(node.typ)) obj.add('comments', t.array_node_comment(node.comments)) obj.add('comptime_expr_value', t.comptime_expr_value(node.comptime_expr_value)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) comptime_expr_value(node ast.ComptTimeConstValue) &Node { match node { ast.EmptyExpr { return t.empty_expr(node) } string { return t.string_node(node) } else { return t.string_node(node.str()) } } } // function declaration fn (t Tree) fn_decl(node ast.FnDecl) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('FnDecl')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('short_name', t.string_node(node.short_name)) obj.add_terse('mod', t.string_node(node.mod)) obj.add_terse('kind', t.enum_node(node.kind)) obj.add_terse('is_deprecated', t.bool_node(node.is_deprecated)) obj.add_terse('is_pub', t.bool_node(node.is_pub)) obj.add_terse('is_c_variadic', t.bool_node(node.is_c_variadic)) obj.add_terse('is_c_extern', t.bool_node(node.is_c_extern)) obj.add_terse('is_variadic', t.bool_node(node.is_variadic)) obj.add('is_anon', t.bool_node(node.is_anon)) obj.add_terse('is_noreturn', t.bool_node(node.is_noreturn)) obj.add_terse('is_weak', t.bool_node(node.is_weak)) obj.add_terse('is_manualfree', t.bool_node(node.is_manualfree)) obj.add('is_main', t.bool_node(node.is_main)) obj.add('is_test', t.bool_node(node.is_test)) obj.add('is_conditional', t.bool_node(node.is_conditional)) obj.add_terse('is_exported', t.bool_node(node.is_exported)) obj.add('is_keep_alive', t.bool_node(node.is_keep_alive)) obj.add_terse('is_unsafe', t.bool_node(node.is_unsafe)) obj.add_terse('is_markused', t.bool_node(node.is_markused)) obj.add_terse('is_file_translated', t.bool_node(node.is_file_translated)) obj.add_terse('is_closure', t.bool_node(node.is_closure)) obj.add_terse('receiver', t.struct_field(node.receiver)) obj.add('receiver_pos', t.pos(node.receiver_pos)) obj.add_terse('is_method', t.bool_node(node.is_method)) obj.add_terse('is_static_type_method', t.bool_node(node.is_static_type_method)) obj.add('method_type_pos', t.pos(node.method_type_pos)) obj.add('method_idx', t.number_node(node.method_idx)) obj.add_terse('rec_mut', t.bool_node(node.rec_mut)) obj.add_terse('has_prev_newline', t.bool_node(node.has_prev_newline)) obj.add_terse('has_break_line', t.bool_node(node.has_break_line)) obj.add('rec_share', t.enum_node(node.rec_share)) obj.add_terse('language', t.enum_node(node.language)) obj.add('file_mode', t.enum_node(node.file_mode)) obj.add('no_body', t.bool_node(node.no_body)) obj.add('is_builtin', t.bool_node(node.is_builtin)) obj.add('file', t.string_node(node.file)) obj.add('is_direct_arr', t.bool_node(node.is_direct_arr)) obj.add('ctdefine_idx', t.number_node(node.ctdefine_idx)) obj.add('pos', t.pos(node.pos)) obj.add('end_pos', t.pos(node.end_pos)) obj.add('body_pos', t.pos(node.body_pos)) obj.add('return_type_pos', t.pos(node.return_type_pos)) obj.add('file', t.string_node(node.file)) obj.add('has_return', t.bool_node(node.has_return)) obj.add('should_be_skipped', t.bool_node(node.should_be_skipped)) obj.add('ninstances', t.number_node(node.ninstances)) obj.add_terse('has_await', t.bool_node(node.has_await)) obj.add_terse('return_type', t.type_node(node.return_type)) obj.add('source_file', t.number_node(int(node.source_file))) obj.add('scope', t.number_node(int(node.scope))) obj.add_terse('attrs', t.array_node_attr(node.attrs)) obj.add_terse('params', t.array_node_arg(node.params)) obj.add_terse('generic_names', t.array_node_string(node.generic_names)) obj.add_terse('stmts', t.array_node_stmt(node.stmts)) obj.add('comments', t.array_node_comment(node.comments)) obj.add('next_comments', t.array_node_comment(node.next_comments)) obj.add('label_names', t.array_node_string(node.label_names)) obj.add('defer_stmts', t.array_node_defer_stmt(node.defer_stmts)) return obj } fn (t Tree) anon_fn(node ast.AnonFn) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('AnonFn')) obj.add_terse('decl', t.fn_decl(node.decl)) obj.add('inherited_vars', t.array_node_arg(node.inherited_vars)) obj.add_terse('typ', t.type_node(node.typ)) obj.add('has_ct_var', t.bool_node(node.has_ct_var)) mut symbol_obj := create_object() for key, val in node.has_gen { symbol_obj.add_terse(key.str(), t.bool_node(val)) } obj.add_terse('has_gen', symbol_obj) return obj } fn (t Tree) struct_decl(node ast.StructDecl) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('StructDecl')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('is_pub', t.bool_node(node.is_pub)) obj.add('pub_pos', t.number_node(node.pub_pos)) obj.add('mut_pos', t.number_node(node.mut_pos)) obj.add('pub_mut_pos', t.number_node(node.pub_mut_pos)) obj.add('global_pos', t.number_node(node.global_pos)) obj.add('module_pos', t.number_node(node.module_pos)) obj.add_terse('language', t.enum_node(node.language)) obj.add_terse('is_union', t.bool_node(node.is_union)) obj.add('pos', t.pos(node.pos)) obj.add_terse('fields', t.array_node_struct_field(node.fields)) obj.add_terse('generic_types', t.array_node_type(node.generic_types)) obj.add_terse('attrs', t.array_node_attr(node.attrs)) obj.add('end_comments', t.array_node_comment(node.end_comments)) obj.add_terse('embeds', t.array_node_embed(node.embeds)) obj.add('is_implements', t.bool_node(node.is_implements)) obj.add_terse('implements_types', t.array_node_type_expr(node.implements_types)) return obj } fn (t Tree) struct_field(node ast.StructField) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('StructField')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('anon_struct_decl', t.struct_decl(node.anon_struct_decl)) obj.add_terse('unaliased_typ', t.type_node(node.unaliased_typ)) obj.add('type_pos', t.pos(node.type_pos)) obj.add('option_pos', t.pos(node.option_pos)) obj.add_terse('has_default_expr', t.bool_node(node.has_default_expr)) obj.add_terse('default_expr_typ', t.type_node(node.default_expr_typ)) obj.add_terse('default_expr', t.expr(node.default_expr)) obj.add_terse('is_pub', t.bool_node(node.is_pub)) obj.add_terse('is_mut', t.bool_node(node.is_mut)) obj.add_terse('is_global', t.bool_node(node.is_global)) obj.add_terse('is_volatile', t.bool_node(node.is_volatile)) obj.add_terse('is_deprecated', t.bool_node(node.is_deprecated)) obj.add_terse('attrs', t.array_node_attr(node.attrs)) obj.add('pre_comments', t.array_node_comment(node.pre_comments)) obj.add('comments', t.array_node_comment(node.comments)) obj.add('next_comments', t.array_node_comment(node.next_comments)) obj.add('pos', t.pos(node.pos)) obj.add_terse('i', t.number_node(node.i)) return obj } fn (t Tree) embed(node ast.Embed) &Node { mut obj := create_object() obj.add_terse('typ', t.type_node(node.typ)) obj.add('pos', t.pos(node.pos)) obj.add('comments', t.array_node_comment(node.comments)) return obj } fn (t Tree) enum_decl(node ast.EnumDecl) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('EnumDecl')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('is_pub', t.bool_node(node.is_pub)) obj.add_terse('is_flag', t.bool_node(node.is_flag)) obj.add_terse('is_multi_allowed', t.bool_node(node.is_multi_allowed)) obj.add('pos', t.pos(node.pos)) obj.add_terse('fields', t.array_node_enum_field(node.fields)) obj.add('comments', t.array_node_comment(node.comments)) obj.add_terse('attrs', t.array_node_attr(node.attrs)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('enum_typ', t.type_node(node.enum_typ)) return obj } fn (t Tree) enum_field(node ast.EnumField) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('EnumField')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('has_expr', t.bool_node(node.has_expr)) obj.add_terse('expr', t.expr(node.expr)) obj.add('pos', t.pos(node.pos)) obj.add('pre_comments', t.array_node_comment(node.pre_comments)) obj.add('comments', t.array_node_comment(node.comments)) obj.add('next_comments', t.array_node_comment(node.next_comments)) return obj } fn (t Tree) interface_decl(node ast.InterfaceDecl) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('InterfaceDecl')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('is_pub', t.bool_node(node.is_pub)) obj.add('mut_pos', t.number_node(node.mut_pos)) obj.add_terse('field_names', t.array_node_string(node.field_names)) obj.add_terse('methods', t.array_node_fn_decl(node.methods)) obj.add_terse('fields', t.array_node_struct_field(node.fields)) obj.add('pre_comments', t.array_node_comment(node.pre_comments)) obj.add('name_pos', t.pos(node.name_pos)) obj.add_terse('language', t.enum_node(node.language)) obj.add('pos', t.pos(node.pos)) obj.add('are_embeds_expanded', t.bool_node(node.are_embeds_expanded)) obj.add_terse('embeds', t.array_node_interface_embedding(node.embeds)) obj.add_terse('attrs', t.array_node_attr(node.attrs)) return obj } fn (t Tree) interface_embedding(node ast.InterfaceEmbedding) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('InterfaceEmbedding')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('typ', t.type_node(node.typ)) obj.add('pos', t.pos(node.pos)) obj.add('comments', t.array_node_comment(node.comments)) return obj } fn (t Tree) attr(node ast.Attr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('Attr')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('has_arg', t.bool_node(node.has_arg)) obj.add_terse('arg', t.string_node(node.arg)) obj.add_terse('kind', t.enum_node(node.kind)) obj.add_terse('ct_opt', t.bool_node(node.ct_opt)) obj.add_terse('has_at', t.bool_node(node.has_at)) obj.add_terse('ct_expr', t.expr(node.ct_expr)) obj.add_terse('ct_evaled', t.bool_node(node.ct_evaled)) obj.add_terse('ct_skip', t.bool_node(node.ct_skip)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) hash_stmt(node ast.HashStmt) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('HashStmt')) obj.add_terse('mod', t.string_node(node.mod)) obj.add_terse('val', t.string_node(node.val)) obj.add_terse('kind', t.string_node(node.kind)) obj.add_terse('main', t.string_node(node.main)) obj.add_terse('msg', t.string_node(node.msg)) obj.add_terse('is_use_once', t.bool_node(node.is_use_once)) obj.add_terse('ct_conds', t.array_node_expr(node.ct_conds)) obj.add_terse('source_file', t.string_node(node.source_file)) obj.add_terse('attrs', t.array_node_attr(node.attrs)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) comptime_for(node ast.ComptimeFor) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('ComptimeFor')) obj.add_terse('val_var', t.string_node(node.val_var)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('kind', t.enum_node(node.kind)) obj.add('pos', t.pos(node.pos)) obj.add('typ_pos', t.pos(node.pos)) obj.add_terse('stmts', t.array_node_stmt(node.stmts)) return obj } fn (t Tree) global_decl(node ast.GlobalDecl) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('GlobalDecl')) obj.add_terse('mod', t.string_node(node.mod)) obj.add_terse('attrs', t.array_node_attr(node.attrs)) obj.add_terse('is_block', t.bool_node(node.is_block)) obj.add_terse('fields', t.array_node_global_field(node.fields)) obj.add('pos', t.pos(node.pos)) obj.add('end_comments', t.array_node_comment(node.end_comments)) return obj } fn (t Tree) global_field(node ast.GlobalField) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('GlobalField')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('expr', t.expr(node.expr)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('has_expr', t.bool_node(node.has_expr)) obj.add_terse('is_markused', t.bool_node(node.is_markused)) obj.add_terse('is_weak', t.bool_node(node.is_weak)) obj.add_terse('is_hidden', t.bool_node(node.is_hidden)) obj.add('comments', t.array_node_comment(node.comments)) obj.add('pos', t.pos(node.pos)) obj.add('typ_pos', t.pos(node.typ_pos)) return obj } fn (t Tree) defer_stmt(node ast.DeferStmt) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('DeferStmt')) obj.add_terse('stmts', t.array_node_stmt(node.stmts)) obj.add_terse('defer_vars', t.array_node_ident(node.defer_vars)) obj.add_terse('ifdef', t.string_node(node.ifdef)) obj.add('idx_in_fn', t.number_node(node.idx_in_fn)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) type_decl(node ast.TypeDecl) &Node { match node { ast.AliasTypeDecl { return t.alias_type_decl(node) } ast.FnTypeDecl { return t.fn_type_decl(node) } ast.SumTypeDecl { return t.sum_type_decl(node) } } } fn (t Tree) alias_type_decl(node ast.AliasTypeDecl) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('AliasTypeDecl')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('mod', t.string_node(node.mod)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('parent_type', t.type_node(node.parent_type)) obj.add_terse('is_pub', t.bool_node(node.is_pub)) obj.add('comments', t.array_node_comment(node.comments)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) sum_type_decl(node ast.SumTypeDecl) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('SumTypeDecl')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('mod', t.string_node(node.mod)) obj.add_terse('is_pub', t.bool_node(node.is_pub)) obj.add('pos', t.pos(node.pos)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('generic_types', t.array_node_type(node.generic_types)) obj.add_terse('variants', t.array_node_type_expr(node.variants)) obj.add('name_pos', t.pos(node.name_pos)) return obj } fn (t Tree) fn_type_decl(node ast.FnTypeDecl) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('FnTypeDecl')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('mod', t.string_node(node.mod)) obj.add_terse('is_pub', t.bool_node(node.is_pub)) obj.add_terse('typ', t.type_node(node.typ)) obj.add('pos', t.pos(node.pos)) obj.add('comments', t.array_node_comment(node.comments)) return obj } fn (t Tree) arg(node ast.Param) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('Param')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('is_mut', t.bool_node(node.is_mut)) obj.add_terse('is_shared', t.bool_node(node.is_shared)) obj.add_terse('is_atomic', t.bool_node(node.is_atomic)) obj.add_terse('on_newline', t.bool_node(node.on_newline)) obj.add('pos', t.pos(node.pos)) obj.add('type_pos', t.pos(node.type_pos)) return obj } fn (t Tree) goto_label(node ast.GotoLabel) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('GotoLabel')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('is_used', t.bool_node(node.is_used)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) goto_stmt(node ast.GotoStmt) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('GotoStmt')) obj.add_terse('name', t.string_node(node.name)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) assign_stmt(node ast.AssignStmt) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('AssignStmt')) obj.add_terse('op', t.token_node(node.op)) obj.add_terse('left', t.array_node_expr(node.left)) obj.add_terse('left_types', t.array_node_type(node.left_types)) obj.add_terse('right', t.array_node_expr(node.right)) obj.add_terse('right_types', t.array_node_type(node.left_types)) obj.add_terse('is_static', t.bool_node(node.is_static)) obj.add_terse('is_volatile', t.bool_node(node.is_volatile)) obj.add_terse('is_simple', t.bool_node(node.is_simple)) obj.add_terse('has_cross_var', t.bool_node(node.has_cross_var)) obj.add('pos', t.pos(node.pos)) obj.add('end_comments', t.array_node_comment(node.end_comments)) return obj } fn (t Tree) var(node ast.Var) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('Var')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('orig_type', t.type_node(node.orig_type)) obj.add_terse('expr', t.expr(node.expr)) obj.add_terse('is_arg', t.bool_node(node.is_arg)) obj.add_terse('is_mut', t.bool_node(node.is_mut)) obj.add_terse('is_static', t.bool_node(node.is_static)) obj.add_terse('is_volatile', t.bool_node(node.is_volatile)) obj.add('is_used', t.bool_node(node.is_used)) obj.add('is_changed', t.bool_node(node.is_changed)) obj.add_terse('ct_type_var', t.enum_node(node.ct_type_var)) obj.add('is_or', t.bool_node(node.is_or)) obj.add('is_tmp', t.bool_node(node.is_tmp)) obj.add('is_autofree_tmp', t.bool_node(node.is_autofree_tmp)) obj.add('is_auto_deref', t.bool_node(node.is_auto_deref)) obj.add('is_inherited', t.bool_node(node.is_inherited)) obj.add('has_inherited', t.bool_node(node.has_inherited)) obj.add('is_auto_heap', t.bool_node(node.is_auto_heap)) obj.add('is_stack_obj', t.bool_node(node.is_stack_obj)) obj.add_terse('share', t.enum_node(node.share)) obj.add('pos', t.pos(node.pos)) obj.add_terse('smartcasts', t.array_node_type(node.smartcasts)) return obj } fn (t Tree) return_(node ast.Return) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('Return')) obj.add_terse('exprs', t.array_node_expr(node.exprs)) obj.add_terse('types', t.array_node_type(node.types)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) for_c_stmt(node ast.ForCStmt) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('ForCStmt')) obj.add_terse('has_init', t.bool_node(node.has_init)) obj.add_terse('init', t.stmt(node.init)) obj.add_terse('has_cond', t.bool_node(node.has_cond)) obj.add_terse('cond', t.expr(node.cond)) obj.add_terse('has_inc', t.bool_node(node.has_inc)) obj.add_terse('inc', t.stmt(node.inc)) obj.add_terse('is_multi', t.bool_node(node.is_multi)) obj.add_terse('label', t.string_node(node.label)) obj.add('pos', t.pos(node.pos)) obj.add('comments', t.array_node_comment(node.comments)) obj.add('scope', t.number_node(int(node.scope))) obj.add_terse('stmts', t.array_node_stmt(node.stmts)) return obj } fn (t Tree) for_stmt(node ast.ForStmt) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('ForStmt')) obj.add_terse('cond', t.expr(node.cond)) obj.add_terse('is_inf', t.bool_node(node.is_inf)) obj.add_terse('label', t.string_node(node.label)) obj.add('pos', t.pos(node.pos)) obj.add('comments', t.array_node_comment(node.comments)) obj.add('scope', t.number_node(int(node.scope))) obj.add_terse('stmts', t.array_node_stmt(node.stmts)) return obj } fn (t Tree) for_in_stmt(node ast.ForInStmt) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('ForInStmt')) obj.add_terse('key_var', t.string_node(node.key_var)) obj.add_terse('val_var', t.string_node(node.val_var)) obj.add_terse('cond', t.expr(node.cond)) obj.add_terse('is_range', t.bool_node(node.is_range)) obj.add_terse('high', t.expr(node.high)) obj.add_terse('key_type', t.type_node(node.key_type)) obj.add_terse('val_type', t.type_node(node.val_type)) obj.add_terse('cond_type', t.type_node(node.cond_type)) obj.add_terse('kind', t.enum_node(node.kind)) obj.add_terse('val_is_mut', t.bool_node(node.val_is_mut)) obj.add_terse('val_is_ref', t.bool_node(node.val_is_ref)) obj.add_terse('label', t.string_node(node.label)) obj.add('pos', t.pos(node.pos)) obj.add('comments', t.array_node_comment(node.comments)) obj.add('scope', t.number_node(int(node.scope))) obj.add_terse('stmts', t.array_node_stmt(node.stmts)) return obj } fn (t Tree) branch_stmt(node ast.BranchStmt) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('BranchStmt')) obj.add_terse('kind', t.token_node(node.kind)) obj.add_terse('label', t.string_node(node.label)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) assert_stmt(node ast.AssertStmt) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('AssertStmt')) obj.add_terse('expr', t.expr(node.expr)) obj.add_terse('is_used', t.bool_node(node.is_used)) if node.extra !is ast.EmptyExpr { obj.add_terse('extra', t.expr(node.extra)) obj.add('extra_pos', t.pos(node.extra_pos)) } obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) block(node ast.Block) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('Block')) obj.add_terse('stmts', t.array_node_stmt(node.stmts)) obj.add_terse('is_unsafe', t.bool_node(node.is_unsafe)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) comptime_call(node ast.ComptimeCall) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('ComptimeCall')) obj.add_terse('method_name', t.string_node(node.method_name)) obj.add_terse('kind', t.enum_node(node.kind)) obj.add_terse('left', t.expr(node.left)) obj.add_terse('is_vweb', t.bool_node(node.is_vweb)) obj.add_terse('is_veb', t.bool_node(node.is_veb)) obj.add_terse('veb_tmpl', t.string_node(node.veb_tmpl.path)) obj.add_terse('args_var', t.string_node(node.args_var)) obj.add_terse('has_parens', t.bool_node(node.has_parens)) obj.add_terse('embed_file', t.embed_file(node.embed_file)) obj.add('method_pos', t.pos(node.method_pos)) obj.add_terse('left_type', t.type_node(node.left_type)) obj.add_terse('result_type', t.type_node(node.result_type)) obj.add('scope', t.scope(node.scope)) obj.add_terse('env_value', t.string_node(node.env_value)) obj.add_terse('compile_value', t.string_node(node.compile_value)) obj.add('pos', t.pos(node.pos)) obj.add_terse('args', t.array_node_call_arg(node.args)) obj.add_terse('or_block', t.or_expr(node.or_block)) return obj } fn (t Tree) comptime_selector(node ast.ComptimeSelector) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('ComptimeSelector')) obj.add_terse('has_parens', t.bool_node(node.has_parens)) obj.add_terse('left', t.expr(node.left)) obj.add_terse('field_expr', t.expr(node.field_expr)) obj.add_terse('left_type', t.type_node(node.left_type)) obj.add_terse('typ', t.type_node(node.typ)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) expr_stmt(node ast.ExprStmt) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('ExprStmt')) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('is_expr', t.bool_node(node.is_expr)) obj.add_terse('expr', t.expr(node.expr)) obj.add('pos', t.pos(node.pos)) obj.add('comments', t.array_node_comment(node.comments)) return obj } // expr fn (t Tree) expr(expr ast.Expr) &Node { match expr { ast.IntegerLiteral { return t.integer_literal(expr) } ast.FloatLiteral { return t.float_literal(expr) } ast.StringLiteral { return t.string_literal(expr) } ast.CharLiteral { return t.char_literal(expr) } ast.BoolLiteral { return t.bool_literal(expr) } ast.StringInterLiteral { return t.string_inter_literal(expr) } ast.EnumVal { return t.enum_val(expr) } ast.Assoc { return t.assoc(expr) } ast.AtExpr { return t.at_expr(expr) } ast.CastExpr { return t.cast_expr(expr) } ast.AsCast { return t.as_cast(expr) } ast.TypeNode { return t.type_expr(expr) } ast.SizeOf { return t.size_of(expr) } ast.IsRefType { return t.is_ref_type(expr) } ast.PrefixExpr { return t.prefix_expr(expr) } ast.InfixExpr { return t.infix_expr(expr) } ast.IndexExpr { return t.index_expr(expr) } ast.PostfixExpr { return t.postfix_expr(expr) } ast.SelectorExpr { return t.selector_expr(expr) } ast.RangeExpr { return t.range_expr(expr) } ast.IfExpr { return t.if_expr(expr) } ast.Ident { return t.ident(expr) } ast.CallExpr { return t.call_expr(expr) } ast.OrExpr { return t.or_expr(expr) } ast.StructInit { return t.struct_init(expr) } ast.ArrayInit { return t.array_init(expr) } ast.MapInit { return t.map_init(expr) } ast.None { return t.none_expr(expr) } ast.ParExpr { return t.par_expr(expr) } ast.IfGuardExpr { return t.if_guard_expr(expr) } ast.MatchExpr { return t.match_expr(expr) } ast.ConcatExpr { return t.concat_expr(expr) } ast.TypeOf { return t.type_of(expr) } ast.Likely { return t.likely(expr) } ast.SqlExpr { return t.sql_expr(expr) } ast.ComptimeCall { return t.comptime_call(expr) } ast.ComptimeSelector { return t.comptime_selector(expr) } ast.LockExpr { return t.lock_expr(expr) } ast.UnsafeExpr { return t.unsafe_expr(expr) } ast.ChanInit { return t.chan_init(expr) } ast.SelectExpr { return t.select_expr(expr) } ast.Comment { return t.comment(expr) } ast.AnonFn { return t.anon_fn(expr) } ast.ArrayDecompose { return t.array_decompose(expr) } ast.GoExpr { return t.go_expr(expr) } ast.SpawnExpr { return t.spawn_expr(expr) } ast.OffsetOf { return t.offset_of(expr) } ast.DumpExpr { return t.dump_expr(expr) } ast.LambdaExpr { return t.lambda_expr(expr) } ast.NodeError { return t.node_error(expr) } ast.EmptyExpr { return t.empty_expr(expr) } ast.Nil { return t.nil_expr(expr) } else { // println('unknown expr') return t.null_node() } } } fn (t Tree) integer_literal(node ast.IntegerLiteral) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('IntegerLiteral')) obj.add_terse('val', t.string_node(node.val)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) float_literal(node ast.FloatLiteral) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('FloatLiteral')) obj.add_terse('val', t.string_node(node.val)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) string_literal(node ast.StringLiteral) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('StringLiteral')) obj.add_terse('val', t.string_node(node.val)) obj.add_terse('is_raw', t.bool_node(node.is_raw)) obj.add_terse('language', t.enum_node(node.language)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) char_literal(node ast.CharLiteral) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('CharLiteral')) obj.add_terse('val', t.string_node(node.val)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) bool_literal(node ast.BoolLiteral) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('BoolLiteral')) obj.add_terse('val', t.bool_node(node.val)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) string_inter_literal(node ast.StringInterLiteral) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('StringInterLiteral')) obj.add_terse('vals', t.array_node_string(node.vals)) obj.add_terse('exprs', t.array_node_expr(node.exprs)) obj.add_terse('expr_types', t.array_node_type(node.expr_types)) obj.add_terse('fwidths', t.array_node_int(node.fwidths)) obj.add_terse('precisions', t.array_node_int(node.precisions)) obj.add_terse('pluss', t.array_node_bool(node.pluss)) obj.add_terse('fills', t.array_node_bool(node.fills)) obj.add_terse('fmt_poss', t.array_node_position(node.fmt_poss)) obj.add_terse('fmts', t.array_node_u8(node.fmts)) obj.add_terse('need_fmts', t.array_node_bool(node.need_fmts)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) enum_val(node ast.EnumVal) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('EnumVal')) obj.add_terse('enum_name', t.string_node(node.enum_name)) obj.add_terse('mod', t.string_node(node.mod)) obj.add_terse('val', t.string_node(node.val)) obj.add_terse('typ', t.type_node(node.typ)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) assoc(node ast.Assoc) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('Assoc')) obj.add_terse('var_name', t.string_node(node.var_name)) obj.add_terse('fields', t.array_node_string(node.fields)) obj.add_terse('exprs', t.array_node_expr(node.exprs)) obj.add_terse('typ', t.type_node(node.typ)) obj.add('pos', t.pos(node.pos)) obj.add('scope', t.number_node(int(node.scope))) return obj } fn (t Tree) at_expr(node ast.AtExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('AtExpr')) obj.add_terse('name', t.string_node(node.name)) obj.add('pos', t.pos(node.pos)) obj.add_terse('kind', t.enum_node(node.kind)) obj.add_terse('val', t.string_node(node.val)) return obj } fn (t Tree) cast_expr(node ast.CastExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('CastExpr')) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('ityp', t.number_node(int(node.typ))) obj.add_terse('typname', t.string_node(node.typname)) obj.add_terse('has_arg', t.bool_node(node.has_arg)) obj.add_terse('arg', t.expr(node.arg)) obj.add_terse('expr_type', t.type_node(node.expr_type)) obj.add_terse('expr', t.expr(node.expr)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) as_cast(node ast.AsCast) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('AsCast')) obj.add_terse('expr', t.expr(node.expr)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('expr_type', t.type_node(node.expr_type)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) type_expr(node ast.TypeNode) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('TypeNode')) obj.add_terse('typ', t.type_node(node.typ)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) size_of(node ast.SizeOf) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('SizeOf')) obj.add_terse('guessed_type', t.bool_node(node.guessed_type)) obj.add_terse('is_type', t.bool_node(node.is_type)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('expr', t.expr(node.expr)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) is_ref_type(node ast.IsRefType) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('IsRefType')) obj.add_terse('guessed_type', t.bool_node(node.guessed_type)) obj.add_terse('is_type', t.bool_node(node.is_type)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('expr', t.expr(node.expr)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) prefix_expr(node ast.PrefixExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('PrefixExpr')) obj.add_terse('op', t.token_node(node.op)) obj.add_terse('right', t.expr(node.right)) obj.add_terse('right_type', t.type_node(node.right_type)) obj.add_terse('or_block', t.or_expr(node.or_block)) obj.add_terse('is_option', t.bool_node(node.is_option)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) infix_expr(node ast.InfixExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('InfixExpr')) obj.add_terse('op', t.token_node(node.op)) obj.add_terse('left', t.expr(node.left)) obj.add_terse('left_type', t.type_node(node.left_type)) obj.add_terse('right', t.expr(node.right)) obj.add_terse('right_type', t.type_node(node.right_type)) obj.add_terse('promoted_type', t.type_node(node.promoted_type)) obj.add('auto_locked', t.string_node(node.auto_locked)) obj.add_terse('or_block', t.or_expr(node.or_block)) obj.add_terse('is_stmt', t.bool_node(node.is_stmt)) obj.add_terse('ct_left_value_evaled', t.bool_node(node.ct_left_value_evaled)) obj.add_terse('ct_left_value', t.comptime_expr_value(node.ct_left_value)) obj.add_terse('ct_right_value_evaled', t.bool_node(node.ct_right_value_evaled)) obj.add_terse('ct_right_value', t.comptime_expr_value(node.ct_right_value)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) index_expr(node ast.IndexExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('IndexExpr')) obj.add_terse('left', t.expr(node.left)) obj.add_terse('left_type', t.type_node(node.left_type)) obj.add_terse('index', t.expr(node.index)) obj.add_terse('is_setter', t.bool_node(node.is_setter)) obj.add_terse('is_direct', t.bool_node(node.is_direct)) obj.add_terse('or_expr', t.or_expr(node.or_expr)) obj.add_terse('typ', t.type_node(node.typ)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) postfix_expr(node ast.PostfixExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('PostfixExpr')) obj.add_terse('op', t.token_node(node.op)) obj.add_terse('expr', t.expr(node.expr)) obj.add('auto_locked', t.string_node(node.auto_locked)) obj.add('pos', t.pos(node.pos)) obj.add('is_c2v_prefix', t.bool_node(node.is_c2v_prefix)) return obj } fn (t Tree) selector_expr(node ast.SelectorExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('SelectorExpr')) obj.add_terse('expr', t.expr(node.expr)) obj.add_terse('expr_type', t.type_node(node.expr_type)) obj.add_terse('field_name', t.string_node(node.field_name)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('name_type', t.type_node(node.name_type)) obj.add_terse('or_block', t.or_expr(node.or_block)) obj.add_terse('gkind_field', t.enum_node(node.gkind_field)) obj.add_terse('from_embed_types', t.array_node_type(node.from_embed_types)) obj.add_terse('has_hidden_receiver', t.bool_node(node.has_hidden_receiver)) obj.add_terse('next_token', t.token_node(node.next_token)) obj.add_terse('is_field_typ', t.bool_node(node.is_field_typ)) obj.add('pos', t.pos(node.pos)) obj.add('scope', t.number_node(int(node.scope))) return obj } fn (t Tree) range_expr(node ast.RangeExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('RangeExpr')) obj.add_terse('low', t.expr(node.low)) obj.add_terse('high', t.expr(node.high)) obj.add_terse('has_high', t.bool_node(node.has_high)) obj.add_terse('has_low', t.bool_node(node.has_low)) obj.add_terse('typ', t.type_node(node.typ)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) if_expr(node ast.IfExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('IfExpr')) obj.add_terse('is_comptime', t.bool_node(node.is_comptime)) obj.add_terse('tok_kind', t.token_node(node.tok_kind)) obj.add_terse('branches', t.array_node_if_branch(node.branches)) obj.add_terse('left', t.expr(node.left)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('has_else', t.bool_node(node.has_else)) obj.add_terse('is_expr', t.bool_node(node.is_expr)) obj.add('pos', t.pos(node.pos)) obj.add('post_comments', t.array_node_comment(node.post_comments)) return obj } fn (t Tree) if_branch(node ast.IfBranch) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('IfBranch')) obj.add_terse('cond', t.expr(node.cond)) obj.add('pos', t.pos(node.pos)) obj.add('body_pos', t.pos(node.body_pos)) obj.add_terse('stmts', t.array_node_stmt(node.stmts)) obj.add('scope', t.number_node(int(node.scope))) obj.add('comments', t.array_node_comment(node.comments)) return obj } fn (t Tree) ident(node ast.Ident) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('Ident')) obj.add_terse('mod', t.string_node(node.mod)) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('language', t.enum_node(node.language)) obj.add_terse('is_mut', t.bool_node(node.is_mut)) obj.add_terse('comptime', t.bool_node(node.comptime)) obj.add_terse('tok_kind', t.token_node(node.tok_kind)) obj.add_terse('kind', t.enum_node(node.kind)) obj.add_terse('info', t.ident_info(node.info)) obj.add('pos', t.pos(node.pos)) obj.add('mut_pos', t.pos(node.mut_pos)) obj.add('obj', t.scope_object(node.obj)) obj.add('scope', t.number_node(int(node.scope))) obj.add_terse('or_expr', t.or_expr(node.or_expr)) return obj } fn (t Tree) ident_info(node ast.IdentInfo) &Node { match node { ast.IdentVar { return t.ident_var(node) } ast.IdentFn { return t.ident_fn(node) } } } fn (t Tree) ident_var(node ast.IdentVar) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('IdentVar')) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('is_mut', t.bool_node(node.is_mut)) obj.add_terse('is_static', t.bool_node(node.is_static)) obj.add_terse('is_volatile', t.bool_node(node.is_volatile)) obj.add_terse('is_option', t.bool_node(node.is_option)) obj.add_terse('share', t.enum_node(node.share)) return obj } fn (t Tree) ident_fn(node ast.IdentFn) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('IdentFn')) obj.add_terse('typ', t.type_node(node.typ)) return obj } fn (t Tree) call_expr(node ast.CallExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('CallExpr')) obj.add_terse('mod', t.string_node(node.mod)) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('const_name', t.string_node(node.const_name)) obj.add_terse('language', t.enum_node(node.language)) obj.add_terse('kind', t.enum_node(node.kind)) obj.add_terse('left_type', t.type_node(node.left_type)) obj.add_terse('receiver_type', t.type_node(node.receiver_type)) obj.add_terse('return_type', t.type_node(node.return_type)) obj.add_terse('fn_var_type', t.type_node(node.fn_var_type)) obj.add_terse('left', t.expr(node.left)) obj.add_terse('is_method', t.bool_node(node.is_method)) obj.add_terse('is_field', t.bool_node(node.is_field)) obj.add_terse('is_fn_var', t.bool_node(node.is_fn_var)) obj.add_terse('is_fn_a_const', t.bool_node(node.is_fn_a_const)) obj.add('is_keep_alive', t.bool_node(node.is_keep_alive)) obj.add_terse('is_noreturn', t.bool_node(node.is_noreturn)) obj.add_terse('is_ctor_new', t.bool_node(node.is_ctor_new)) obj.add_terse('is_return_used', t.bool_node(node.is_return_used)) obj.add_terse('is_static_method', t.bool_node(node.is_static_method)) obj.add_terse('is_variadic', t.bool_node(node.is_variadic)) obj.add('should_be_skipped', t.bool_node(node.should_be_skipped)) obj.add_terse('free_receiver', t.bool_node(node.free_receiver)) obj.add('scope', t.number_node(int(node.scope))) obj.add_terse('args', t.array_node_call_arg(node.args)) obj.add_terse('expected_arg_types', t.array_node_type(node.expected_arg_types)) obj.add_terse('concrete_types', t.array_node_type(node.concrete_types)) obj.add_terse('or_block', t.or_expr(node.or_block)) obj.add('concrete_list_pos', t.pos(node.concrete_list_pos)) obj.add_terse('from_embed_types', t.array_node_type(node.from_embed_types)) obj.add('comments', t.array_node_comment(node.comments)) obj.add('pos', t.pos(node.pos)) obj.add('name_pos', t.pos(node.name_pos)) return obj } fn (t Tree) call_arg(node ast.CallArg) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('CallArg')) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('is_mut', t.bool_node(node.is_mut)) obj.add_terse('share', t.enum_node(node.share)) obj.add_terse('expr', t.expr(node.expr)) obj.add_terse('should_be_ptr', t.bool_node(node.should_be_ptr)) obj.add('is_tmp_autofree', t.bool_node(node.is_tmp_autofree)) obj.add('pos', t.pos(node.pos)) obj.add('comments', t.array_node_comment(node.comments)) return obj } fn (t Tree) or_expr(node ast.OrExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('OrExpr')) obj.add_terse('stmts', t.array_node_stmt(node.stmts)) obj.add_terse('kind', t.enum_node(node.kind)) obj.add('pos', t.pos(node.pos)) obj.add('scope', t.number_node(int(node.scope))) return obj } fn (t Tree) struct_init(node ast.StructInit) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('StructInit')) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('no_keys', t.bool_node(node.no_keys)) obj.add_terse('is_short_syntax', t.bool_node(node.is_short_syntax)) obj.add_terse('is_anon', t.bool_node(node.is_anon)) obj.add_terse('unresolved', t.bool_node(node.unresolved)) obj.add_terse('has_update_expr', t.bool_node(node.has_update_expr)) obj.add_terse('update_expr', t.expr(node.update_expr)) obj.add_terse('update_expr_type', t.type_node(node.update_expr_type)) obj.add('pos', t.pos(node.pos)) obj.add('name_pos', t.pos(node.name_pos)) obj.add('update_expr_comments', t.array_node_comment(node.update_expr_comments)) obj.add('update_expr_pos', t.pos(node.update_expr_pos)) obj.add_terse('init_fields', t.array_node_struct_init_field(node.init_fields)) obj.add('pre_comments', t.array_node_comment(node.pre_comments)) return obj } fn (t Tree) struct_init_field(node ast.StructInitField) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('StructInitField')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('expr', t.expr(node.expr)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('expected_type', t.type_node(node.expected_type)) obj.add_terse('parent_type', t.type_node(node.parent_type)) obj.add('pre_comments', t.array_node_comment(node.pre_comments)) obj.add('end_comments', t.array_node_comment(node.end_comments)) obj.add('next_comments', t.array_node_comment(node.next_comments)) obj.add('pos', t.pos(node.pos)) obj.add('name_pos', t.pos(node.name_pos)) return obj } fn (t Tree) array_init(node ast.ArrayInit) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('ArrayInit')) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('elem_type', t.type_node(node.elem_type)) obj.add_terse('exprs', t.array_node_expr(node.exprs)) obj.add('ecmnts', t.two_dimension_comment(node.ecmnts)) obj.add('pre_cmnts', t.array_node_comment(node.pre_cmnts)) obj.add('elem_type_pos', t.pos(node.elem_type_pos)) obj.add_terse('is_fixed', t.bool_node(node.is_fixed)) obj.add_terse('is_option', t.bool_node(node.is_option)) obj.add_terse('has_val', t.bool_node(node.has_val)) obj.add_terse('mod', t.string_node(node.mod)) obj.add_terse('len_expr', t.expr(node.len_expr)) obj.add_terse('cap_expr', t.expr(node.cap_expr)) obj.add_terse('init_expr', t.expr(node.init_expr)) obj.add_terse('has_len', t.bool_node(node.has_len)) obj.add_terse('has_cap', t.bool_node(node.has_cap)) obj.add_terse('has_init', t.bool_node(node.has_init)) obj.add_terse('has_index', t.bool_node(node.has_index)) obj.add_terse('expr_types', t.array_node_type(node.expr_types)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) map_init(node ast.MapInit) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('MapInit')) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('key_type', t.type_node(node.key_type)) obj.add_terse('value_type', t.type_node(node.value_type)) obj.add_terse('keys', t.array_node_expr(node.keys)) obj.add_terse('vals', t.array_node_expr(node.vals)) obj.add_terse('val_types', t.array_node_type(node.val_types)) obj.add_terse('has_update_expr', t.bool_node(node.has_update_expr)) obj.add_terse('update_expr', t.expr(node.update_expr)) obj.add('pos', t.pos(node.pos)) obj.add('pre_cmnts', t.array_node_comment(node.pre_cmnts)) obj.add('comments', t.two_dimension_comment(node.comments)) obj.add('update_expr_comments', t.array_node_comment(node.update_expr_comments)) obj.add('update_expr_pos', t.pos(node.update_expr_pos)) return obj } fn (t Tree) none_expr(node ast.None) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('None')) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) par_expr(node ast.ParExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('ParExpr')) obj.add_terse('expr', t.expr(node.expr)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) if_guard_expr(node ast.IfGuardExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('IfGuardExpr')) obj.add_terse('vars', t.array_node_if_guard_var(node.vars)) obj.add_terse('expr', t.expr(node.expr)) obj.add_terse('expr_type', t.type_node(node.expr_type)) return obj } fn (t Tree) if_guard_var(node ast.IfGuardVar) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('IfGuardVar')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('is_mut', t.bool_node(node.is_mut)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) match_expr(node ast.MatchExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('MatchExpr')) obj.add_terse('tok_kind', t.token_node(node.tok_kind)) obj.add_terse('cond', t.expr(node.cond)) obj.add_terse('cond_type', t.type_node(node.cond_type)) obj.add_terse('return_type', t.type_node(node.return_type)) obj.add_terse('expected_type', t.type_node(node.expected_type)) obj.add_terse('is_sum_type', t.bool_node(node.is_sum_type)) obj.add_terse('is_expr', t.bool_node(node.is_expr)) obj.add('pos', t.pos(node.pos)) obj.add_terse('branches', t.array_node_match_branch(node.branches)) obj.add('comments', t.array_node_comment(node.comments)) return obj } fn (t Tree) match_branch(node ast.MatchBranch) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('MatchBranch')) obj.add('ecmnts', t.two_dimension_comment(node.ecmnts)) obj.add_terse('stmts', t.array_node_stmt(node.stmts)) obj.add_terse('is_else', t.bool_node(node.is_else)) obj.add('pos', t.pos(node.pos)) obj.add_terse('post_comments', t.array_node_comment(node.post_comments)) obj.add('branch_pos', t.pos(node.branch_pos)) obj.add_terse('exprs', t.array_node_expr(node.exprs)) obj.add('scope', t.number_node(int(node.scope))) return obj } fn (t Tree) concat_expr(node ast.ConcatExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('ConcatExpr')) obj.add_terse('vals', t.array_node_expr(node.vals)) obj.add_terse('return_type', t.type_node(node.return_type)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) type_of(node ast.TypeOf) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('TypeOf')) obj.add_terse('is_type', t.bool_node(node.is_type)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('expr', t.expr(node.expr)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) likely(node ast.Likely) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('Likely')) obj.add_terse('expr', t.expr(node.expr)) obj.add_terse('is_likely', t.bool_node(node.is_likely)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) sql_expr(node ast.SqlExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('SqlExpr')) obj.add_terse('type', t.type_node(node.typ)) obj.add_terse('aggregate_kind', t.string_node('${node.aggregate_kind}')) obj.add_terse('aggregate_field', t.string_node(node.aggregate_field)) obj.add_terse('db_expr', t.expr(node.db_expr)) obj.add_terse('table_expr', t.type_expr(node.table_expr)) obj.add_terse('has_where', t.bool_node(node.has_where)) obj.add_terse('where_expr', t.expr(node.where_expr)) obj.add_terse('has_order', t.bool_node(node.has_order)) obj.add_terse('order_expr', t.expr(node.order_expr)) obj.add_terse('has_desc', t.bool_node(node.has_desc)) obj.add_terse('is_array', t.bool_node(node.is_array)) obj.add_terse('or_expr', t.or_expr(node.or_expr)) obj.add('pos', t.pos(node.pos)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('has_limit', t.bool_node(node.has_limit)) obj.add_terse('limit_expr', t.expr(node.limit_expr)) obj.add_terse('has_offset', t.bool_node(node.has_offset)) obj.add_terse('offset_expr', t.expr(node.offset_expr)) obj.add_terse('fields', t.array_node_struct_field(node.fields)) mut sub_struct_map := create_object() for key, val in node.sub_structs { sub_struct_map.add_terse(key.str(), t.sql_expr(val)) } obj.add_terse('sub_structs', sub_struct_map) return obj } fn (t Tree) semicolon_stmt(node ast.SemicolonStmt) &Node { mut obj := create_object() obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) sql_stmt(node ast.SqlStmt) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('SqlStmt')) obj.add_terse('db_expr_type', t.type_node(node.db_expr_type)) obj.add_terse('db_expr', t.expr(node.db_expr)) obj.add_terse('or_expr', t.or_expr(node.or_expr)) obj.add('pos', t.pos(node.pos)) obj.add_terse('lines', t.array_node_sql_stmt_line(node.lines)) return obj } fn (t Tree) sql_stmt_line(node ast.SqlStmtLine) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('SqlStmtLine')) obj.add_terse('kind', t.enum_node(node.kind)) obj.add_terse('table_expr', t.type_expr(node.table_expr)) obj.add_terse('object_var', t.string_node(node.object_var)) obj.add_terse('where_expr', t.expr(node.where_expr)) obj.add_terse('fields', t.array_node_struct_field(node.fields)) obj.add_terse('updated_columns', t.array_node_string(node.updated_columns)) obj.add_terse('update_exprs', t.array_node_expr(node.update_exprs)) obj.add('pos', t.pos(node.pos)) obj.add('pre_comments', t.array_node_comment(node.pre_comments)) obj.add('end_comments', t.array_node_comment(node.end_comments)) mut sub_struct_map := create_object() for key, val in node.sub_structs { sub_struct_map.add_terse(key.str(), t.sql_stmt_line(val)) } obj.add_terse('sub_structs', sub_struct_map) return obj } fn (t Tree) lock_expr(expr ast.LockExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('LockExpr')) obj.add_terse('is_expr', t.bool_node(expr.is_expr)) obj.add_terse('typ', t.type_node(expr.typ)) obj.add('pos', t.pos(expr.pos)) obj.add_terse('stmts', t.array_node_stmt(expr.stmts)) obj.add_terse('lockeds', t.array_node_expr(expr.lockeds)) obj.add_terse('r_lock', t.array_node_bool(expr.is_rlock)) return obj } fn (t Tree) unsafe_expr(expr ast.UnsafeExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('UnsafeExpr')) obj.add_terse('expr', t.expr(expr.expr)) obj.add('pos', t.pos(expr.pos)) return obj } fn (t Tree) chan_init(expr ast.ChanInit) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('ChanInit')) obj.add_terse('has_cap', t.bool_node(expr.has_cap)) obj.add_terse('cap_expr', t.expr(expr.cap_expr)) obj.add_terse('typ', t.type_node(expr.typ)) obj.add_terse('elem_type', t.type_node(expr.elem_type)) obj.add('pos', t.pos(expr.pos)) obj.add('elem_type_pos', t.pos(expr.elem_type_pos)) return obj } fn (t Tree) select_expr(expr ast.SelectExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('SelectExpr')) obj.add_terse('branches', t.array_node_select_branch(expr.branches)) obj.add_terse('is_expr', t.bool_node(expr.is_expr)) obj.add_terse('has_exception', t.bool_node(expr.has_exception)) obj.add_terse('expected_type', t.type_node(expr.expected_type)) obj.add('pos', t.pos(expr.pos)) return obj } fn (t Tree) select_branch(expr ast.SelectBranch) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('SelectBranch')) obj.add_terse('stmt', t.stmt(expr.stmt)) obj.add_terse('stmts', t.array_node_stmt(expr.stmts)) obj.add('pos', t.pos(expr.pos)) obj.add('comment', t.comment(expr.comment)) obj.add_terse('is_else', t.bool_node(expr.is_else)) obj.add_terse('is_timeout', t.bool_node(expr.is_timeout)) obj.add('post_comments', t.array_node_comment(expr.post_comments)) return obj } fn (t Tree) array_decompose(expr ast.ArrayDecompose) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('ArrayDecompose')) obj.add_terse('expr', t.expr(expr.expr)) obj.add_terse('expr_type', t.type_node(expr.expr_type)) obj.add_terse('arg_type', t.type_node(expr.arg_type)) obj.add('pos', t.pos(expr.pos)) return obj } fn (t Tree) go_expr(expr ast.GoExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('GoExpr')) obj.add_terse('call_expr', t.call_expr(expr.call_expr)) obj.add_terse('is_expr', t.bool_node(expr.is_expr)) obj.add('pos', t.pos(expr.pos)) return obj } fn (t Tree) spawn_expr(expr ast.SpawnExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('SpawnExpr')) obj.add_terse('call_expr', t.call_expr(expr.call_expr)) obj.add_terse('is_expr', t.bool_node(expr.is_expr)) obj.add('pos', t.pos(expr.pos)) return obj } fn (t Tree) offset_of(expr ast.OffsetOf) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('OffsetOf')) obj.add_terse('struct_type', t.type_node(expr.struct_type)) obj.add_terse('field', t.string_node('field')) obj.add('pos', t.pos(expr.pos)) return obj } fn (t Tree) dump_expr(expr ast.DumpExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('DumpExpr')) obj.add_terse('expr', t.expr(expr.expr)) obj.add_terse('expr_type', t.type_node(expr.expr_type)) obj.add('pos', t.pos(expr.pos)) return obj } fn (t Tree) node_error(expr ast.NodeError) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('NodeError')) obj.add_terse('idx', t.number_node(expr.idx)) obj.add('pos', t.pos(expr.pos)) return obj } fn (t Tree) empty_expr(expr ast.EmptyExpr) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('EmptyExpr')) // obj.add('x', t.number_node(expr.x)) return obj } fn (t Tree) empty_stmt(node ast.EmptyStmt) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('EmptyStmt')) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) debugger_stmt(node ast.DebuggerStmt) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('DebuggerStmt')) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) nil_expr(node ast.Nil) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('Nil')) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) asm_stmt(node ast.AsmStmt) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('AsmStmt')) obj.add_terse('arch', t.enum_node(node.arch)) obj.add_terse('is_basic', t.bool_node(node.is_basic)) obj.add_terse('is_volatile', t.bool_node(node.is_volatile)) obj.add_terse('is_goto', t.bool_node(node.is_goto)) obj.add('scope', t.scope(node.scope)) // obj.add('scope', t.number_node(int(node.scope))) obj.add('pos', t.pos(node.pos)) obj.add_terse('clobbered', t.array_node_asm_clobbered(node.clobbered)) obj.add_terse('templates', t.array_node_asm_template(node.templates)) obj.add_terse('output', t.array_node_asm_io(node.output)) obj.add_terse('input', t.array_node_asm_io(node.input)) obj.add_terse('global_labels', t.array_node_string(node.global_labels)) obj.add_terse('local_labels', t.array_node_string(node.local_labels)) return obj } fn (t Tree) asm_register(node ast.AsmRegister) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('AsmRegister')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('size', t.number_node(node.size)) return obj } fn (t Tree) asm_template(node ast.AsmTemplate) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('AsmTemplate')) obj.add_terse('name', t.string_node(node.name)) obj.add_terse('is_label', t.bool_node(node.is_label)) obj.add_terse('is_directive', t.bool_node(node.is_directive)) obj.add_terse('args', t.array_node_asm_arg(node.args)) obj.add('comments', t.array_node_comment(node.comments)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) asm_addressing(node ast.AsmAddressing) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('AsmAddressing')) obj.add_terse('scale', t.number_node(node.scale)) obj.add_terse('mode', t.enum_node(node.mode)) obj.add_terse('segment', t.string_node(node.segment)) obj.add_terse('displacement', t.asm_arg(node.displacement)) obj.add_terse('base', t.asm_arg(node.base)) obj.add_terse('index', t.asm_arg(node.index)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) asm_arg(node ast.AsmArg) &Node { match node { ast.AsmAddressing { return t.asm_addressing(node) } ast.AsmAlias { return t.asm_alias(node) } ast.AsmDisp { return t.asm_disp(node) } ast.AsmRegister { return t.asm_register(node) } ast.BoolLiteral { return t.bool_literal(node) } ast.CharLiteral { return t.char_literal(node) } ast.FloatLiteral { return t.float_literal(node) } ast.IntegerLiteral { return t.integer_literal(node) } string { return t.string_node(node) } } } fn (t Tree) asm_alias(node ast.AsmAlias) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('AsmAlias')) obj.add_terse('name', t.string_node(node.name)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) asm_disp(node ast.AsmDisp) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('AsmDisp')) obj.add_terse('val', t.string_node(node.val)) obj.add('pos', t.pos(node.pos)) return obj } fn (t Tree) asm_clobbered(node ast.AsmClobbered) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('AsmClobbered')) obj.add_terse('reg', t.asm_register(node.reg)) obj.add('comments', t.array_node_comment(node.comments)) return obj } fn (t Tree) asm_io(node ast.AsmIO) &Node { mut obj := create_object() obj.add_terse('ast_type', t.string_node('AsmIO')) obj.add_terse('alias', t.string_node(node.alias)) obj.add_terse('constraint', t.string_node(node.constraint)) obj.add_terse('expr', t.expr(node.expr)) obj.add_terse('typ', t.type_node(node.typ)) obj.add('comments', t.array_node_comment(node.comments)) obj.add('pos', t.pos(node.pos)) return obj } // do not support yet by vlang // fn (t Tree) array_node1[T](nodes []T, method_name string) &Node { // mut arr := create_array() // // call method dynamically, V do not support yet // // error: todo: not a string literal // // for node in nodes { // // arr.add_item(t.$method_name(node)) // // } // // temp // $for method in Tree.methods { // if method.name == method_name { // for node in nodes { // res := t.$method(node) // arr.add_item(res) // TODO,waiting for bug fixed // } // } // } // return arr // } // do not support yet by vlang // fn (t Tree) array_node2[T](nodes []T) &Node { // mut arr := create_array() // for node in nodes { // match node { // string { // arr.add_item(t.string_node(node)) // } // ast.Comment { // arr.add_item(t.comment(node)) // } // ast.ConstField { // arr.add_item(t.const_field(node)) // } // else { // panic('unknown array type') // } // } // } // return arr // } // list all the different type of array node,temporarily fn (t Tree) array_node_string(nodes []string) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.string_node(node)) } return arr } fn (t Tree) array_node_position(nodes []token.Pos) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.pos(node)) } return arr } fn (t Tree) array_node_if_branch(nodes []ast.IfBranch) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.if_branch(node)) } return arr } fn (t Tree) array_node_fn_decl(nodes []ast.FnDecl) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.fn_decl(node)) } return arr } fn (t Tree) array_node_generic_fns(nodes []&ast.FnDecl) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.fn_decl(node)) } return arr } fn (t Tree) array_node_embed_file(nodes []ast.EmbeddedFile) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.embed_file(node)) } return arr } fn (t Tree) array_node_attr(nodes []ast.Attr) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.attr(node)) } return arr } fn (t Tree) array_node_scope_struct_field(nodes map[string]ast.ScopeStructField) &Node { mut arr := create_array() for _, node in nodes { arr.add_item(t.scope_struct_field(node)) } return arr } fn (t Tree) array_node_type(nodes []ast.Type) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.type_node(node)) } return arr } fn (t Tree) array_node_type_expr(nodes []ast.TypeNode) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.type_expr(node)) } return arr } fn (t Tree) array_node_import_symbol(nodes []ast.ImportSymbol) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.import_symbol(node)) } return arr } fn (t Tree) array_node_comment(nodes []ast.Comment) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.comment(node)) } return arr } fn (t Tree) array_node_const_field(nodes []ast.ConstField) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.const_field(node)) } return arr } fn (t Tree) array_node_arg(nodes []ast.Param) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.arg(node)) } return arr } fn (t Tree) array_node_stmt(nodes []ast.Stmt) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.stmt(node)) } return arr } fn (t Tree) array_node_defer_stmt(nodes []ast.DeferStmt) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.defer_stmt(node)) } return arr } fn (t Tree) array_node_struct_field(nodes []ast.StructField) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.struct_field(node)) } return arr } fn (t Tree) array_node_embed(nodes []ast.Embed) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.embed(node)) } return arr } fn (t Tree) array_node_enum_field(nodes []ast.EnumField) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.enum_field(node)) } return arr } fn (t Tree) array_node_global_field(nodes []ast.GlobalField) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.global_field(node)) } return arr } fn (t Tree) array_node_expr(nodes []ast.Expr) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.expr(node)) } return arr } fn (t Tree) array_node_call_arg(nodes []ast.CallArg) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.call_arg(node)) } return arr } fn (t Tree) array_node_int(nodes []int) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.number_node(node)) } return arr } fn (t Tree) array_node_u8(nodes []u8) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.number_node(node)) } return arr } fn (t Tree) array_node_bool(nodes []bool) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.bool_node(node)) } return arr } fn (t Tree) array_node_struct_init_field(nodes []ast.StructInitField) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.struct_init_field(node)) } return arr } fn (t Tree) array_node_if_guard_var(nodes []ast.IfGuardVar) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.if_guard_var(node)) } return arr } fn (t Tree) array_node_match_branch(nodes []ast.MatchBranch) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.match_branch(node)) } return arr } fn (t Tree) array_node_ident(nodes []ast.Ident) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.ident(node)) } return arr } fn (t Tree) array_node_select_branch(nodes []ast.SelectBranch) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.select_branch(node)) } return arr } fn (t Tree) array_node_asm_clobbered(nodes []ast.AsmClobbered) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.asm_clobbered(node)) } return arr } fn (t Tree) array_node_asm_template(nodes []ast.AsmTemplate) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.asm_template(node)) } return arr } fn (t Tree) array_node_asm_io(nodes []ast.AsmIO) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.asm_io(node)) } return arr } fn (t Tree) array_node_asm_arg(nodes []ast.AsmArg) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.asm_arg(node)) } return arr } fn (t Tree) array_node_sql_stmt_line(nodes []ast.SqlStmtLine) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.sql_stmt_line(node)) } return arr } fn (t Tree) array_node_interface_embedding(nodes []ast.InterfaceEmbedding) &Node { mut arr := create_array() for node in nodes { arr.add_item(t.interface_embedding(node)) } return arr } ================================================ FILE: cmd/tools/vast2/vast2.v ================================================ // Copyright (c) 2020-2024 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. module main import os import v2.ast import v2.ast_dump import v2.parser import v2.pref import v2.token import v2.transformer import v2.types fn main() { args := os.args[1..] if args.len == 0 { eprintln('Usage: vast ') eprintln('Dumps AST to _ast.json and _ast_transformed.json') exit(1) } files := get_files(args) if files.len == 0 { eprintln('Usage: vast ') eprintln('Dumps AST to _ast.json and _ast_transformed.json') exit(1) } // Get base name for output files input_file := files[0] base_name := if input_file.ends_with('.v') { input_file[..input_file.len - 2] } else { input_file } prefs := pref.new_preferences() mut file_set := token.FileSet.new() mut p := parser.Parser.new(&prefs) // Parse builtin and dependencies first mut ast_files := []ast.File{} ast_files << p.parse_files(get_v_files_from_dir(prefs.get_vlib_module_path('builtin')), mut file_set) ast_files << p.parse_files(get_v_files_from_dir(prefs.get_vlib_module_path('strconv')), mut file_set) ast_files << p.parse_files(get_v_files_from_dir(prefs.get_vlib_module_path('strings')), mut file_set) ast_files << p.parse_files(get_v_files_from_dir(prefs.get_vlib_module_path('hash')), mut file_set) ast_files << p.parse_files(get_v_files_from_dir(prefs.get_vlib_module_path('math.bits')), mut file_set) // Parse the user file(s) ast_files << p.parse_files(files, mut file_set) // Write pre-transformation AST (only user files, not builtin) user_files := ast_files.filter(it.name in files) ast_json := ast_dump.dump_files(user_files) ast_file := '${base_name}_ast.json' os.write_file(ast_file, ast_json) or { eprintln('Failed to write ${ast_file}: ${err}') exit(1) } println('Wrote ${ast_file}') // Type check env := types.Environment.new() mut checker := types.Checker.new(&prefs, file_set, env) checker.check_files(ast_files) // Transform mut trans := transformer.Transformer.new_with_pref(ast_files, env, &prefs) transformed_files := trans.transform_files(ast_files) // Write post-transformation AST (only user files) transformed_user_files := transformed_files.filter(it.name in files) transformed_json := ast_dump.dump_files(transformed_user_files) transformed_file := '${base_name}_ast_transformed.json' os.write_file(transformed_file, transformed_json) or { eprintln('Failed to write ${transformed_file}: ${err}') exit(1) } println('Wrote ${transformed_file}') } // get_files extracts source files from args, excluding options and their values fn get_files(args []string) []string { options_with_values := ['-o', '-output'] mut files := []string{} mut skip_next := false for arg in args { if skip_next { skip_next = false continue } if arg.starts_with('-') { if arg in options_with_values { skip_next = true } continue } files << arg } return files } fn get_v_files_from_dir(dir string) []string { mut v_files := []string{} all_files := os.ls(dir) or { return v_files } for file in all_files { if file.ends_with('.v') && !file.ends_with('_test.v') { // Skip platform-specific files that don't match current platform if should_include_file(file) { v_files << os.join_path(dir, file) } } } return v_files } fn should_include_file(filename string) bool { // Skip test files (including _test.c.v) if filename.contains('_test.') { return false } // Skip JavaScript backend files if filename.ends_with('.js.v') { return false } // Handle platform-specific files current_os := os.user_os() // Check for OS-specific suffixes like _linux.v, _windows.v, _macos.v os_suffixes := ['_linux.v', '_windows.v', '_macos.v', '_darwin.v', '_freebsd.v', '_openbsd.v', '_netbsd.v', '_solaris.v', '_haiku.v', '_android.v'] for suffix in os_suffixes { if filename.ends_with(suffix) { // Include only if it matches current OS if suffix == '_darwin.v' || suffix == '_macos.v' { return current_os == 'macos' } else if suffix == '_linux.v' { return current_os == 'linux' } else if suffix == '_windows.v' { return current_os == 'windows' } return false } } // Check for "not this OS" files like _nix.v (not windows) if filename.ends_with('_nix.v') { return current_os != 'windows' } return true } ================================================ FILE: cmd/tools/vbin2v.v ================================================ module main import os import flag import strings const tool_version = '0.0.4' const tool_description = 'Converts a list of arbitrary files into a single v module file.' struct Context { mut: files []string prefix string show_help bool module_name string write_file string } fn (context Context) header() string { mut header_s := '' header_s += 'module ${context.module_name}\n' header_s += '\n' allfiles := context.files.join(' ') mut options := []string{} if context.prefix.len > 0 { options << '-p ${context.prefix}' } if context.module_name.len > 0 { options << '-m ${context.module_name}' } if context.write_file.len > 0 { options << '-w ${context.write_file}' } soptions := options.join(' ') header_s += '// File generated by:\n' header_s += '// v bin2v ${allfiles} ${soptions}\n' header_s += '// Please, do not edit this file.\n' header_s += '// Your changes may be overwritten.\n' return header_s } fn (context Context) footer() string { return '' } fn (context Context) file2v(bname string, fbytes []u8, bn_max int) string { mut sb := strings.new_builder(1000) sb.write_string('const ${bname}_len' + ' = ${fbytes.len}\n') fbyte := fbytes[0] bnmae_line := 'const ${bname}' + ' = [u8(${fbyte}), ' sb.write_string(bnmae_line) mut line_len := bnmae_line.len + 3 for i := 1; i < fbytes.len; i++ { b := int(fbytes[i]).str() if line_len > 98 { sb.go_back(1) sb.write_string('\n\t') line_len = 8 } if i == fbytes.len - 1 { sb.write_string(b) line_len += b.len } else { sb.write_string('${b}, ') line_len += b.len + 2 } } sb.write_string(']!\n') return sb.str() } fn (context Context) bname_and_bytes(file string) !(string, []u8) { fname := os.file_name(file) fname_escaped := fname.replace_each(['.', '_', '-', '_']) byte_name := '${context.prefix}${fname_escaped}'.to_lower() fbytes := os.read_bytes(file) or { return error('Error: ${err.msg()}') } return byte_name, fbytes } fn (context Context) max_bname_len(bnames []string) int { mut max := 0 for n in bnames { if n.len > max { max = n.len } } // Add 4 to max due to "_len" suffix return max + 4 } fn main() { mut context := Context{} mut fp := flag.new_flag_parser(os.args[1..]) fp.application('v bin2v') fp.version(tool_version) fp.description(tool_description) fp.arguments_description('FILE [FILE]...') context.show_help = fp.bool('help', `h`, false, 'Show this help screen.') context.module_name = fp.string('module', `m`, 'binary', 'Name of the generated module.') context.prefix = fp.string('prefix', `p`, '', 'A prefix put before each resource name.') context.write_file = fp.string('write', `w`, '', 'Write directly to a file with the given name.') if context.show_help { println(fp.usage()) exit(0) } files := fp.finalize() or { eprintln('Error: ${err.msg()}') exit(1) } real_files := files.filter(it != 'bin2v') if real_files.len == 0 { println(fp.usage()) exit(0) } context.files = real_files if context.write_file != '' && os.file_ext(context.write_file) !in ['.vv', '.v'] { context.write_file += '.v' } mut file_byte_map := map[string][]u8{} for file in real_files { bname, fbytes := context.bname_and_bytes(file) or { eprintln(err.msg()) exit(1) } file_byte_map[bname] = fbytes } max_bname := context.max_bname_len(file_byte_map.keys()) if context.write_file.len > 0 { mut out_file := os.create(context.write_file)! out_file.write_string(context.header())! for bname, fbytes in file_byte_map { out_file.write_string(context.file2v(bname, fbytes, max_bname))! } out_file.write_string(context.footer())! } else { print(context.header()) for bname, fbytes in file_byte_map { print(context.file2v(bname, fbytes, max_bname)) } print(context.footer()) } } ================================================ FILE: cmd/tools/vbug.v ================================================ import os import term import readline import net.urllib fn elog(msg string) { eprintln(term.ecolorize(term.gray, msg)) } fn olog(msg string) { println(term.colorize(term.green, msg)) } fn vversion() string { vexe := os.getenv('VEXE') return os.execute('${os.quoted_path(vexe)} version').output.trim_space() } // get output from `v doctor` fn get_vdoctor_output(is_verbose bool) string { vexe := os.getenv('VEXE') verbose_flag := if is_verbose { '-v' } else { '' } result := os.execute('${os.quoted_path(vexe)} ${verbose_flag} doctor') if result.exit_code != 0 { elog('> unable to get `v doctor` output: ${result.output}') return '' } return result.output } fn runv(label string, user_cmd string) os.Result { mut result := os.Result{} elog('> ${label} using: ${term.ecolorize(term.magenta, user_cmd)}') result = os.execute(user_cmd) print(result.output) return result } // get output from `./v -g -o vdbg cmd/v && ./vdbg -user_args run file.v` fn get_v_build_output(is_verbose bool, is_yes bool, file_path string, user_args string, generated_file string) string { mut result := os.Result{} mut vexe := os.getenv('VEXE') // prepare a V compiler with -g to have better backtraces if possible wd := os.getwd() vroot := @VMODROOT os.chdir(vroot) or {} verbose_flag := if is_verbose { '-v' } else { '' } vdbg_path := $if windows { '${vroot}/vdbg.exe' } $else { '${vroot}/vdbg' } vdbg_compilation_cmd := '${os.quoted_path(vexe)} ${verbose_flag} -g -o ${os.quoted_path(vdbg_path)} cmd/v' result = runv('Prepare vdbg', vdbg_compilation_cmd) os.chdir(wd) or {} if result.exit_code == 0 { vexe = vdbg_path } else { elog('> unable to compile V in debug mode: ${result.output}\ncommand: ${vdbg_compilation_cmd}\n') } result = runv('Compile', '${os.quoted_path(vexe)} ${verbose_flag} ${user_args} ${os.quoted_path(file_path)}') defer { os.rm(vdbg_path) or { if is_verbose { elog('> unable to delete `vdbg`: ${err}') } } } if result.exit_code == 0 { real_generated_file := os.real_path(generated_file) defer(fn) { os.rm(generated_file) or { if is_verbose { elog('> unable to delete generated file: ${err}') } } } run := is_yes || ask('It looks like the compilation went well, do you want to run the file?') if run { result = runv('Run', real_generated_file) if result.exit_code == 0 && !is_yes { elog('> The file ran correctly as well.') confirm_or_exit('Are you sure you want to continue?') } } } return result.output } fn ask(msg string) bool { prompt := os.input_opt(term.colorize(term.bright_white, '${msg} [Y/n] ')) or { 'y' } return prompt == '' || prompt[0].ascii_str().to_lower() != 'n' } fn confirm_or_exit(msg string) { if !ask(msg) { exit(1) } } fn main() { unbuffer_stdout() mut compiler_args := []string{} mut file_path := '' is_verbose := '-v' in os.args is_yes := '-y' in os.args for arg in os.args[1..] { if arg == 'bug' { continue } if arg.ends_with('.v') || arg.ends_with('.vsh') || arg.ends_with('.vv') { if file_path != '' { elog('> v bug: only one V file can be submitted') exit(1) } file_path = arg } else { if arg !in ['-y', '-v'] { compiler_args << arg } } } if file_path == '' { elog('> v bug: no v file listed to report') exit(1) } os.unsetenv('VCOLORS') // collect error information // output from `v doctor` vdoctor_output := get_vdoctor_output(is_verbose) // file content file_content := os.read_file(file_path) or { elog('> unable to get file "${file_path}" content: ${err}') '' } user_args := compiler_args.join(' ') mut generated_file := file_path.all_before_last('.') if os.user_os() == 'windows' { generated_file += '.exe' } build_output := get_v_build_output(is_verbose, is_yes, file_path, user_args, generated_file) // ask the user if he wants to submit even after an error if !is_yes && (vdoctor_output == '' || file_content == '' || build_output == '') { elog('> Error while retrieving the information.') confirm_or_exit('Do you want to continue?') } expected_result := readline.read_line('What did you expect to see? ') or { // Ctrl-C was pressed elog('\nCanceled') exit(1) } // open prefilled issue creation page, or print link as a fallback if !is_yes && vdoctor_output.contains('behind V master') { olog('> It looks like your installation of V is outdated.') olog('> We advise you to run `v up` before submitting an issue.') confirm_or_exit('Are you sure you want to continue?') } // When updating this template, make sure to update `.github/ISSUE_TEMPLATE/bug_report.md` too raw_body := '
V version: ${vversion()}, press to see full `v doctor` output ${vdoctor_output}
**What did you do?** `./v -g -o vdbg cmd/v && ./vdbg ${user_args} ${file_path} && ${os.real_path(generated_file)}` {file_content} **What did you see?** ``` ${build_output}``` **What did you expect to see?** ${expected_result} ' mut encoded_body := urllib.query_escape(raw_body.replace_once('{file_content}', '```v\n${file_content}\n```')) mut generated_uri := 'https://github.com/vlang/v/issues/new?labels=Bug&body=${encoded_body}' if generated_uri.len > 8192 { // GitHub doesn't support URLs longer than 8192 characters encoded_body = urllib.query_escape(raw_body.replace_once('{file_content}', 'See attached file `${file_path}`')) generated_uri = 'https://github.com/vlang/v/issues/new?labels=Bug&body=${encoded_body}' elog('> Your file is too big to be submitted.') elog('> Go to the following URL, and attach your file:') olog(generated_uri) } else { os.open_uri(generated_uri) or { if is_verbose { elog(err.str()) } olog(generated_uri) } } } ================================================ FILE: cmd/tools/vbuild-examples.v ================================================ module main import os import testing const vroot = os.dir(os.real_path(os.getenv_opt('VEXE') or { @VEXE })) // build as a project folder const efolders = [ 'examples/viewer', 'examples/vweb_orm_jwt', 'examples/vweb_fullstack', 'examples/fasthttp', ] pub fn normalised_vroot_path(path string) string { return os.real_path(os.join_path_single(vroot, path)).replace('\\', '/') } fn main() { args_string := os.args[1..].join(' ') params := args_string.all_before('build-examples') mut skip_prefixes := efolders.map(normalised_vroot_path(it)) res := testing.v_build_failing_skipped(params, 'examples', skip_prefixes, fn (mut session testing.TestSession) { for x in efolders { pathsegments := x.split_any('/') session.add(os.real_path(os.join_path(vroot, ...pathsegments))) } }) if res { exit(1) } if testing.v_build_failing_skipped(params + '-live', os.join_path_single('examples', 'hot_reload'), skip_prefixes, fn (mut session testing.TestSession) {}) { exit(1) } } ================================================ FILE: cmd/tools/vbuild-tools.v ================================================ module main import os import testing import v.util // Note: tools like vdoc are compiled in their own subfolder // => cmd/tools/vdoc/vdoc.exe // Usually, they have several top level .v files in the subfolder, // that cannot be compiled separately, but instead, the whole folder, // should be compiled (v folder). // To implement that, these folders are initially skipped, then added // as a whole *after the testing.prepare_test_session call*. const tools_in_subfolders = ['vast', 'vcreate', 'vdoc', 'vpm', 'vsymlink', 'vvet', 'vwhere', 'vcover'] // non_packaged_tools are tools that should not be packaged with // prebuild versions of V, to keep the size smaller. // They are mainly useful for the V project itself, not to end users. const non_packaged_tools = ['gen1m', 'gen_vc', 'fast', 'wyhash'] fn main() { if os.getenv('VTEST_SANDBOXED_PACKAGING') == '' { util.ensure_modules_for_all_tools_are_installed('-v' in os.args) } args_string := os.args[1..].join(' ') vexe := os.getenv('VEXE') vroot := os.dir(vexe) os.chdir(vroot)! folder := os.join_path('cmd', 'tools') tfolder := os.join_path(vroot, 'cmd', 'tools') main_label := 'Building ${folder} ...' finish_label := 'building ${folder}' mut skips := []string{} for stool in tools_in_subfolders { skips << os.join_path(tfolder, stool).replace('\\', '/') } buildopts := args_string.all_before('build-tools') mut session := testing.prepare_test_session(buildopts, folder, skips, main_label) session.rm_binaries = false session.build_tools = true for stool in tools_in_subfolders { session.add(os.join_path(tfolder, stool)) } // eprintln('> session.files: ${session.files}') // eprintln('> session.skip_files: ${session.skip_files}') session.test() eprintln(session.benchmark.total_message(finish_label)) if session.failed_cmds.len > 0 { exit(1) } mut executables := os.ls(session.vtmp_dir)! executables.sort() for texe in executables { tname := texe.replace(os.file_ext(texe), '') if tname in non_packaged_tools { continue } // tpath := os.join_path(session.vtmp_dir, texe) if texe.ends_with('_builder') || texe.ends_with('_builder.exe') { os.mv_by_cp(tpath, os.join_path(tfolder, 'builders', texe)) or { panic(err) } continue } if tname in tools_in_subfolders { os.mv_by_cp(tpath, os.join_path(tfolder, tname, texe)) or { panic(err) } continue } if os.is_dir(tpath) { continue } target_path := os.join_path(tfolder, texe) os.mv_by_cp(tpath, target_path) or { emsg := err.msg() if !emsg.contains('vbuild-tools') && !emsg.contains('vtest-all') { eprintln('error while moving ${tpath} to ${target_path}: ${emsg}') } continue } } } ================================================ FILE: cmd/tools/vbuild-vbinaries.v ================================================ module main import testing fn main() { if testing.building_any_v_binaries_failed() { exit(1) } } ================================================ FILE: cmd/tools/vbump.v ================================================ // Copyright (c) 2019-2024 Subhomoy Haldar. All rights reserved. // Use of this source code is governed by an MIT license that can be found in the LICENSE file. module main import flag import os import regex import semver const tool_name = os.file_name(os.executable()) const tool_version = '0.1.0' const tool_description = '\n Bump the semantic version of the v.mod and/or specified files. The first instance of a version number is replaced with the new version. Additionally, the line affected must contain the word "version" in any form of capitalization. For instance, the following lines will be recognized by the heuristic: tool_version = \'1.2.1\' version: \'0.2.42\' VERSION = "1.23.8" If certain lines need to be skipped, use the --skip option. For instance, the following command will skip lines containing "tool-version": v bump --patch --skip "tool-version" [files...] Examples: Bump the patch version in v.mod if it exists v bump --patch Bump the major version in v.mod and vls.v v bump --major v.mod vls.v Upgrade the minor version in sample.v only v bump --minor sample.v ' const semver_query = r'((0)|([1-9]\d*)\.){2}(0)|([1-9]\d*)(\-[\w\d\.\-_]+)?(\+[\w\d\.\-_]+)?' struct Options { show_help bool major bool minor bool patch bool skip string } type ReplacementFunction = fn (re regex.RE, input string, start int, end int) string fn replace_with_increased_patch_version(re regex.RE, input string, start int, end int) string { version := semver.from(input[start..end]) or { return input } return version.increment(.patch).str() } fn replace_with_increased_minor_version(re regex.RE, input string, start int, end int) string { version := semver.from(input[start..end]) or { return input } return version.increment(.minor).str() } fn replace_with_increased_major_version(re regex.RE, input string, start int, end int) string { version := semver.from(input[start..end]) or { return input } return version.increment(.major).str() } fn get_replacement_function(options Options) ReplacementFunction { if options.patch { return replace_with_increased_patch_version } else if options.minor { return replace_with_increased_minor_version } else if options.major { return replace_with_increased_major_version } return replace_with_increased_patch_version } fn process_file(input_file string, options Options) ! { lines := os.read_lines(input_file) or { return error('Failed to read file: ${input_file}') } mut re := regex.regex_opt(semver_query) or { return error('Could not create a RegEx parser.') } repl_fn := get_replacement_function(options) mut new_lines := []string{cap: lines.len} mut replacement_complete := false for line in lines { // Copy over the remaining lines normally if the replacement is complete if replacement_complete { new_lines << line continue } // Check if replacement is necessary updated_line := if line.to_lower().contains('version') && !(options.skip != '' && line.contains(options.skip)) { replacement_complete = true re.replace_by_fn(line, repl_fn) } else { line } new_lines << updated_line } // Add a trailing newline new_lines << '' backup_file := input_file + '.cache' // Remove the backup file if it exists. os.rm(backup_file) or {} // Rename the original to the backup. os.mv(input_file, backup_file) or { return error('Failed to move file: ${input_file}') } // Process the old file and write it back to the original. os.write_file(input_file, new_lines.join_lines()) or { return error('Failed to write file: ${input_file}') } // Remove the backup file. os.rm(backup_file) or {} if replacement_complete { println('Bumped version in ${input_file}') } else { println('No changes made in ${input_file}') } } fn main() { if os.args.len < 2 { eprintln('Usage: ${tool_name} [options] [file1 file2 ...] ${tool_description} Try ${tool_name} -h for more help...') exit(1) } mut fp := flag.new_flag_parser(os.args) fp.application(tool_name) fp.version(tool_version) fp.description(tool_description) fp.arguments_description('[file1 file2 ...]') fp.skip_executable() options := Options{ show_help: fp.bool('help', `h`, false, 'Show this help text.') patch: fp.bool('patch', `p`, false, 'Bump the patch version.') minor: fp.bool('minor', `n`, false, 'Bump the minor version.') major: fp.bool('major', `m`, false, 'Bump the major version.') skip: fp.string('skip', `s`, '', 'Skip lines matching this substring.').trim_space() } remaining := fp.finalize() or { eprintln(fp.usage()) exit(1) } if options.show_help { println(fp.usage()) exit(0) } validate_options(options) or { eprintln(fp.usage()) exit(1) } files := remaining[1..] if files.len == 0 { if !os.exists('v.mod') { eprintln('v.mod does not exist. You can create one using "v init".') exit(1) } process_file('v.mod', options) or { eprintln('Failed to process v.mod: ${err}') exit(1) } } for input_file in files { if !os.exists(input_file) { eprintln('File not found: ${input_file}') exit(1) } process_file(input_file, options) or { eprintln('Failed to process ${input_file}: ${err}') exit(1) } } } fn validate_options(options Options) ! { if options.patch && options.major { return error('Cannot specify both --patch and --major.') } if options.patch && options.minor { return error('Cannot specify both --patch and --minor.') } if options.major && options.minor { return error('Cannot specify both --major and --minor.') } if !(options.patch || options.major || options.minor) { return error('Must specify one of --patch, --major, or --minor.') } } ================================================ FILE: cmd/tools/vbump_test.v ================================================ import os const vexe = @VEXE const tfolder = os.join_path(os.vtmp_dir(), 'vbump') fn testsuite_begin() { os.mkdir_all(tfolder) or {} } fn testsuite_end() { os.rmdir_all(tfolder) or {} } struct BumpTestCase { file_name string contents string line int expected_patch string expected_minor string expected_major string } const test_cases = [ BumpTestCase{ file_name: 'v.mod' contents: "Module { name: 'Sample' description: 'Sample project' version: '1.2.6' license: 'MIT' dependencies: [] } " line: 3 expected_patch: " version: '1.2.7'" expected_minor: " version: '1.3.0'" expected_major: " version: '2.0.0'" }, BumpTestCase{ file_name: 'random_versions.vv' contents: " 1.1.2 1.2.5 3.21.73 version = '1.5.1' " line: 4 expected_patch: "version = '1.5.2'" expected_minor: "version = '1.6.0'" expected_major: "version = '2.0.0'" }, BumpTestCase{ file_name: 'sample_tool.v' contents: "// Module comment and copyright information import os import flag const tool_name = os.file_name(os.executable()) const tool_version = '0.1.33' fn main() { // stuff } " line: 5 expected_patch: "const tool_version = '0.1.34'" expected_minor: "const tool_version = '0.2.0'" expected_major: "const tool_version = '1.0.0'" }, ] fn run_individual_test(case BumpTestCase) ! { test_file := os.join_path_single(tfolder, case.file_name) os.rm(test_file) or {} os.write_file(test_file, case.contents)! os.execute_or_exit('${os.quoted_path(vexe)} bump --patch ${os.quoted_path(test_file)}') patch_lines := os.read_lines(test_file)! assert patch_lines[case.line] == case.expected_patch os.execute_or_exit('${os.quoted_path(vexe)} bump --minor ${os.quoted_path(test_file)}') minor_lines := os.read_lines(test_file)! assert minor_lines[case.line] == case.expected_minor os.execute_or_exit('${os.quoted_path(vexe)} bump --major ${os.quoted_path(test_file)}') major_lines := os.read_lines(test_file)! assert major_lines[case.line] == case.expected_major os.rm(test_file)! } fn test_all_bump_cases() { for case in test_cases { run_individual_test(case) or { panic(err) } } } struct SkipTestCase { file_name string contents string skip string line int expected_patch string expected_minor string expected_major string } const skip_test_cases = [ SkipTestCase{ file_name: 'CITATION.cff' contents: 'abstract: A sample CLI tool made in V that prints geometric shapes to the screen. authors: - alias: hungrybluedev family-names: Haldar given-names: Subhomoy cff-version: 1.2.0 date-released: 2023-04-20 license: MIT message: Please cite this software using these information. repository-code: https://github.com/hungrybluedev/geo title: geo url: https://github.com/hungrybluedev/geo version: 0.2.4 ' line: 12 skip: 'cff-version' expected_patch: 'version: 0.2.5' expected_minor: 'version: 0.3.0' expected_major: 'version: 1.0.0' }, ] fn run_skip_test(case SkipTestCase) ! { test_file := os.join_path_single(tfolder, case.file_name) os.rm(test_file) or {} os.write_file(test_file, case.contents)! os.execute_or_exit('${os.quoted_path(vexe)} bump --patch --skip="${case.skip}" ${os.quoted_path(test_file)}') patch_lines := os.read_lines(test_file)! assert patch_lines[case.line] == case.expected_patch os.execute_or_exit('${os.quoted_path(vexe)} bump --minor --skip="${case.skip}" ${os.quoted_path(test_file)}') minor_lines := os.read_lines(test_file)! assert minor_lines[case.line] == case.expected_minor os.execute_or_exit('${os.quoted_path(vexe)} bump --major --skip="${case.skip}" ${os.quoted_path(test_file)}') major_lines := os.read_lines(test_file)! assert major_lines[case.line] == case.expected_major os.rm(test_file)! } fn test_all_skip_bump_cases() ! { for case in skip_test_cases { run_skip_test(case) or { panic(err) } } } ================================================ FILE: cmd/tools/vcheck-md.v ================================================ // Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. module main import os import os.cmdline import rand import term import v.help import regex const too_long_line_length_example = 120 const too_long_line_length_codeblock = 120 const too_long_line_length_table = 160 const too_long_line_length_link = 250 const too_long_line_length_other = 100 const term_colors = term.can_show_color_on_stderr() const hide_warnings = '-hide-warnings' in os.args || '-w' in os.args const show_progress = os.getenv('GITHUB_JOB') == '' && '-silent' !in os.args const non_option_args = cmdline.only_non_options(os.args[2..]) const is_verbose = os.getenv('VERBOSE') != '' const vcheckfolder = os.join_path(os.vtmp_dir(), 'vcheck_${os.getpid()}') const should_autofix = os.getenv('VAUTOFIX') != '' || '-fix' in os.args const vexe = @VEXE struct CheckResult { pub mut: files int lines int examples int oks int warnings int ferrors int errors int } struct VCheckIgnoreRule { base_dir string pattern string } struct VCheckIgnoreContext { repo_root string } struct VCheckIgnoreMatch { ignore_file string pattern string } struct MDPathScanResult { files []string skipped int } fn (v1 CheckResult) + (v2 CheckResult) CheckResult { return CheckResult{ files: v1.files + v2.files lines: v1.lines + v2.lines examples: v1.examples + v2.examples oks: v1.oks + v2.oks warnings: v1.warnings + v2.warnings ferrors: v1.ferrors + v2.ferrors errors: v1.errors + v2.errors } } fn main() { unbuffer_stdout() if non_option_args.len == 0 || '-help' in os.args { help.print_and_exit('check-md') } if '-all' in os.args { println('´-all´ flag is deprecated. Please use ´v check-md .´ instead.') exit(1) } mut skip_line_length_check := '-skip-line-length-check' in os.args mut files_paths := non_option_args.clone() mut res := CheckResult{} if term_colors { os.setenv('VCOLORS', 'always', true) } os.mkdir_all(vcheckfolder, mode: 0o700) or {} // keep directory private defer { os.rmdir_all(vcheckfolder) or {} } mut all_mdfiles := []MDFile{} mut skipped_mdfiles := 0 for i := 0; i < files_paths.len; i++ { file_path := files_paths[i] if os.is_dir(file_path) { scan_result := md_file_paths(file_path) files_paths << scan_result.files skipped_mdfiles += scan_result.skipped continue } real_path := os.real_path(file_path) lines := os.read_lines(real_path) or { println('"${file_path}" does not exist') res.warnings++ continue } all_mdfiles << MDFile{ skip_line_length_check: skip_line_length_check path: file_path lines: lines } } println('> Found: ${all_mdfiles.len} .md files. Skipped by .vcheckignore: ${skipped_mdfiles}.') if is_verbose { for idx, mdfile in all_mdfiles { println('> file ${idx + 1} is ${mdfile.path}') } } if show_progress { // this is intended to be replaced by the progress lines println('') } for idx, mut mdfile in all_mdfiles { mdfile.idx = idx mdfile.nfiles = all_mdfiles.len res += mdfile.check() } if res.errors == 0 && show_progress { clear_previous_line() } println('Checked .md files: ${res.files} | Ex.: ${res.examples} | Lines: ${res.lines} | OKs: ${res.oks} | Warnings: ${res.warnings} | Errors: ${res.errors} | Fmt errors: ${res.ferrors}') if res.ferrors > 0 && !should_autofix { println('Note: you can use `VAUTOFIX=1 v check-md file.md`, or `v check-md -fix file.md`,') println(' to fix the V formatting errors in the markdown code blocks, when possible.') println(' Run the command 2 times, to verify that all formatting errors were fixed.') println('Note: `v help check-md` shows a list of ```v fence keywords (for partial code).') } if res.errors > 0 { exit(1) } } fn md_file_paths(dir string) MDPathScanResult { mut files_to_check := []string{} mut skipped := 0 vcheckignore := collect_vcheckignore_context(dir) md_files := os.walk_ext(dir, '.md') for file in md_files { nfile := file.replace('\\', '/') if nfile.contains_any_substr(['/thirdparty/', 'CHANGELOG', '/testdata/']) { continue } if skip_match := vcheckignore.skip_match(file) { if is_verbose { println('SKIP: ${vcheckignore.repo_relative_path(file)} (from ${vcheckignore.repo_relative_path(skip_match.ignore_file)}: ${skip_match.pattern})') } skipped++ continue } files_to_check << file } return MDPathScanResult{ files: files_to_check skipped: skipped } } fn collect_vcheckignore_context(cwd string) VCheckIgnoreContext { repo_root := find_repo_root(cwd) return VCheckIgnoreContext{ repo_root: repo_root } } fn find_repo_root(cwd string) string { mut dir := os.real_path(cwd) for { if os.exists(os.join_path(dir, '.git')) { return dir } parent := os.dir(dir) if parent == dir || parent == '' { return dir } dir = parent } return dir } fn (ctx VCheckIgnoreContext) skip_match(file_path string) ?VCheckIgnoreMatch { file := os.real_path(file_path).replace('\\', '/') mut dir := os.dir(file) repo_root := ctx.repo_root.replace('\\', '/') for { ignore_path := os.join_path(dir, '.vcheckignore') if os.is_file(ignore_path) { lines := os.read_lines(ignore_path) or { []string{} } for line in lines { pattern := normalize_vcheckignore_line(line) if pattern == '' || pattern.starts_with('#') { continue } if matches_vcheckignore_rule(file, VCheckIgnoreRule{ base_dir: dir pattern: pattern }) { return VCheckIgnoreMatch{ ignore_file: ignore_path pattern: pattern } } } } if dir.replace('\\', '/') == repo_root { break } parent := os.dir(dir) if parent == dir || parent == '' { break } dir = parent } return none } fn normalize_vcheckignore_line(line string) string { trimmed := line.trim_space() if trimmed == '' { return '' } if comment_idx := trimmed.index('#') { return trimmed[..comment_idx].trim_space() } return trimmed } fn (ctx VCheckIgnoreContext) repo_relative_path(file_path string) string { file := os.real_path(file_path).replace('\\', '/') root := ctx.repo_root.replace('\\', '/') root_prefix := root + '/' if file.starts_with(root_prefix) { return file.all_after(root_prefix) } return file } fn matches_vcheckignore_rule(file string, rule VCheckIgnoreRule) bool { base := rule.base_dir.replace('\\', '/') base_prefix := base + '/' if !file.starts_with(base_prefix) { return false } relative_file := file.all_after(base_prefix) mut pattern := rule.pattern.replace('\\', '/') if pattern.starts_with('!') { return false } mut anchored := false if pattern.starts_with('/') { anchored = true pattern = pattern.trim_left('/') } if pattern.ends_with('/') { pattern = pattern.trim_right('/') return matches_vcheckignore_directory_pattern(relative_file, pattern, anchored) } if anchored { return relative_file.match_glob(pattern) } if pattern.contains('/') { return relative_file.match_glob(pattern) } return os.file_name(relative_file).match_glob(pattern) } fn matches_vcheckignore_directory_pattern(relative_file string, pattern string, anchored bool) bool { mut relative_dir := os.dir(relative_file).replace('\\', '/') if relative_dir == '.' || relative_dir == '' { return false } if anchored { return relative_dir.match_glob(pattern) || relative_dir.match_glob(pattern + '/*') } mut candidate := relative_dir for { if candidate.match_glob(pattern) || candidate.match_glob(pattern + '/*') { return true } if slash_idx := candidate.index('/') { candidate = candidate[slash_idx + 1..] continue } break } return false } fn wprintln(s string) { if !hide_warnings { println(s) } } fn ftext(s string, cb fn (string) string) string { if term_colors { return cb(s) } return s } fn btext(s string) string { return ftext(s, term.bold) } fn mtext(s string) string { return ftext(s, term.magenta) } fn rtext(s string) string { return ftext(s, term.red) } fn wline(file_path string, lnumber int, column int, message string) string { return btext('${file_path}:${lnumber + 1}:${column + 1}:') + btext(mtext(' warn:')) + rtext(' ${message}') } fn eline(file_path string, lnumber int, column int, message string) string { return btext('${file_path}:${lnumber + 1}:${column + 1}:') + btext(rtext(' error: ${message}')) } const default_command = 'compile' struct VCodeExample { mut: text []string command string sline int eline int } enum MDFileParserState { markdown vexample codeblock } struct MDFile { path string skip_line_length_check bool mut: idx int nfiles int lines []string examples []VCodeExample current VCodeExample state MDFileParserState = .markdown oks int warnings int errors int // compilation errors + formatting errors ferrors int // purely formatting errors } fn (mut f MDFile) progress(message string) { if show_progress { clear_previous_line() println('${message} | File ${f.idx + 1:3}/${f.nfiles:-3}: ${f.path}') } } struct CheckResultContext { path string line_number int line string } fn (mut f MDFile) wcheck(actual int, limit int, ctx CheckResultContext, msg_template string) { if actual > limit { final := msg_template.replace('@', limit.str()) + ', actual: ' + actual.str() wprintln(wline(ctx.path, ctx.line_number, ctx.line.len, final)) wprintln(ctx.line) wprintln(ftext('-'.repeat(limit) + '^', term.gray)) f.warnings++ } } fn (mut f MDFile) echeck(actual int, limit int, ctx CheckResultContext, msg_template string) { if actual > limit { final := msg_template.replace('@', limit.str()) + ', actual: ' + actual.str() eprintln(eline(ctx.path, ctx.line_number, ctx.line.len, final)) eprintln(ctx.line) eprintln(ftext('-'.repeat(limit) + '^', term.gray)) f.errors++ } } fn (mut f MDFile) check() CheckResult { mut anchor_data := AnchorData{} for j, line in f.lines { // f.progress('line: ${j}') if !f.skip_line_length_check { ctx := CheckResultContext{f.path, j, line} if f.state == .vexample { f.wcheck(line.len, too_long_line_length_example, ctx, 'example lines must be less than @ characters') } else if f.state == .codeblock { f.wcheck(line.len, too_long_line_length_codeblock, ctx, 'code lines must be less than @ characters') } else if line.starts_with('|') { f.wcheck(line.len, too_long_line_length_table, ctx, 'table lines must be less than @ characters') } else if line.contains('http') { // vfmt off f.wcheck(line.all_after('https').len, too_long_line_length_link, ctx, 'link lines must be less than @ characters') // vfmt on } else { f.echeck(line.len, too_long_line_length_other, ctx, 'must be less than @ characters') } } if f.state == .markdown { anchor_data.add_links(j, line) anchor_data.add_link_targets(j, line) } f.parse_line(j, line) } f.check_link_target_match(anchor_data) f.check_examples() return CheckResult{ files: 1 lines: f.lines.len examples: f.examples.len oks: f.oks warnings: f.warnings errors: f.errors ferrors: f.ferrors } } fn (mut f MDFile) parse_line(lnumber int, line string) { if line.starts_with('```v') { if f.state == .markdown { f.state = .vexample mut command := line.replace('```v', '').trim_space() if command == '' { command = default_command } else if command == 'nofmt' { command += ' ${default_command}' } f.current = VCodeExample{ sline: lnumber command: command } } return } if line.starts_with('```') { match f.state { .vexample { f.state = .markdown f.current.eline = lnumber f.examples << f.current f.current = VCodeExample{} return } .codeblock { f.state = .markdown return } .markdown { f.state = .codeblock return } } } if f.state == .vexample { f.current.text << line } } struct Headline { line int label string level int } struct Anchor { line int } type AnchorTarget = Anchor | Headline struct AnchorLink { line int label string } struct AnchorData { mut: links map[string][]AnchorLink anchors map[string][]AnchorTarget } fn (mut ad AnchorData) add_links(line_number int, line string) { query := r'\[(?P