arxjit 1.24.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
arxjit-1.24.1/PKG-INFO ADDED
@@ -0,0 +1,67 @@
1
+ Metadata-Version: 2.4
2
+ Name: arxjit
3
+ Version: 1.24.1
4
+ Summary: ArxJIT is a developing Numba-style JIT frontend for the Arx compiler stack.
5
+ License-Expression: Apache-2.0
6
+ Author: Ivan Ogasawara
7
+ Author-email: ivan.ogasawara@gmail.com
8
+ Requires-Python: >=3.10,<4
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
15
+ Requires-Dist: astx (==1.24.1)
16
+ Requires-Dist: plum-dispatch (>=2)
17
+ Requires-Dist: pyirx (==1.24.1)
18
+ Description-Content-Type: text/markdown
19
+
20
+ # ArxJIT
21
+
22
+ ArxJIT is the planned Numba-style route from a restricted subset of pure Python
23
+ to ASTx, IRx, LLVM, and native callable code.
24
+
25
+ > **Important:** native JIT compilation is not implemented yet. A decorated
26
+ > function currently executes the original Python function.
27
+
28
+ ## Current API
29
+
30
+ ```python
31
+ from arxjit import i64, jit
32
+
33
+
34
+ @jit(signature=i64(i64, i64), cache=True)
35
+ def add(left, right):
36
+ return left + right
37
+
38
+
39
+ assert add(20, 22) == 42 # Python fallback today
40
+ ```
41
+
42
+ Implemented foundations:
43
+
44
+ - `@jit` and the `JitFunction` wrapper
45
+ - scalar signatures: `i32`, `i64`, `f32`, `f64`, and `bool_`
46
+ - robust function-source extraction with real-file locations
47
+ - validation for the proposed scalar Python subset
48
+ - structured diagnostics and public error types
49
+
50
+ The validator accepts typed scalar arguments, arithmetic/comparison/Boolean
51
+ expressions, single-target assignments, `if`/`else`, `while`, `for` over the
52
+ builtin `range`, and `return`. It rejects unsupported constructs with one
53
+ diagnostic per violation.
54
+
55
+ Not implemented:
56
+
57
+ - Python AST to ASTx lowering
58
+ - IRx compilation or native function calls
59
+ - runtime argument/result marshalling
60
+ - signature inference and artifact caching
61
+ - array, Tensor, or Apache Arrow signatures
62
+
63
+ See the [staged design](https://arxlang.org/arxjit/design.html) for the
64
+ Python-to-ASTx pipeline.
65
+
66
+ License: Apache-2.0.
67
+
@@ -0,0 +1,47 @@
1
+ # ArxJIT
2
+
3
+ ArxJIT is the planned Numba-style route from a restricted subset of pure Python
4
+ to ASTx, IRx, LLVM, and native callable code.
5
+
6
+ > **Important:** native JIT compilation is not implemented yet. A decorated
7
+ > function currently executes the original Python function.
8
+
9
+ ## Current API
10
+
11
+ ```python
12
+ from arxjit import i64, jit
13
+
14
+
15
+ @jit(signature=i64(i64, i64), cache=True)
16
+ def add(left, right):
17
+ return left + right
18
+
19
+
20
+ assert add(20, 22) == 42 # Python fallback today
21
+ ```
22
+
23
+ Implemented foundations:
24
+
25
+ - `@jit` and the `JitFunction` wrapper
26
+ - scalar signatures: `i32`, `i64`, `f32`, `f64`, and `bool_`
27
+ - robust function-source extraction with real-file locations
28
+ - validation for the proposed scalar Python subset
29
+ - structured diagnostics and public error types
30
+
31
+ The validator accepts typed scalar arguments, arithmetic/comparison/Boolean
32
+ expressions, single-target assignments, `if`/`else`, `while`, `for` over the
33
+ builtin `range`, and `return`. It rejects unsupported constructs with one
34
+ diagnostic per violation.
35
+
36
+ Not implemented:
37
+
38
+ - Python AST to ASTx lowering
39
+ - IRx compilation or native function calls
40
+ - runtime argument/result marshalling
41
+ - signature inference and artifact caching
42
+ - array, Tensor, or Apache Arrow signatures
43
+
44
+ See the [staged design](https://arxlang.org/arxjit/design.html) for the
45
+ Python-to-ASTx pipeline.
46
+
47
+ License: Apache-2.0.
@@ -0,0 +1,106 @@
1
+ [project]
2
+ name = "arxjit"
3
+ version = "1.24.1" # semantic-release
4
+ description = "ArxJIT is a developing Numba-style JIT frontend for the Arx compiler stack."
5
+ readme = "README.md"
6
+ authors = [
7
+ {name = "Ivan Ogasawara", email = "ivan.ogasawara@gmail.com"}
8
+ ]
9
+ license = "Apache-2.0"
10
+ requires-python = ">=3.10,<4"
11
+ dependencies = [
12
+ "astx == 1.24.1", # semantic-release
13
+ "pyirx == 1.24.1", # semantic-release
14
+ "plum-dispatch >= 2",
15
+ ]
16
+
17
+ [build-system]
18
+ requires = ["poetry-core>=2"]
19
+ build-backend = "poetry.core.masonry.api"
20
+
21
+ [tool.poetry]
22
+ exclude = [
23
+ ".git/*",
24
+ ".env*",
25
+ ]
26
+ packages = [
27
+ {include = "arxjit", from="src"},
28
+ ]
29
+ include = ["src/arxjit/py.typed"]
30
+
31
+ [tool.pytest.ini_options]
32
+ testpaths = [
33
+ "tests",
34
+ ]
35
+ filterwarnings = [
36
+ "error::RuntimeWarning",
37
+ ]
38
+
39
+ [tool.bandit]
40
+ exclude_dirs = ["tests"]
41
+ targets = "./"
42
+
43
+ [tool.vulture]
44
+ exclude = ["tests"]
45
+ ignore_decorators = ["abc.abstractmethod"]
46
+ ignore_names = []
47
+ make_whitelist = true
48
+ min_confidence = 80
49
+ paths = ["./"]
50
+ sort_by_size = true
51
+ verbose = false
52
+
53
+ [tool.ruff]
54
+ line-length = 79
55
+ force-exclude = true
56
+ src = ["./"]
57
+ target-version = "py310"
58
+ exclude = [
59
+ 'docs',
60
+ ]
61
+ fix = true
62
+
63
+ [tool.ruff.lint]
64
+ ignore = [
65
+ "F811", # redefined-while-unused
66
+ "PLR2004", # Magic value used in comparison
67
+ "PLR0911", # Too many return statements
68
+ "PLR0912", # Too many branches
69
+ "PLR0913", # Too many arguments in a function definition
70
+ "PLR0917", # Too many positional arguments
71
+ "RUF012", # mutable-class-default
72
+ "PLR0915", # Too many statements
73
+ ]
74
+ select = [
75
+ "E", # pycodestyle
76
+ "F", # pyflakes
77
+ "YTT", # flake8-2020
78
+ "PL", # PL
79
+ "RUF", # Ruff-specific rules
80
+ "I001", # isort
81
+ ]
82
+ extend-select = [
83
+ "UP006", # Prefer builtin generics in annotations
84
+ "UP007", # Prefer | syntax for unions and optionals
85
+ ]
86
+
87
+ [tool.ruff.lint.pydocstyle]
88
+ convention = "numpy"
89
+
90
+ [tool.ruff.lint.isort]
91
+ # Use a single line between direct and from import
92
+ lines-between-types = 1
93
+
94
+ [tool.ruff.format]
95
+ quote-style = "double"
96
+
97
+ [tool.mypy]
98
+ python_version = "3.10"
99
+ check_untyped_defs = true
100
+ strict = true
101
+ ignore_missing_imports = true
102
+ warn_unused_ignores = true
103
+ warn_redundant_casts = true
104
+ warn_unused_configs = true
105
+ show_error_codes = true
106
+ exclude = ["scripts/"]
@@ -0,0 +1,65 @@
1
+ """
2
+ title: Top-level package for arxjit.
3
+ """
4
+
5
+ from importlib import metadata as importlib_metadata
6
+
7
+ from arxjit.core import JitFunction, jit
8
+ from arxjit.diagnostics import Diagnostic, DiagnosticSeverity
9
+ from arxjit.errors import (
10
+ ArxJitError,
11
+ SourceExtractionError,
12
+ UnsupportedSyntaxError,
13
+ )
14
+ from arxjit.source import ExtractedSource, extract_source
15
+ from arxjit.types import (
16
+ Signature,
17
+ SigType,
18
+ bool_,
19
+ f32,
20
+ f64,
21
+ i32,
22
+ i64,
23
+ )
24
+ from arxjit.validation import validate
25
+
26
+ _DISTRIBUTION_NAME = "arxjit"
27
+
28
+
29
+ def get_version() -> str:
30
+ """
31
+ title: Return the program version.
32
+ returns:
33
+ type: str
34
+ """
35
+ try:
36
+ return importlib_metadata.version(_DISTRIBUTION_NAME)
37
+ except importlib_metadata.PackageNotFoundError: # pragma: no cover
38
+ return "1.24.1" # semantic-release
39
+
40
+
41
+ __author__: str = "Ivan Ogasawara"
42
+ __email__: str = "ivan.ogasawara@gmail.com"
43
+ __version__: str = get_version()
44
+
45
+ __all__ = [
46
+ "ArxJitError",
47
+ "Diagnostic",
48
+ "DiagnosticSeverity",
49
+ "ExtractedSource",
50
+ "JitFunction",
51
+ "SigType",
52
+ "Signature",
53
+ "SourceExtractionError",
54
+ "UnsupportedSyntaxError",
55
+ "__version__",
56
+ "bool_",
57
+ "extract_source",
58
+ "f32",
59
+ "f64",
60
+ "get_version",
61
+ "i32",
62
+ "i64",
63
+ "jit",
64
+ "validate",
65
+ ]
@@ -0,0 +1,108 @@
1
+ """
2
+ title: The @jit decorator, the public entry point of arxjit.
3
+ summary: >-
4
+ Wraps a pure Python function so it can be compiled through the Arx stack. In
5
+ this first version the wrapper records the requested signature and falls back
6
+ to running the original Python function; real compilation lands in later
7
+ sprints.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import functools
13
+
14
+ from typing import Any, Callable
15
+
16
+ from arxjit.types import Signature
17
+
18
+ PyFunc = Callable[..., Any]
19
+
20
+
21
+ class JitFunction:
22
+ """
23
+ title: A callable wrapper around a @jit-decorated function.
24
+ attributes:
25
+ py_func:
26
+ description: The original, undecorated Python function.
27
+ signature:
28
+ description: The explicit signature, or None when not given.
29
+ cache:
30
+ description: Whether compiled artifacts should be cached.
31
+ """
32
+
33
+ def __init__(
34
+ self,
35
+ py_func: PyFunc,
36
+ signature: Signature | None = None,
37
+ cache: bool = False,
38
+ ) -> None:
39
+ """
40
+ title: Wrap a Python function for just-in-time compilation.
41
+ parameters:
42
+ py_func:
43
+ type: PyFunc
44
+ description: The function being decorated.
45
+ signature:
46
+ type: Signature | None
47
+ description: The explicit call signature, if provided.
48
+ cache:
49
+ type: bool
50
+ description: Whether to cache compiled artifacts.
51
+ """
52
+ self.py_func = py_func
53
+ self.signature = signature
54
+ self.cache = cache
55
+ functools.update_wrapper(self, py_func)
56
+
57
+ def __call__(self, *args: Any, **kwargs: Any) -> Any:
58
+ """
59
+ title: Run the function (Python fallback until compilation lands).
60
+ parameters:
61
+ args:
62
+ type: Any
63
+ description: Positional arguments forwarded to the function.
64
+ variadic: positional
65
+ kwargs:
66
+ type: Any
67
+ description: Keyword arguments forwarded to the function.
68
+ variadic: keyword
69
+ returns:
70
+ type: Any
71
+ """
72
+ return self.py_func(*args, **kwargs)
73
+
74
+
75
+ def jit(
76
+ fn: PyFunc | None = None,
77
+ *,
78
+ signature: Signature | None = None,
79
+ cache: bool = False,
80
+ ) -> JitFunction | functools.partial[JitFunction]:
81
+ """
82
+ title: Compile a pure Python function through the Arx stack.
83
+ summary: >-
84
+ Usable bare as ``@jit`` or with options as ``@jit(signature=i64(i64,
85
+ i64), cache=True)``. Records the requested signature and returns a
86
+ callable wrapper. When called with options it returns a partial that
87
+ wraps the function next.
88
+ parameters:
89
+ fn:
90
+ type: PyFunc | None
91
+ description: The function to wrap, when used as a bare decorator.
92
+ signature:
93
+ type: Signature | None
94
+ description: The explicit call signature.
95
+ cache:
96
+ type: bool
97
+ description: Whether to cache compiled artifacts.
98
+ returns:
99
+ type: JitFunction | functools.partial[JitFunction]
100
+ """
101
+ if signature is not None and not isinstance(signature, Signature):
102
+ raise TypeError(
103
+ "jit(signature=...) must be a Signature, e.g. i64(i64, i64)"
104
+ )
105
+
106
+ if fn is not None:
107
+ return JitFunction(fn, signature=signature, cache=cache)
108
+ return functools.partial(JitFunction, signature=signature, cache=cache)
@@ -0,0 +1,88 @@
1
+ """
2
+ title: Structured diagnostic records for arxjit.
3
+ summary: >-
4
+ Define the frozen Diagnostic record and the DiagnosticSeverity enum that
5
+ arxjit uses to report problems found while extracting, validating, or
6
+ compiling a decorated Python function. Diagnostics point at the user's Python
7
+ source (the file and line of the decorated function), so messages stay
8
+ actionable without exposing compiler internals.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from dataclasses import dataclass
14
+ from enum import Enum
15
+
16
+
17
+ class DiagnosticSeverity(Enum):
18
+ """
19
+ title: Severity level of a diagnostic.
20
+ """
21
+
22
+ ERROR = "error"
23
+ WARNING = "warning"
24
+ INFO = "info"
25
+ HINT = "hint"
26
+
27
+
28
+ @dataclass(frozen=True)
29
+ class Diagnostic:
30
+ """
31
+ title: One structured diagnostic reported by arxjit.
32
+ attributes:
33
+ severity:
34
+ type: DiagnosticSeverity
35
+ description: The severity level of the diagnostic.
36
+ message:
37
+ type: str
38
+ description: The human-readable diagnostic message.
39
+ filename:
40
+ type: str
41
+ description: >-
42
+ The file defining the decorated function, or "<unknown>" when the
43
+ source cannot be attributed.
44
+ line:
45
+ type: int | None
46
+ description: One-based source line in ``filename``, when known.
47
+ column:
48
+ type: int | None
49
+ description: >-
50
+ One-based Unicode character column in ``line``, when known. Python
51
+ AST ``col_offset`` values (zero-based UTF-8 byte offsets) must be
52
+ converted to this representation at the boundary that produces the
53
+ diagnostic, never stored raw.
54
+ code:
55
+ type: str | None
56
+ description: Stable diagnostic code, e.g. "AJ001", when assigned.
57
+ """
58
+
59
+ severity: DiagnosticSeverity
60
+ message: str
61
+ filename: str
62
+ line: int | None
63
+ column: int | None
64
+ code: str | None = None
65
+
66
+ def __str__(self) -> str:
67
+ """
68
+ title: Render the diagnostic as one human-readable line.
69
+ summary: >-
70
+ Format is ``file:line:column: severity: [code] message``. Unknown
71
+ location parts are omitted (a column is only rendered when the line
72
+ is also known), and an unset or empty code renders no bracket prefix.
73
+ returns:
74
+ type: str
75
+ """
76
+ location = self.filename
77
+ if self.line is not None:
78
+ location = f"{location}:{self.line}"
79
+ if self.column is not None:
80
+ location = f"{location}:{self.column}"
81
+ prefix = f"[{self.code}] " if self.code else ""
82
+ return f"{location}: {self.severity.value}: {prefix}{self.message}"
83
+
84
+
85
+ __all__ = [
86
+ "Diagnostic",
87
+ "DiagnosticSeverity",
88
+ ]
@@ -0,0 +1,80 @@
1
+ """
2
+ title: Public exception hierarchy for arxjit.
3
+ summary: >-
4
+ Define the single error hierarchy arxjit raises to callers: ArxJitError as
5
+ the base, with SourceExtractionError for functions whose source cannot be
6
+ retrieved and parsed, and UnsupportedSyntaxError for functions using Python
7
+ constructs outside the supported subset. Each error carries a list of
8
+ structured Diagnostic records so callers can inspect failures
9
+ programmatically instead of scraping message text.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from collections.abc import Sequence
15
+
16
+ from arxjit.diagnostics import Diagnostic
17
+
18
+
19
+ class ArxJitError(Exception):
20
+ """
21
+ title: Base class for every error raised by arxjit.
22
+ attributes:
23
+ diagnostics:
24
+ type: list[Diagnostic]
25
+ description: Structured diagnostics describing the failure.
26
+ """
27
+
28
+ diagnostics: list[Diagnostic]
29
+
30
+ def __init__(
31
+ self,
32
+ message: str,
33
+ *,
34
+ diagnostics: Sequence[Diagnostic] | None = None,
35
+ ) -> None:
36
+ """
37
+ title: Initialize an ArxJitError.
38
+ parameters:
39
+ message:
40
+ type: str
41
+ diagnostics:
42
+ type: Sequence[Diagnostic] | None
43
+ """
44
+ self.diagnostics = list(diagnostics or ())
45
+ super().__init__(message)
46
+
47
+
48
+ class SourceExtractionError(ArxJitError):
49
+ """
50
+ title: Raised when a decorated function's source cannot be extracted.
51
+ summary: >-
52
+ Covers the whole extraction stage, functions whose source cannot be
53
+ retrieved or cannot be parsed as a standalone function definition, such
54
+ as ones defined in the REPL, built with exec, implemented in C, or
55
+ lambdas. Constructs rejected after successful extraction raise
56
+ UnsupportedSyntaxError instead.
57
+ attributes:
58
+ diagnostics:
59
+ type: list[Diagnostic]
60
+ """
61
+
62
+
63
+ class UnsupportedSyntaxError(ArxJitError):
64
+ """
65
+ title: Raised when a function uses Python outside the supported subset.
66
+ summary: >-
67
+ Carries one diagnostic per rejected construct, each pointing at the
68
+ offending source line, so a function with several unsupported constructs
69
+ reports all of them at once.
70
+ attributes:
71
+ diagnostics:
72
+ type: list[Diagnostic]
73
+ """
74
+
75
+
76
+ __all__ = [
77
+ "ArxJitError",
78
+ "SourceExtractionError",
79
+ "UnsupportedSyntaxError",
80
+ ]
File without changes