decl-lang 0.3.0__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.
Files changed (41) hide show
  1. decl_lang-0.3.0/LICENSE +21 -0
  2. decl_lang-0.3.0/PKG-INFO +111 -0
  3. decl_lang-0.3.0/README.md +80 -0
  4. decl_lang-0.3.0/decl/__init__.py +255 -0
  5. decl_lang-0.3.0/decl/_tree_sitter/__init__.py +11 -0
  6. decl_lang-0.3.0/decl/_tree_sitter/_binding.pyi +3 -0
  7. decl_lang-0.3.0/decl/_tree_sitter/binding.c +26 -0
  8. decl_lang-0.3.0/decl/_tree_sitter/src/parser.c +35905 -0
  9. decl_lang-0.3.0/decl/_tree_sitter/src/scanner.c +58 -0
  10. decl_lang-0.3.0/decl/_tree_sitter/src/tree_sitter/alloc.h +54 -0
  11. decl_lang-0.3.0/decl/_tree_sitter/src/tree_sitter/array.h +336 -0
  12. decl_lang-0.3.0/decl/_tree_sitter/src/tree_sitter/parser.h +286 -0
  13. decl_lang-0.3.0/decl/cli.py +22 -0
  14. decl_lang-0.3.0/decl/runtime/__init__.py +0 -0
  15. decl_lang-0.3.0/decl/runtime/__main__.py +8 -0
  16. decl_lang-0.3.0/decl/runtime/checker.py +676 -0
  17. decl_lang-0.3.0/decl/runtime/cli.py +383 -0
  18. decl_lang-0.3.0/decl/runtime/conformance.py +76 -0
  19. decl_lang-0.3.0/decl/runtime/engine.py +1745 -0
  20. decl_lang-0.3.0/decl/runtime/fmt.py +332 -0
  21. decl_lang-0.3.0/decl/runtime/infer.py +1278 -0
  22. decl_lang-0.3.0/decl/runtime/lsp.py +3880 -0
  23. decl_lang-0.3.0/decl/runtime/module.py +235 -0
  24. decl_lang-0.3.0/decl/runtime/package.py +272 -0
  25. decl_lang-0.3.0/decl/runtime/parse.py +632 -0
  26. decl_lang-0.3.0/decl/runtime/pipeline.py +85 -0
  27. decl_lang-0.3.0/decl/runtime/repl.py +633 -0
  28. decl_lang-0.3.0/decl/runtime/semantics.py +1552 -0
  29. decl_lang-0.3.0/decl/runtime/session.py +1794 -0
  30. decl_lang-0.3.0/decl/runtime/subsume.py +264 -0
  31. decl_lang-0.3.0/decl_lang.egg-info/PKG-INFO +111 -0
  32. decl_lang-0.3.0/decl_lang.egg-info/SOURCES.txt +39 -0
  33. decl_lang-0.3.0/decl_lang.egg-info/dependency_links.txt +1 -0
  34. decl_lang-0.3.0/decl_lang.egg-info/entry_points.txt +3 -0
  35. decl_lang-0.3.0/decl_lang.egg-info/requires.txt +6 -0
  36. decl_lang-0.3.0/decl_lang.egg-info/top_level.txt +1 -0
  37. decl_lang-0.3.0/pyproject.toml +80 -0
  38. decl_lang-0.3.0/setup.cfg +4 -0
  39. decl_lang-0.3.0/setup.py +37 -0
  40. decl_lang-0.3.0/tests/test_api.py +76 -0
  41. decl_lang-0.3.0/tests/test_corpus.py +31 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 luuvish
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,111 @@
1
+ Metadata-Version: 2.4
2
+ Name: decl-lang
3
+ Version: 0.3.0
4
+ Summary: Decl — a declarative language for describing, generating, and validating structured data: the decl CLI (check / evaluate / validate / fmt), the decl-lsp language server, and a Python API, implemented natively
5
+ Author: luuvish
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/luuvish/decl-lang
8
+ Project-URL: Repository, https://github.com/luuvish/decl-lang
9
+ Project-URL: Issues, https://github.com/luuvish/decl-lang/issues
10
+ Keywords: decl,declarative,schema,validation,configuration,json,language,lsp
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Programming Language :: C
20
+ Classifier: Topic :: Software Development :: Compilers
21
+ Classifier: Topic :: Software Development :: Quality Assurance
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: tree-sitter>=0.25
26
+ Provides-Extra: dev
27
+ Requires-Dist: ruff; extra == "dev"
28
+ Requires-Dist: mypy; extra == "dev"
29
+ Requires-Dist: pytest; extra == "dev"
30
+ Dynamic: license-file
31
+
32
+ # decl
33
+
34
+ **Decl** is a declarative language for describing, generating, and
35
+ validating structured data — a JSON superset with a strong static type
36
+ system, constraints with first-class diagnostics, references, physical
37
+ quantities, generics, and modules. Pure, deterministic, terminating.
38
+
39
+ This package is a **native Python implementation** of the whole
40
+ language — the tree-sitter grammar compiled as a C extension plus a
41
+ pure-Python port of the static checker, the evaluator, packages, the
42
+ canonical formatter, and the language server, byte-identical to the
43
+ reference implementation. It ships the `decl` command-line tool, the
44
+ `decl-lsp` language server, and a small Python API. No Node.js is
45
+ involved.
46
+
47
+ ```bash
48
+ pip install decl-lang # installs as decl-lang, imports as `decl` — the command's name and the module path (decl.runtime)
49
+ ```
50
+
51
+ ## Command line
52
+
53
+ ```bash
54
+ decl check schema.decl # parse + static checks (module-aware)
55
+ decl evaluate site.decl # the exported outputs -> JSON on stdout
56
+ decl evaluate site.decl --output site=site.json --output report # one document to a file, one to stdout
57
+ decl evaluate cfg.decl --input deployed=doc.json --output deployed # bind a document, emit its completed value
58
+ decl validate cfg.decl --input deployed=doc.json --expect-errors E4001
59
+ decl validate tests/validation # judge a fixture corpus
60
+ decl fmt --check src/*.decl # canonical formatting
61
+ decl repl site.decl # an interactive session: expressions, bindings, edits, undo
62
+ decl-lsp # stdio language server for editors
63
+ ```
64
+
65
+ ## Python API
66
+
67
+ ```python
68
+ import decl
69
+
70
+ docs = decl.evaluate("site.decl") # {"site": {...}} — the exported outputs, by name
71
+ site = decl.evaluate("site.decl", outputs=["site"])["site"]
72
+ done = decl.evaluate("cfg.decl", inputs={"deployed": "doc.json"}, outputs=["deployed"])["deployed"]
73
+ problems = decl.check("schema.decl") # [] when clean
74
+ report = decl.validate(
75
+ "cfg.decl", inputs={"deployed": {"host": "h"}}
76
+ ) # a document may be a value, not a file
77
+ text = decl.format_source("const x=1+2\n") # 'const x = 1 + 2\n'
78
+ ```
79
+
80
+ The functions are the `decl` command line in its own vocabulary:
81
+ `inputs` binds documents by input name (a JSON file path, or the value
82
+ itself), `outputs` names the roots to return — outputs, or inputs bound
83
+ here or demanded through their fallback — and defaults to the entry
84
+ module's exported outputs. The npm package (`evaluate`, `check`,
85
+ `validate`, `formatSource`) and the Rust crate (`decl_lang::evaluate`, …)
86
+ offer the same functions with the same semantics.
87
+
88
+ Every call runs the same implementation as the CLI and returns its
89
+ machine-readable report; `decl.DeclError.diagnostics` carries the
90
+ diagnostics (`file`, `severity`, `code`, `id`, `path`, `message`) when
91
+ an operation fails.
92
+
93
+ ## A taste of the language
94
+
95
+ ```decl
96
+ type Service = {
97
+ name: /[a-z][a-z0-9-]*/
98
+ port?: 1024..65535 = 8080
99
+ replicas?: 1..64 = 1
100
+ endpoint = `${name}:${port}`
101
+ assert grpc_ports: name != "grpc" || port >= 9000
102
+ else warn `grpc convention is 9000+`
103
+ }
104
+
105
+ export output demo: Service[] = [
106
+ { name: "gateway" }
107
+ { name: "auth", port: 9001, replicas: 2 }
108
+ ]
109
+ ```
110
+
111
+ Specification, guide, and sources: https://github.com/luuvish/decl-lang
@@ -0,0 +1,80 @@
1
+ # decl
2
+
3
+ **Decl** is a declarative language for describing, generating, and
4
+ validating structured data — a JSON superset with a strong static type
5
+ system, constraints with first-class diagnostics, references, physical
6
+ quantities, generics, and modules. Pure, deterministic, terminating.
7
+
8
+ This package is a **native Python implementation** of the whole
9
+ language — the tree-sitter grammar compiled as a C extension plus a
10
+ pure-Python port of the static checker, the evaluator, packages, the
11
+ canonical formatter, and the language server, byte-identical to the
12
+ reference implementation. It ships the `decl` command-line tool, the
13
+ `decl-lsp` language server, and a small Python API. No Node.js is
14
+ involved.
15
+
16
+ ```bash
17
+ pip install decl-lang # installs as decl-lang, imports as `decl` — the command's name and the module path (decl.runtime)
18
+ ```
19
+
20
+ ## Command line
21
+
22
+ ```bash
23
+ decl check schema.decl # parse + static checks (module-aware)
24
+ decl evaluate site.decl # the exported outputs -> JSON on stdout
25
+ decl evaluate site.decl --output site=site.json --output report # one document to a file, one to stdout
26
+ decl evaluate cfg.decl --input deployed=doc.json --output deployed # bind a document, emit its completed value
27
+ decl validate cfg.decl --input deployed=doc.json --expect-errors E4001
28
+ decl validate tests/validation # judge a fixture corpus
29
+ decl fmt --check src/*.decl # canonical formatting
30
+ decl repl site.decl # an interactive session: expressions, bindings, edits, undo
31
+ decl-lsp # stdio language server for editors
32
+ ```
33
+
34
+ ## Python API
35
+
36
+ ```python
37
+ import decl
38
+
39
+ docs = decl.evaluate("site.decl") # {"site": {...}} — the exported outputs, by name
40
+ site = decl.evaluate("site.decl", outputs=["site"])["site"]
41
+ done = decl.evaluate("cfg.decl", inputs={"deployed": "doc.json"}, outputs=["deployed"])["deployed"]
42
+ problems = decl.check("schema.decl") # [] when clean
43
+ report = decl.validate(
44
+ "cfg.decl", inputs={"deployed": {"host": "h"}}
45
+ ) # a document may be a value, not a file
46
+ text = decl.format_source("const x=1+2\n") # 'const x = 1 + 2\n'
47
+ ```
48
+
49
+ The functions are the `decl` command line in its own vocabulary:
50
+ `inputs` binds documents by input name (a JSON file path, or the value
51
+ itself), `outputs` names the roots to return — outputs, or inputs bound
52
+ here or demanded through their fallback — and defaults to the entry
53
+ module's exported outputs. The npm package (`evaluate`, `check`,
54
+ `validate`, `formatSource`) and the Rust crate (`decl_lang::evaluate`, …)
55
+ offer the same functions with the same semantics.
56
+
57
+ Every call runs the same implementation as the CLI and returns its
58
+ machine-readable report; `decl.DeclError.diagnostics` carries the
59
+ diagnostics (`file`, `severity`, `code`, `id`, `path`, `message`) when
60
+ an operation fails.
61
+
62
+ ## A taste of the language
63
+
64
+ ```decl
65
+ type Service = {
66
+ name: /[a-z][a-z0-9-]*/
67
+ port?: 1024..65535 = 8080
68
+ replicas?: 1..64 = 1
69
+ endpoint = `${name}:${port}`
70
+ assert grpc_ports: name != "grpc" || port >= 9000
71
+ else warn `grpc convention is 9000+`
72
+ }
73
+
74
+ export output demo: Service[] = [
75
+ { name: "gateway" }
76
+ { name: "auth", port: 9001, replicas: 2 }
77
+ ]
78
+ ```
79
+
80
+ Specification, guide, and sources: https://github.com/luuvish/decl-lang
@@ -0,0 +1,255 @@
1
+ """Python API for the Decl language.
2
+
3
+ Every operation runs the native Python implementation (``decl.runtime``),
4
+ held byte-identical to the reference implementation by
5
+ tests/parity/differential.py. The functions mirror the ``decl`` command
6
+ line, in its vocabulary: ``evaluate`` binds inputs and returns outputs.
7
+
8
+ >>> import decl
9
+ >>> decl.evaluate("site.decl") # {"site": {...}} — the exported outputs
10
+ >>> decl.evaluate("cfg.decl", inputs={"deployed": "doc.json"}, outputs=["deployed"])["deployed"]
11
+ >>> decl.check("schema.decl") # [] when clean, else diagnostics
12
+ >>> decl.validate("cfg.decl", inputs={"deployed": {"host": "h"}})
13
+ ... # a document may be a value, not a file
14
+ >>> decl.format_source("const x=1+2\\n") # 'const x = 1 + 2\\n'
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import json
20
+ import os
21
+ from collections.abc import Iterable, Mapping, Sequence
22
+ from typing import Any, TypedDict, cast
23
+
24
+ __all__ = [
25
+ "DeclError",
26
+ "Diagnostic",
27
+ "check",
28
+ "evaluate",
29
+ "evaluate_source",
30
+ "format_file",
31
+ "format_source",
32
+ "validate",
33
+ ]
34
+ __version__ = "0.3.0"
35
+
36
+
37
+ class Diagnostic(TypedDict, total=False):
38
+ """One diagnostic, in the report's field order (§12.2)."""
39
+
40
+ file: str
41
+ code: str
42
+ id: str
43
+ severity: str
44
+ message: str
45
+ path: str
46
+
47
+
48
+ class DeclError(Exception):
49
+ """Raised when an operation fails; ``diagnostics`` carries the report
50
+ (empty for a usage error such as an unknown input or root)."""
51
+
52
+ def __init__(self, message: str, diagnostics: Sequence[Diagnostic] = ()):
53
+ super().__init__(message)
54
+ self.diagnostics: list[Diagnostic] = list(diagnostics)
55
+
56
+
57
+ # a document to bind to an input: the path of a JSON file, or the value itself
58
+ InputDocument = "str | os.PathLike[str] | Any"
59
+ Inputs = "Mapping[str, InputDocument] | Iterable[tuple[str, InputDocument]]"
60
+
61
+
62
+ def _tagged(file: str, d: dict[str, Any]) -> Diagnostic:
63
+ o: dict[str, Any] = {"file": file}
64
+ if d.get("code"):
65
+ o["code"] = d["code"]
66
+ if d.get("id"):
67
+ o["id"] = d["id"]
68
+ o["severity"] = d["severity"]
69
+ o["message"] = d["message"]
70
+ o["path"] = d.get("path", "")
71
+ return cast(Diagnostic, o)
72
+
73
+
74
+ def _fail(fallback: str, diagnostics: list[Any]) -> None:
75
+ raise DeclError(diagnostics[0]["message"] if diagnostics else fallback, diagnostics)
76
+
77
+
78
+ def _file_tag(given: str, entry: Any, module_path: str) -> str:
79
+ return given if entry is not None and module_path == entry.path else module_path
80
+
81
+
82
+ def _pairs(inputs: Any) -> list[Any]:
83
+ if inputs is None:
84
+ return []
85
+ return list(inputs.items()) if isinstance(inputs, Mapping) else list(inputs)
86
+
87
+
88
+ def _bind_inputs(modules: list[Any], file: str, inputs: Any) -> list[Any]:
89
+ """The documents to bind, each to the module that declares its input (§10)."""
90
+ from .runtime.semantics import read_json
91
+
92
+ binds = []
93
+ for name, doc in _pairs(inputs):
94
+ module = next((m for m in modules if name in m.env.inputs), None)
95
+ if module is None:
96
+ raise DeclError(f"no input named {name}")
97
+ if isinstance(doc, (str, os.PathLike)):
98
+ try:
99
+ with open(doc, encoding="utf-8") as fh:
100
+ text = fh.read()
101
+ except OSError:
102
+ _fail(
103
+ "",
104
+ [
105
+ {
106
+ "file": file,
107
+ "code": "E6004",
108
+ "severity": "error",
109
+ "message": f"bound document cannot be read: {doc}",
110
+ "path": name,
111
+ }
112
+ ],
113
+ )
114
+ where = str(doc)
115
+ else:
116
+ text, where = json.dumps(doc), name
117
+ try:
118
+ raw = read_json(text)
119
+ except Exception:
120
+ _fail(
121
+ "",
122
+ [
123
+ {
124
+ "file": file,
125
+ "code": "E6004",
126
+ "severity": "error",
127
+ "message": f"bound document is not well-formed JSON: {where}",
128
+ "path": name,
129
+ }
130
+ ],
131
+ )
132
+ binds.append({"module": module, "input": name, "raw": raw})
133
+ return binds
134
+
135
+
136
+ def evaluate(
137
+ path: str | os.PathLike[str],
138
+ *,
139
+ inputs: Mapping[str, Any] | Iterable[tuple[str, Any]] | None = None,
140
+ outputs: Iterable[str] | None = None,
141
+ ) -> dict[str, Any]:
142
+ """Evaluate a module on the native runtime: bind the ``inputs`` documents
143
+ (by input name; a JSON file path, or the value itself), run the pipeline,
144
+ and return the requested roots' documents by name — ``outputs`` may name
145
+ outputs and inputs (bound here, or demanded through their fallback);
146
+ by default the entry module's exported outputs (§5.5). Raises DeclError
147
+ with the diagnostics on any error-severity outcome."""
148
+ from .runtime.checker import check_module
149
+ from .runtime.cli import open_universe
150
+ from .runtime.module import run_universe
151
+
152
+ file = str(path)
153
+ r = open_universe(file)
154
+ if r["diags"] or r["entry"] is None:
155
+ _fail(f"{file}: cannot be loaded", [_tagged(file, d) for d in r["diags"]])
156
+ entry = r["entry"]
157
+ checks = [
158
+ _tagged(_file_tag(file, entry, m.path), d)
159
+ for m in r["modules"]
160
+ for d in check_module(m.decls, m.env)
161
+ ]
162
+ if checks:
163
+ _fail("", checks)
164
+ u = run_universe(r["modules"], entry, _bind_inputs(r["modules"], file, inputs))
165
+ report = [_tagged(file, d) for d in u["diags"]]
166
+ if any(d["severity"] == "error" for d in report):
167
+ _fail("", report)
168
+ names = (
169
+ list(outputs)
170
+ if outputs is not None
171
+ else [o["name"] for o in entry.env.outputs if o.get("exported")]
172
+ )
173
+ out: dict[str, Any] = {}
174
+ for n in names:
175
+ if n not in entry.env.roots:
176
+ raise DeclError(f"no root named {n}", report)
177
+ out[n] = json.loads(u["eng"].serialize(entry.env.roots[n], n))
178
+ return out
179
+
180
+
181
+ def check(*paths: str | os.PathLike[str]) -> list[Diagnostic]:
182
+ """Parse and statically check entry files (module-aware) on the native
183
+ runtime. Returns diagnostics; empty means clean."""
184
+ from .runtime.cli import check_files
185
+
186
+ return [_tagged(d["file"], d) for d in check_files([str(p) for p in paths])]
187
+
188
+
189
+ def validate(
190
+ path: str | os.PathLike[str],
191
+ *,
192
+ inputs: Mapping[str, Any] | Iterable[tuple[str, Any]] | None = None,
193
+ expect_errors: Iterable[str] | None = None,
194
+ ) -> list[Diagnostic]:
195
+ """Validate a file: static checks, then evaluation with the ``inputs``
196
+ documents bound; returns every diagnostic (all severities). Raises
197
+ DeclError when the file does not parse. With ``expect_errors`` the set
198
+ of error codes must match exactly; DeclError carries the mismatch."""
199
+ from .runtime.checker import check_module
200
+ from .runtime.cli import open_universe
201
+ from .runtime.module import run_universe
202
+ from .runtime.parse import parse_source
203
+ from .runtime.pipeline import run_pipeline
204
+
205
+ file = str(path)
206
+ with open(file, encoding="utf-8") as fh:
207
+ src = fh.read()
208
+ parsed = parse_source(src)
209
+ if parsed["errors"]:
210
+ raise DeclError(f"{file}: {len(parsed['errors'])} parse error(s)")
211
+ decls = parsed["decls"]
212
+ diags = [_tagged(file, d) for d in check_module(decls)]
213
+ if not diags:
214
+ if _pairs(inputs):
215
+ r = open_universe(file)
216
+ u = run_universe(r["modules"], r["entry"], _bind_inputs(r["modules"], file, inputs))
217
+ diags = [_tagged(file, d) for d in u["diags"]]
218
+ else:
219
+ diags = [_tagged(file, d) for d in run_pipeline(decls)["diags"]]
220
+ if expect_errors is not None:
221
+ want = sorted(expect_errors)
222
+ got = sorted(d.get("code") or "" for d in diags if d["severity"] == "error")
223
+ if set(want) != set(got):
224
+ raise DeclError(f"expected errors {want}, got {got}", diags)
225
+ return diags
226
+
227
+
228
+ def evaluate_source(text: str) -> dict[str, Any]:
229
+ """Parse, check, and evaluate one module given as source text; returns
230
+ the report dict (phase, ok, parse_errors, checks, diagnostics, outputs, inputs)."""
231
+ from .runtime.pipeline import evaluate_source as run
232
+
233
+ return run(text)
234
+
235
+
236
+ def format_file(path: str | os.PathLike[str], *, check: bool = False) -> bool:
237
+ """Canonically format a file in place. Returns True if it was (or would be) changed."""
238
+ with open(path, encoding="utf-8") as f:
239
+ src = f.read()
240
+ out = format_source(src)
241
+ if out != src and not check:
242
+ with open(path, "w", encoding="utf-8") as f:
243
+ f.write(out)
244
+ return out != src
245
+
246
+
247
+ def format_source(text: str) -> str:
248
+ """Return the canonical formatting of a Decl source string; raises
249
+ DeclError when it does not parse."""
250
+ from .runtime.fmt import format_source as fmt
251
+
252
+ try:
253
+ return fmt(text)
254
+ except ValueError as e:
255
+ raise DeclError(str(e)) from None
@@ -0,0 +1,11 @@
1
+ """The Decl grammar as a `tree_sitter.Language` (compiled C extension)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from tree_sitter import Language
6
+
7
+ from ._binding import language as _language_ptr
8
+
9
+ LANGUAGE = Language(_language_ptr())
10
+
11
+ __all__ = ["LANGUAGE"]
@@ -0,0 +1,3 @@
1
+ """The C extension (binding.c): the grammar as a capsule the `tree_sitter` package accepts."""
2
+
3
+ def language() -> object: ...
@@ -0,0 +1,26 @@
1
+ /* Python binding for the Decl tree-sitter grammar: exposes the language
2
+ * as a PyCapsule the `tree_sitter` package accepts. The grammar sources
3
+ * (parser.c, scanner.c) are synced from ../../tree-sitter-decl/src. */
4
+ #include <Python.h>
5
+
6
+ typedef struct TSLanguage TSLanguage;
7
+ TSLanguage *tree_sitter_decl(void);
8
+
9
+ static PyObject *binding_language(PyObject *self, PyObject *args) {
10
+ (void)self; (void)args;
11
+ return PyCapsule_New(tree_sitter_decl(), "tree_sitter.Language", NULL);
12
+ }
13
+
14
+ static PyMethodDef methods[] = {
15
+ {"language", binding_language, METH_NOARGS, "Get the tree-sitter language for Decl."},
16
+ {NULL, NULL, 0, NULL}
17
+ };
18
+
19
+ static struct PyModuleDef module = {
20
+ PyModuleDef_HEAD_INIT, "_binding", "Decl tree-sitter grammar", -1, methods,
21
+ NULL, NULL, NULL, NULL
22
+ };
23
+
24
+ PyMODINIT_FUNC PyInit__binding(void) {
25
+ return PyModule_Create(&module);
26
+ }