diff --git a/flipjump/__init__.py b/flipjump/__init__.py index 7c3ad574..b4f3ca19 100644 --- a/flipjump/__init__.py +++ b/flipjump/__init__.py @@ -18,6 +18,7 @@ from flipjump.fjm.fjm_consts import FJMVersion, FJ_MAGIC from flipjump.interpreter.fjm_run import TerminationStatistics, is_native_engine_active from flipjump.utils.classes import TerminationCause +from flipjump.utils.constants import FLIPJUMP_VERSION as __version__ from flipjump.utils.functions import get_stl_paths from flipjump.utils.exceptions import IODeviceException, FlipJumpException from flipjump.interpreter.io_devices.IODevice import IODevice @@ -26,6 +27,7 @@ from flipjump.interpreter.io_devices.BrokenIO import BrokenIO __all__ = [ + '__version__', 'assemble_run_according_to_cmd_line_args', 'assemble', 'run', diff --git a/flipjump/flipjump_cli.py b/flipjump/flipjump_cli.py index 9e4ba202..bbcfecad 100644 --- a/flipjump/flipjump_cli.py +++ b/flipjump/flipjump_cli.py @@ -16,7 +16,11 @@ from flipjump.fjm.fjm_consts import FJMVersion, SUPPORTED_VERSIONS_NAMES from flipjump.fjm.fjm_writer import Writer from flipjump.interpreter.io_devices.cli_devices import IO_MODES, make_io_device, split_io_mode -from flipjump.utils.constants import LAST_OPS_DEBUGGING_LIST_DEFAULT_LENGTH, DEFAULT_MAX_MACRO_RECURSION_DEPTH +from flipjump.utils.constants import ( + LAST_OPS_DEBUGGING_LIST_DEFAULT_LENGTH, + DEFAULT_MAX_MACRO_RECURSION_DEPTH, + FLIPJUMP_VERSION, +) from flipjump.utils.exceptions import IODeviceException from flipjump.utils.functions import get_file_tuples, get_temp_directory_suffix @@ -340,6 +344,13 @@ def add_universal_arguments(parser: argparse.ArgumentParser) -> None: @param parser: the parser """ parser.add_argument('files', help="the .fj files to assemble (if run-only, the .fjm file to run)", nargs='+') + parser.add_argument( + '-V', + '--flipjump_version', + action='version', + version=f'flipjump {FLIPJUMP_VERSION}', + help="show the installed flipjump version and exit", + ) parser.add_argument( '-s', '--silent', action='store_true', help="don't show assemble & run times, and run statistics" ) diff --git a/flipjump/stl/hex/README.md b/flipjump/stl/hex/README.md index 2e92c897..17b00f00 100644 --- a/flipjump/stl/hex/README.md +++ b/flipjump/stl/hex/README.md @@ -10,13 +10,14 @@ This folder is the table-driven counterpart to `bit/`. Where `bit/`-macros work | `memory.fj` | `hex`, `vec`, `zero`, `mov`, `xor_by`, `set`, `swap`. | | `logics.fj` | `xor`, `or`, `and`, `not`, plus `exact_*`, `double_xor`, `quadrupled_exact_xor`. | | `math.fj` | `add`, `sub`, `add_constant`, `add_shifted`, `add_hex_shifted_constant`, plus the `clear_carry` / `not_carry` / `set_carry` helpers for both `ns add` and `ns sub`. | -| `math_basic.fj` | `inc`, `dec`, `neg`, `inc1`, `dec1`, `step`, `add_count_bits`, `count_bits`, `sign_extend`. | +| `math_basic.fj` | `inc`, `dec`, `neg`, `abs`, `inc1`, `dec1`, `step`, `add_count_bits`, `count_bits`, `sign_extend`. | | `mul.fj` | `mul`, `mul10`, `add_mul`, plus the per-multiplication carry / init machinery. | | `div.fj` | `div` (unsigned) and `idiv` (signed, with configurable remainder convention). | | `shifts.fj` | `shl_hex`, `shr_hex`, plus the inline-table `shl_bit_once` / `shr_bit_once` helpers. | | `cond_jumps.fj` | `if`, `if0`, `if1`, `if_flags`, `sign`, `cmp` (3-way), `cmp_eq_next`, `min`/`max`, `cmp.init`. | -| `input.fj` | `input_hex`, `input` (1 hex / n hexes), `input_as_hex`, `input_dec_uint`/`input_dec_int`. | +| `input.fj` | `input_hex`, `input` (1 hex / n hexes), `input_as_hex`, `input_dec_uint`/`input_dec_int`, `input_dec_uint_until`/`input_dec_int_until`. | | `output.fj` | `output`, `print`, `print_as_digit`, `print_uint`, `print_int`, `print_digit`, `print_dec_uint`, `print_dec_int`. | +| `strings.fj` | `input_ptr_line`, `print_ptr_text`, `print_ptr_line` (packed-byte line/text I/O), plus `fill_bytes` / `copy_bytes` block helpers. | | `casting.fj` *(root)* | `bit2hex` / `hex2bit` — bridging the two namespaces. | | `pointers/` | The hex pointer subsystem (see below). | diff --git a/flipjump/utils/constants.py b/flipjump/utils/constants.py index 833cb9c9..505bd5d7 100644 --- a/flipjump/utils/constants.py +++ b/flipjump/utils/constants.py @@ -7,9 +7,15 @@ from __future__ import annotations import lzma +from importlib.metadata import version as _package_version, PackageNotFoundError from pathlib import Path from typing import List, Dict +try: + FLIPJUMP_VERSION = _package_version('flipjump') +except PackageNotFoundError: # running from a source tree without an installed distribution + FLIPJUMP_VERSION = 'unknown' + MACRO_SEPARATOR_STRING = "---" STARTING_LABEL_IN_MACROS_STRING = ':start:' WFLIP_LABEL_PREFIX = ':wflips:' diff --git a/tests/unit/test_cli.py b/tests/unit/test_cli.py index 1d6fbf6f..cf6dee6f 100644 --- a/tests/unit/test_cli.py +++ b/tests/unit/test_cli.py @@ -144,3 +144,14 @@ def test_cli_no_output_flag_is_gone(tmp_path: Path) -> None: fjm_path = assemble_to_path(HELLO_NO_STL.read_text(), tmp_path) with pytest.raises(SystemExit): assemble_run_according_to_cmd_line_args(cmd_line_args=['--run', '-s', '--no_output', str(fjm_path)]) + + +@pytest.mark.parametrize('flag', ['-V', '--flipjump_version']) +def test_cli_flipjump_version_flag(flag: str, capsys: pytest.CaptureFixture[str]) -> None: + # -V / --flipjump_version print the package version and exit 0, before the required `files` positional. + from flipjump import __version__ + + with pytest.raises(SystemExit) as exc_info: + parse_arguments(cmd_line_args=[flag]) + assert exc_info.value.code == 0 + assert capsys.readouterr().out.strip() == f'flipjump {__version__}'