diff options
| -rw-r--r-- | mesonbuild/cargo/cfg.py | 74 | ||||
| -rw-r--r-- | unittests/cargotests.py | 69 |
2 files changed, 36 insertions, 107 deletions
diff --git a/mesonbuild/cargo/cfg.py b/mesonbuild/cargo/cfg.py index 3586a2a54..a0ee6e2b7 100644 --- a/mesonbuild/cargo/cfg.py +++ b/mesonbuild/cargo/cfg.py @@ -23,12 +23,9 @@ so you could have examples like: from __future__ import annotations import dataclasses import enum -import functools import typing as T -from . import builder -from .. import mparser from ..mesonlib import MesonBugException if T.TYPE_CHECKING: @@ -144,8 +141,8 @@ class Identifier(IR): @dataclasses.dataclass class Equal(IR): - lhs: IR - rhs: IR + lhs: Identifier + rhs: String @dataclasses.dataclass @@ -219,57 +216,20 @@ def parse(ast: _LEX_STREAM) -> IR: return _parse(ast_i) -@functools.singledispatch -def ir_to_meson(ir: T.Any, build: builder.Builder) -> mparser.BaseNode: - raise NotImplementedError - - -@ir_to_meson.register -def _(ir: String, build: builder.Builder) -> mparser.BaseNode: - return build.string(ir.value) - - -@ir_to_meson.register -def _(ir: Identifier, build: builder.Builder) -> mparser.BaseNode: - host_machine = build.identifier('host_machine') - if ir.value == "target_arch": - return build.method('cpu_family', host_machine) - elif ir.value in {"target_os", "target_family"}: - return build.method('system', host_machine) - elif ir.value == "target_endian": - return build.method('endian', host_machine) - raise MesonBugException(f"Unhandled Cargo identifier: {ir.value}") - - -@ir_to_meson.register -def _(ir: Equal, build: builder.Builder) -> mparser.BaseNode: - return build.equal(ir_to_meson(ir.lhs, build), ir_to_meson(ir.rhs, build)) - - -@ir_to_meson.register -def _(ir: Not, build: builder.Builder) -> mparser.BaseNode: - return build.not_(ir_to_meson(ir.value, build)) - - -@ir_to_meson.register -def _(ir: Any, build: builder.Builder) -> mparser.BaseNode: - if not ir.args: - return build.bool(False) - args = iter(reversed(ir.args)) - last = next(args) - cur = build.or_(ir_to_meson(next(args), build), ir_to_meson(last, build)) - for a in args: - cur = build.or_(ir_to_meson(a, build), cur) - return cur +def _eval_cfg(ir: IR, cfgs: T.Dict[str, str]) -> bool: + if isinstance(ir, Identifier): + return ir.value in cfgs + elif isinstance(ir, Equal): + return cfgs.get(ir.lhs.value) == ir.rhs.value + elif isinstance(ir, Not): + return not _eval_cfg(ir.value, cfgs) + elif isinstance(ir, Any): + return any(_eval_cfg(i, cfgs) for i in ir.args) + elif isinstance(ir, All): + return all(_eval_cfg(i, cfgs) for i in ir.args) + else: + raise MesonBugException(f'Unhandled Cargo cfg IR: {ir}') -@ir_to_meson.register -def _(ir: All, build: builder.Builder) -> mparser.BaseNode: - if not ir.args: - return build.bool(True) - args = iter(reversed(ir.args)) - last = next(args) - cur = build.and_(ir_to_meson(next(args), build), ir_to_meson(last, build)) - for a in args: - cur = build.and_(ir_to_meson(a, build), cur) - return cur +def eval_cfg(raw: str, cfgs: T.Dict[str, str]) -> bool: + return _eval_cfg(parse(lexer(raw)), cfgs) diff --git a/unittests/cargotests.py b/unittests/cargotests.py index 90b7f867f..eeb676bd2 100644 --- a/unittests/cargotests.py +++ b/unittests/cargotests.py @@ -151,60 +151,29 @@ class CargoCfgTest(unittest.TestCase): with self.subTest(): self.assertEqual(cfg.parse(iter(cfg.lexer(data))), expected) - def test_ir_to_meson(self) -> None: - build = builder.Builder('') - HOST_MACHINE = build.identifier('host_machine') - + def test_eval_ir(self) -> None: + d = { + 'target_os': 'unix', + 'unix': '', + } cases = [ - ('target_os = "windows"', - build.equal(build.method('system', HOST_MACHINE), - build.string('windows'))), - ('target_arch = "x86"', - build.equal(build.method('cpu_family', HOST_MACHINE), - build.string('x86'))), - ('target_family = "unix"', - build.equal(build.method('system', HOST_MACHINE), - build.string('unix'))), - ('not(target_arch = "x86")', - build.not_(build.equal( - build.method('cpu_family', HOST_MACHINE), - build.string('x86')))), - ('any(target_arch = "x86", target_arch = "x86_64")', - build.or_( - build.equal(build.method('cpu_family', HOST_MACHINE), - build.string('x86')), - build.equal(build.method('cpu_family', HOST_MACHINE), - build.string('x86_64')))), - ('any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")', - build.or_( - build.equal(build.method('cpu_family', HOST_MACHINE), - build.string('x86')), - build.or_( - build.equal(build.method('cpu_family', HOST_MACHINE), - build.string('x86_64')), - build.equal(build.method('cpu_family', HOST_MACHINE), - build.string('aarch64'))))), - ('all(target_arch = "x86", target_arch = "x86_64")', - build.and_( - build.equal(build.method('cpu_family', HOST_MACHINE), - build.string('x86')), - build.equal(build.method('cpu_family', HOST_MACHINE), - build.string('x86_64')))), - ('all(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")', - build.and_( - build.equal(build.method('cpu_family', HOST_MACHINE), - build.string('x86')), - build.and_( - build.equal(build.method('cpu_family', HOST_MACHINE), - build.string('x86_64')), - build.equal(build.method('cpu_family', HOST_MACHINE), - build.string('aarch64'))))), - ('all()', build.bool(True)), - ('any()', build.bool(False)), + ('target_os = "windows"', False), + ('target_os = "unix"', True), + ('doesnotexist = "unix"', False), + ('not(target_os = "windows")', True), + ('any(target_os = "windows", target_arch = "x86_64")', False), + ('any(target_os = "windows", target_os = "unix")', True), + ('all(target_os = "windows", target_os = "unix")', False), + ('all(not(target_os = "windows"), target_os = "unix")', True), + ('any(unix, windows)', True), + ('all()', True), + ('any()', False), + ('cfg(unix)', True), + ('cfg(windows)', False), ] for data, expected in cases: with self.subTest(): - value = cfg.ir_to_meson(cfg.parse(iter(cfg.lexer(data))), build) + value = cfg.eval_cfg(data, d) self.assertEqual(value, expected) class CargoLockTest(unittest.TestCase): |
