@gram-data/tree-sitter-gram 0.3.5 → 0.3.6
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.
- package/editors/zed/Cargo.toml +20 -0
- package/editors/zed/README.md +23 -5
- package/editors/zed/build.rs +26 -0
- package/editors/zed/extension.toml +7 -2
- package/editors/zed/languages/gram/config.toml +2 -2
- package/editors/zed/src/lib.rs +156 -0
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/@gram-data+tree-sitter-gram.node +0 -0
- package/prebuilds/darwin-x64/@gram-data+tree-sitter-gram.node +0 -0
- package/prebuilds/linux-arm64/@gram-data+tree-sitter-gram.node +0 -0
- package/prebuilds/linux-x64/@gram-data+tree-sitter-gram.node +0 -0
- package/prebuilds/win32-arm64/@gram-data+tree-sitter-gram.node +0 -0
- package/prebuilds/win32-x64/@gram-data+tree-sitter-gram.node +0 -0
- package/src/parser.c +2 -2
- package/src/tree_sitter/array.h +68 -124
- package/tree-sitter-gram.wasm +0 -0
- package/tree-sitter.json +1 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "gram_zed_extension"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
license = "MIT"
|
|
6
|
+
publish = false
|
|
7
|
+
repository = "https://github.com/gram-data/tree-sitter-gram"
|
|
8
|
+
build = "build.rs"
|
|
9
|
+
|
|
10
|
+
[lib]
|
|
11
|
+
path = "src/lib.rs"
|
|
12
|
+
crate-type = ["cdylib"]
|
|
13
|
+
|
|
14
|
+
[dependencies]
|
|
15
|
+
zed_extension_api = "0.7"
|
|
16
|
+
|
|
17
|
+
# Standalone workspace root so this crate is not treated as a stray member of the
|
|
18
|
+
# repository workspace (see root `Cargo.toml` `[workspace]`).
|
|
19
|
+
[workspace]
|
|
20
|
+
members = ["."]
|
package/editors/zed/README.md
CHANGED
|
@@ -5,6 +5,7 @@ A [Zed](https://zed.dev) extension providing syntax highlighting and language su
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- **Syntax Highlighting**: Full syntax highlighting for all Gram constructs including subjects, nodes, relationships, and data types
|
|
8
|
+
- **Language server**: When [`gram-lsp`](../../tools/lsp/) is on your `PATH`, Zed starts it for `.gram` files (diagnostics, hover, definitions, references, completions)
|
|
8
9
|
- **Subject Pattern Matching**: Automatic matching for `()`, `[]`, and `{}`
|
|
9
10
|
- **File Type Detection**: Automatic recognition of `.gram` files
|
|
10
11
|
- **Smart Indentation**: Proper indentation handling for nested structures
|
|
@@ -40,7 +41,7 @@ Then restart Zed.
|
|
|
40
41
|
|
|
41
42
|
## Usage
|
|
42
43
|
|
|
43
|
-
Once installed, the extension
|
|
44
|
+
Once installed, the extension provides syntax highlighting for `.gram` files. With `gram-lsp` installed and on `PATH`, Zed also attaches the language server automatically.
|
|
44
45
|
|
|
45
46
|
### Example Gram Syntax
|
|
46
47
|
|
|
@@ -108,14 +109,25 @@ To work on this extension:
|
|
|
108
109
|
- Select the `editors/zed` directory
|
|
109
110
|
- Restart Zed
|
|
110
111
|
|
|
111
|
-
3.
|
|
112
|
-
|
|
112
|
+
3. Build the Wasm extension once after Rust changes (Zed loads the cdylib):
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
rustup target add wasm32-wasip1
|
|
116
|
+
cd editors/zed && cargo check --target wasm32-wasip1
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
4. Make changes to the extension files
|
|
120
|
+
5. Restart Zed to see changes
|
|
113
121
|
|
|
114
122
|
### Extension Structure
|
|
115
123
|
|
|
116
124
|
```
|
|
117
125
|
editors/zed/
|
|
118
|
-
├──
|
|
126
|
+
├── Cargo.toml # Wasm extension crate (zed_extension_api)
|
|
127
|
+
├── build.rs # Embeds `extension.toml` version for release asset lookup
|
|
128
|
+
├── Cargo.lock
|
|
129
|
+
├── src/lib.rs # `language_server_command`: PATH, then GitHub release download
|
|
130
|
+
├── extension.toml # Extension metadata; grammar repo + `[language_servers.gram-lsp]`
|
|
119
131
|
├── languages/
|
|
120
132
|
│ └── gram/
|
|
121
133
|
│ ├── config.toml # Zed language config (brackets, suffixes, etc.)
|
|
@@ -144,6 +156,12 @@ After either command, `extension.toml` is updated in place. For local dev you ty
|
|
|
144
156
|
|
|
145
157
|
**If Zed shows an old version (e.g. 0.1.11) after installing the dev extension:** Zed may be using a cached clone of the grammar (at an old rev) or an older copy of the extension. Try: (1) Uninstall the Gram extension from Zed’s Extensions panel. (2) Delete the grammar cache: remove `editors/zed/grammars/` if it exists (Zed recreates it when needed). (3) Run `npm run zed:dev` again so `extension.toml` has the current version and rev. (4) In Zed, run “Install Dev Extension” and select `editors/zed` again. Restart Zed and recheck the extension version.
|
|
146
158
|
|
|
159
|
+
### Bundled `gram-lsp` (GitHub Releases)
|
|
160
|
+
|
|
161
|
+
Zed extensions ship a **Wasm** adapter only; native `gram-lsp` binaries cannot be embedded in that bundle. Instead, when `gram-lsp` is **not** on `PATH`, the extension downloads a platform archive from **this repo’s GitHub Release** whose tag is **`v` + `version` from `extension.toml`** (for example `v0.3.5` for `version = "0.3.5"`).
|
|
162
|
+
|
|
163
|
+
Maintainers: pushing a **`v*`** tag runs **`.github/workflows/gram-lsp-release-assets.yml`**, which builds `gram-lsp` for common targets and uploads `gram-lsp-{target}.tar.gz` to the matching GitHub Release. Filenames must stay in sync with `editors/zed/src/lib.rs`. Keep `extension.toml`’s `version` aligned with the tag you ship to the Zed extension registry (for example tag `v0.3.5` and `version = "0.3.5"`) so installs download the intended binaries.
|
|
164
|
+
|
|
147
165
|
## Contributing
|
|
148
166
|
|
|
149
167
|
Contributions are welcome! Please see the main [repository](https://github.com/gram-data/tree-sitter-gram) for contribution guidelines.
|
|
@@ -156,7 +174,7 @@ To improve syntax highlighting and editor behavior:
|
|
|
156
174
|
|
|
157
175
|
## License
|
|
158
176
|
|
|
159
|
-
This extension is part of the tree-sitter-gram project and is licensed under the
|
|
177
|
+
This extension is part of the tree-sitter-gram project and is licensed under the MIT License. See the main repository's [LICENSE](../../LICENSE) file for details.
|
|
160
178
|
|
|
161
179
|
## Learn More
|
|
162
180
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//! Expose `extension.toml`'s `version = "…"` as `env!("GRAM_EXT_VERSION")` for release lookups.
|
|
2
|
+
|
|
3
|
+
use std::env;
|
|
4
|
+
use std::fs;
|
|
5
|
+
use std::path::PathBuf;
|
|
6
|
+
|
|
7
|
+
fn main() {
|
|
8
|
+
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR"));
|
|
9
|
+
let ext_toml = manifest_dir.join("extension.toml");
|
|
10
|
+
println!("cargo:rerun-if-changed={}", ext_toml.display());
|
|
11
|
+
|
|
12
|
+
let content = fs::read_to_string(&ext_toml).unwrap_or_else(|e| panic!("read {}: {e}", ext_toml.display()));
|
|
13
|
+
let version = parse_version(&content)
|
|
14
|
+
.unwrap_or_else(|| panic!("{}: missing `version = \"…\"` line", ext_toml.display()));
|
|
15
|
+
println!("cargo:rustc-env=GRAM_EXT_VERSION={version}");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
fn parse_version(toml: &str) -> Option<String> {
|
|
19
|
+
for line in toml.lines() {
|
|
20
|
+
let line = line.trim();
|
|
21
|
+
if let Some(rest) = line.strip_prefix("version = \"") {
|
|
22
|
+
return rest.split('"').next().map(str::to_string);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
None
|
|
26
|
+
}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
id = "gram"
|
|
2
2
|
name = "Gram Language Support"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.6"
|
|
4
4
|
schema_version = 1
|
|
5
5
|
authors = ["Gram Data Contributors"]
|
|
6
6
|
description = "Support for Gram notation - composable data patterns"
|
|
7
7
|
|
|
8
|
+
capabilities = [
|
|
9
|
+
{ kind = "process:exec", command = "*", args = ["stdio"] },
|
|
10
|
+
{ kind = "download_file", host = "github.com", path = ["gram-data", "tree-sitter-gram", "**"] },
|
|
11
|
+
]
|
|
12
|
+
|
|
8
13
|
# path = "grammars/tree-sitter-gram"
|
|
9
14
|
[grammars.gram]
|
|
10
15
|
repository = "https://github.com/gram-data/tree-sitter-gram"
|
|
11
|
-
rev = "
|
|
16
|
+
rev = "184b524f4a0653bee3a07c44907dc266d698cb6e"
|
|
@@ -12,5 +12,5 @@ word_characters = ["_"]
|
|
|
12
12
|
[prettier]
|
|
13
13
|
allowed = false
|
|
14
14
|
|
|
15
|
-
# [language_servers]
|
|
16
|
-
#
|
|
15
|
+
# Language servers are declared in extension.toml (`[language_servers.gram-lsp]`)
|
|
16
|
+
# and started from `src/lib.rs`. Per-server options go in Zed settings.json under `lsp`.
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
//! Zed extension host glue: starts `gram-lsp` from `PATH` or downloads a release asset.
|
|
2
|
+
|
|
3
|
+
use zed_extension_api::{
|
|
4
|
+
self as zed,
|
|
5
|
+
github_release_by_tag_name,
|
|
6
|
+
set_language_server_installation_status,
|
|
7
|
+
Architecture, Command, DownloadedFileType, Extension, LanguageServerId,
|
|
8
|
+
LanguageServerInstallationStatus, Os, Result, Worktree, current_platform, download_file,
|
|
9
|
+
make_file_executable,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const GRAM_REPO: &str = "gram-data/tree-sitter-gram";
|
|
13
|
+
|
|
14
|
+
struct GramExtension {
|
|
15
|
+
/// Relative path (under the extension work dir) or absolute path from `which`.
|
|
16
|
+
cached_binary: Option<String>,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
impl GramExtension {
|
|
20
|
+
fn rust_target_triple() -> Result<&'static str> {
|
|
21
|
+
match current_platform() {
|
|
22
|
+
(Os::Mac, Architecture::Aarch64) => Ok("aarch64-apple-darwin"),
|
|
23
|
+
(Os::Mac, Architecture::X8664) => Ok("x86_64-apple-darwin"),
|
|
24
|
+
(Os::Linux, Architecture::Aarch64) => Ok("aarch64-unknown-linux-gnu"),
|
|
25
|
+
(Os::Linux, Architecture::X8664) => Ok("x86_64-unknown-linux-gnu"),
|
|
26
|
+
(Os::Windows, Architecture::Aarch64) => Ok("aarch64-pc-windows-msvc"),
|
|
27
|
+
(Os::Windows, Architecture::X8664) => Ok("x86_64-pc-windows-msvc"),
|
|
28
|
+
(Os::Linux, Architecture::X86) | (Os::Windows, Architecture::X86) => Err(
|
|
29
|
+
"gram-lsp: 32-bit platforms are not supported; install gram-lsp on PATH manually"
|
|
30
|
+
.into(),
|
|
31
|
+
),
|
|
32
|
+
(Os::Mac, Architecture::X86) => Err(
|
|
33
|
+
"gram-lsp: unexpected macOS x86 architecture; install gram-lsp on PATH manually"
|
|
34
|
+
.into(),
|
|
35
|
+
),
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
fn gram_lsp_bin_name(os: Os) -> &'static str {
|
|
40
|
+
match os {
|
|
41
|
+
Os::Windows => "gram-lsp.exe",
|
|
42
|
+
Os::Mac | Os::Linux => "gram-lsp",
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
fn ensure_downloaded(
|
|
47
|
+
&mut self,
|
|
48
|
+
language_server_id: &LanguageServerId,
|
|
49
|
+
) -> Result<String> {
|
|
50
|
+
let version = env!("GRAM_EXT_VERSION");
|
|
51
|
+
let extract_dir = format!("gram-lsp-{version}");
|
|
52
|
+
let (os, _) = current_platform();
|
|
53
|
+
let bin_name = Self::gram_lsp_bin_name(os);
|
|
54
|
+
let relative_binary = format!("{extract_dir}/{bin_name}");
|
|
55
|
+
|
|
56
|
+
let triple = Self::rust_target_triple()?;
|
|
57
|
+
let asset_name = format!("gram-lsp-{triple}.tar.gz");
|
|
58
|
+
let tag = format!("v{version}");
|
|
59
|
+
|
|
60
|
+
set_language_server_installation_status(
|
|
61
|
+
language_server_id,
|
|
62
|
+
&LanguageServerInstallationStatus::Downloading,
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
let release = match github_release_by_tag_name(GRAM_REPO, &tag) {
|
|
66
|
+
Ok(r) => r,
|
|
67
|
+
Err(e) => {
|
|
68
|
+
let detail = format!(
|
|
69
|
+
"GitHub release {tag}: {e}. Install `gram-lsp` on PATH or publish release assets (see .github/workflows/gram-lsp-release-assets.yml)."
|
|
70
|
+
);
|
|
71
|
+
set_language_server_installation_status(
|
|
72
|
+
language_server_id,
|
|
73
|
+
&LanguageServerInstallationStatus::Failed(detail.clone()),
|
|
74
|
+
);
|
|
75
|
+
return Err(format!("gram-lsp: no GitHub release for {tag}: {e}"));
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
let asset = match release.assets.iter().find(|a| a.name == asset_name) {
|
|
80
|
+
Some(a) => a,
|
|
81
|
+
None => {
|
|
82
|
+
let msg = format!(
|
|
83
|
+
"gram-lsp: release {tag} has no asset {asset_name}. Build with the gram-lsp-release-assets workflow."
|
|
84
|
+
);
|
|
85
|
+
set_language_server_installation_status(
|
|
86
|
+
language_server_id,
|
|
87
|
+
&LanguageServerInstallationStatus::Failed(msg.clone()),
|
|
88
|
+
);
|
|
89
|
+
return Err(msg);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
if let Err(e) = download_file(
|
|
94
|
+
&asset.download_url,
|
|
95
|
+
&extract_dir,
|
|
96
|
+
DownloadedFileType::GzipTar,
|
|
97
|
+
) {
|
|
98
|
+
set_language_server_installation_status(
|
|
99
|
+
language_server_id,
|
|
100
|
+
&LanguageServerInstallationStatus::Failed(e.clone()),
|
|
101
|
+
);
|
|
102
|
+
return Err(format!("gram-lsp: download failed: {e}"));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if let Err(e) = make_file_executable(&relative_binary) {
|
|
106
|
+
set_language_server_installation_status(
|
|
107
|
+
language_server_id,
|
|
108
|
+
&LanguageServerInstallationStatus::Failed(e.clone()),
|
|
109
|
+
);
|
|
110
|
+
return Err(format!("gram-lsp: chmod failed: {e}"));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
set_language_server_installation_status(
|
|
114
|
+
language_server_id,
|
|
115
|
+
&LanguageServerInstallationStatus::None,
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
self.cached_binary = Some(relative_binary.clone());
|
|
119
|
+
Ok(relative_binary)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
impl Extension for GramExtension {
|
|
124
|
+
fn new() -> Self {
|
|
125
|
+
Self {
|
|
126
|
+
cached_binary: None,
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
fn language_server_command(
|
|
131
|
+
&mut self,
|
|
132
|
+
language_server_id: &LanguageServerId,
|
|
133
|
+
worktree: &Worktree,
|
|
134
|
+
) -> Result<Command> {
|
|
135
|
+
if language_server_id.as_ref() != "gram-lsp" {
|
|
136
|
+
return Err(format!(
|
|
137
|
+
"unsupported language server id: {}",
|
|
138
|
+
language_server_id.as_ref()
|
|
139
|
+
));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if let Some(path) = &self.cached_binary {
|
|
143
|
+
return Ok(Command::new(path).arg("stdio"));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if let Some(path) = worktree.which("gram-lsp") {
|
|
147
|
+
self.cached_binary = Some(path.clone());
|
|
148
|
+
return Ok(Command::new(path).arg("stdio"));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let path = self.ensure_downloaded(language_server_id)?;
|
|
152
|
+
Ok(Command::new(path).arg("stdio"))
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
zed::register_extension!(GramExtension);
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/parser.c
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Automatically @generated by tree-sitter */
|
|
1
|
+
/* Automatically @generated by tree-sitter v0.25.10 */
|
|
2
2
|
|
|
3
3
|
#include "tree_sitter/parser.h"
|
|
4
4
|
|
|
@@ -4368,7 +4368,7 @@ TS_PUBLIC const TSLanguage *tree_sitter_gram(void) {
|
|
|
4368
4368
|
.metadata = {
|
|
4369
4369
|
.major_version = 0,
|
|
4370
4370
|
.minor_version = 3,
|
|
4371
|
-
.patch_version =
|
|
4371
|
+
.patch_version = 6,
|
|
4372
4372
|
},
|
|
4373
4373
|
};
|
|
4374
4374
|
return &language;
|
package/src/tree_sitter/array.h
CHANGED
|
@@ -52,91 +52,67 @@ extern "C" {
|
|
|
52
52
|
|
|
53
53
|
/// Reserve `new_capacity` elements of space in the array. If `new_capacity` is
|
|
54
54
|
/// less than the array's current capacity, this function has no effect.
|
|
55
|
-
#define array_reserve(self, new_capacity)
|
|
56
|
-
((self)
|
|
57
|
-
(void *)(self)->contents, &(self)->capacity, \
|
|
58
|
-
array_elem_size(self), new_capacity) \
|
|
59
|
-
)
|
|
55
|
+
#define array_reserve(self, new_capacity) \
|
|
56
|
+
_array__reserve((Array *)(self), array_elem_size(self), new_capacity)
|
|
60
57
|
|
|
61
58
|
/// Free any memory allocated for this array. Note that this does not free any
|
|
62
59
|
/// memory allocated for the array's contents.
|
|
63
|
-
#define array_delete(self) _array__delete((
|
|
60
|
+
#define array_delete(self) _array__delete((Array *)(self))
|
|
64
61
|
|
|
65
62
|
/// Push a new `element` onto the end of the array.
|
|
66
|
-
#define array_push(self, element)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
(void *)(self)->contents, (self)->size, &(self)->capacity, \
|
|
70
|
-
1, array_elem_size(self) \
|
|
71
|
-
); \
|
|
72
|
-
(self)->contents[(self)->size++] = (element); \
|
|
73
|
-
} while(0)
|
|
63
|
+
#define array_push(self, element) \
|
|
64
|
+
(_array__grow((Array *)(self), 1, array_elem_size(self)), \
|
|
65
|
+
(self)->contents[(self)->size++] = (element))
|
|
74
66
|
|
|
75
67
|
/// Increase the array's size by `count` elements.
|
|
76
68
|
/// New elements are zero-initialized.
|
|
77
|
-
#define array_grow_by(self, count)
|
|
78
|
-
do {
|
|
79
|
-
if ((count) == 0) break;
|
|
80
|
-
(self)
|
|
81
|
-
(self)->contents, (self)->size, &(self)->capacity, \
|
|
82
|
-
count, array_elem_size(self) \
|
|
83
|
-
); \
|
|
69
|
+
#define array_grow_by(self, count) \
|
|
70
|
+
do { \
|
|
71
|
+
if ((count) == 0) break; \
|
|
72
|
+
_array__grow((Array *)(self), count, array_elem_size(self)); \
|
|
84
73
|
memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \
|
|
85
|
-
(self)->size += (count);
|
|
74
|
+
(self)->size += (count); \
|
|
86
75
|
} while (0)
|
|
87
76
|
|
|
88
77
|
/// Append all elements from one array to the end of another.
|
|
89
|
-
#define array_push_all(self, other)
|
|
78
|
+
#define array_push_all(self, other) \
|
|
90
79
|
array_extend((self), (other)->size, (other)->contents)
|
|
91
80
|
|
|
92
81
|
/// Append `count` elements to the end of the array, reading their values from the
|
|
93
82
|
/// `contents` pointer.
|
|
94
|
-
#define array_extend(self, count,
|
|
95
|
-
|
|
96
|
-
(
|
|
97
|
-
|
|
83
|
+
#define array_extend(self, count, contents) \
|
|
84
|
+
_array__splice( \
|
|
85
|
+
(Array *)(self), array_elem_size(self), (self)->size, \
|
|
86
|
+
0, count, contents \
|
|
98
87
|
)
|
|
99
88
|
|
|
100
89
|
/// Remove `old_count` elements from the array starting at the given `index`. At
|
|
101
90
|
/// the same index, insert `new_count` new elements, reading their values from the
|
|
102
91
|
/// `new_contents` pointer.
|
|
103
|
-
#define array_splice(self, _index, old_count, new_count, new_contents)
|
|
104
|
-
|
|
105
|
-
(
|
|
106
|
-
|
|
92
|
+
#define array_splice(self, _index, old_count, new_count, new_contents) \
|
|
93
|
+
_array__splice( \
|
|
94
|
+
(Array *)(self), array_elem_size(self), _index, \
|
|
95
|
+
old_count, new_count, new_contents \
|
|
107
96
|
)
|
|
108
97
|
|
|
109
98
|
/// Insert one `element` into the array at the given `index`.
|
|
110
|
-
#define array_insert(self, _index, element)
|
|
111
|
-
(self)
|
|
112
|
-
(void *)(self)->contents, &(self)->size, &(self)->capacity, \
|
|
113
|
-
array_elem_size(self), _index, 0, 1, &(element) \
|
|
114
|
-
)
|
|
99
|
+
#define array_insert(self, _index, element) \
|
|
100
|
+
_array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element))
|
|
115
101
|
|
|
116
102
|
/// Remove one element from the array at the given `index`.
|
|
117
103
|
#define array_erase(self, _index) \
|
|
118
|
-
_array__erase((
|
|
104
|
+
_array__erase((Array *)(self), array_elem_size(self), _index)
|
|
119
105
|
|
|
120
106
|
/// Pop the last element off the array, returning the element by value.
|
|
121
107
|
#define array_pop(self) ((self)->contents[--(self)->size])
|
|
122
108
|
|
|
123
109
|
/// Assign the contents of one array to another, reallocating if necessary.
|
|
124
|
-
#define array_assign(self, other)
|
|
125
|
-
(self)
|
|
126
|
-
(void *)(self)->contents, &(self)->size, &(self)->capacity, \
|
|
127
|
-
(const void *)(other)->contents, (other)->size, array_elem_size(self) \
|
|
128
|
-
)
|
|
110
|
+
#define array_assign(self, other) \
|
|
111
|
+
_array__assign((Array *)(self), (const Array *)(other), array_elem_size(self))
|
|
129
112
|
|
|
130
113
|
/// Swap one array with another
|
|
131
|
-
#define array_swap(self, other)
|
|
132
|
-
|
|
133
|
-
struct Swap swapped_contents = _array__swap( \
|
|
134
|
-
(void *)(self)->contents, &(self)->size, &(self)->capacity, \
|
|
135
|
-
(void *)(other)->contents, &(other)->size, &(other)->capacity \
|
|
136
|
-
); \
|
|
137
|
-
(self)->contents = swapped_contents.self_contents; \
|
|
138
|
-
(other)->contents = swapped_contents.other_contents; \
|
|
139
|
-
} while (0)
|
|
114
|
+
#define array_swap(self, other) \
|
|
115
|
+
_array__swap((Array *)(self), (Array *)(other))
|
|
140
116
|
|
|
141
117
|
/// Get the size of the array contents
|
|
142
118
|
#define array_elem_size(self) (sizeof *(self)->contents)
|
|
@@ -181,112 +157,82 @@ extern "C" {
|
|
|
181
157
|
|
|
182
158
|
// Private
|
|
183
159
|
|
|
184
|
-
|
|
185
|
-
// are passed to the various `_array__*` functions below to address strict aliasing
|
|
186
|
-
// violations that arises when the _entire_ `Array` struct is passed as `Array(void)*`.
|
|
187
|
-
//
|
|
188
|
-
// The `Array` type itself was not altered as a solution in order to avoid breakage
|
|
189
|
-
// with existing consumers (in particular, parsers with external scanners).
|
|
160
|
+
typedef Array(void) Array;
|
|
190
161
|
|
|
191
162
|
/// This is not what you're looking for, see `array_delete`.
|
|
192
|
-
static inline void _array__delete(
|
|
193
|
-
if (contents)
|
|
194
|
-
|
|
163
|
+
static inline void _array__delete(Array *self) {
|
|
164
|
+
if (self->contents) {
|
|
165
|
+
ts_free(self->contents);
|
|
166
|
+
self->contents = NULL;
|
|
167
|
+
self->size = 0;
|
|
168
|
+
self->capacity = 0;
|
|
169
|
+
}
|
|
195
170
|
}
|
|
196
171
|
|
|
197
172
|
/// This is not what you're looking for, see `array_erase`.
|
|
198
|
-
static inline void _array__erase(
|
|
199
|
-
|
|
200
|
-
assert(index <
|
|
201
|
-
char *contents = (char *)
|
|
173
|
+
static inline void _array__erase(Array *self, size_t element_size,
|
|
174
|
+
uint32_t index) {
|
|
175
|
+
assert(index < self->size);
|
|
176
|
+
char *contents = (char *)self->contents;
|
|
202
177
|
memmove(contents + index * element_size, contents + (index + 1) * element_size,
|
|
203
|
-
(
|
|
204
|
-
|
|
178
|
+
(self->size - index - 1) * element_size);
|
|
179
|
+
self->size--;
|
|
205
180
|
}
|
|
206
181
|
|
|
207
182
|
/// This is not what you're looking for, see `array_reserve`.
|
|
208
|
-
static inline void
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if (contents) {
|
|
213
|
-
new_contents = ts_realloc(contents, new_capacity * element_size);
|
|
183
|
+
static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) {
|
|
184
|
+
if (new_capacity > self->capacity) {
|
|
185
|
+
if (self->contents) {
|
|
186
|
+
self->contents = ts_realloc(self->contents, new_capacity * element_size);
|
|
214
187
|
} else {
|
|
215
|
-
|
|
188
|
+
self->contents = ts_malloc(new_capacity * element_size);
|
|
216
189
|
}
|
|
217
|
-
|
|
190
|
+
self->capacity = new_capacity;
|
|
218
191
|
}
|
|
219
|
-
return new_contents;
|
|
220
192
|
}
|
|
221
193
|
|
|
222
194
|
/// This is not what you're looking for, see `array_assign`.
|
|
223
|
-
static inline void
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
*
|
|
227
|
-
memcpy(new_contents, other_contents, *self_size * element_size);
|
|
228
|
-
return new_contents;
|
|
195
|
+
static inline void _array__assign(Array *self, const Array *other, size_t element_size) {
|
|
196
|
+
_array__reserve(self, element_size, other->size);
|
|
197
|
+
self->size = other->size;
|
|
198
|
+
memcpy(self->contents, other->contents, self->size * element_size);
|
|
229
199
|
}
|
|
230
200
|
|
|
231
|
-
struct Swap {
|
|
232
|
-
void *self_contents;
|
|
233
|
-
void *other_contents;
|
|
234
|
-
};
|
|
235
|
-
|
|
236
201
|
/// This is not what you're looking for, see `array_swap`.
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
uint32_t new_self_size = *other_size;
|
|
242
|
-
uint32_t new_self_capacity = *other_capacity;
|
|
243
|
-
|
|
244
|
-
void *new_other_contents = self_contents;
|
|
245
|
-
*other_size = *self_size;
|
|
246
|
-
*other_capacity = *self_capacity;
|
|
247
|
-
|
|
248
|
-
*self_size = new_self_size;
|
|
249
|
-
*self_capacity = new_self_capacity;
|
|
250
|
-
|
|
251
|
-
struct Swap out = {
|
|
252
|
-
.self_contents = new_self_contents,
|
|
253
|
-
.other_contents = new_other_contents,
|
|
254
|
-
};
|
|
255
|
-
return out;
|
|
202
|
+
static inline void _array__swap(Array *self, Array *other) {
|
|
203
|
+
Array swap = *other;
|
|
204
|
+
*other = *self;
|
|
205
|
+
*self = swap;
|
|
256
206
|
}
|
|
257
207
|
|
|
258
208
|
/// This is not what you're looking for, see `array_push` or `array_grow_by`.
|
|
259
|
-
static inline void
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
if (new_size > *capacity) {
|
|
264
|
-
uint32_t new_capacity = *capacity * 2;
|
|
209
|
+
static inline void _array__grow(Array *self, uint32_t count, size_t element_size) {
|
|
210
|
+
uint32_t new_size = self->size + count;
|
|
211
|
+
if (new_size > self->capacity) {
|
|
212
|
+
uint32_t new_capacity = self->capacity * 2;
|
|
265
213
|
if (new_capacity < 8) new_capacity = 8;
|
|
266
214
|
if (new_capacity < new_size) new_capacity = new_size;
|
|
267
|
-
|
|
215
|
+
_array__reserve(self, element_size, new_capacity);
|
|
268
216
|
}
|
|
269
|
-
return new_contents;
|
|
270
217
|
}
|
|
271
218
|
|
|
272
219
|
/// This is not what you're looking for, see `array_splice`.
|
|
273
|
-
static inline void
|
|
274
|
-
size_t element_size,
|
|
220
|
+
static inline void _array__splice(Array *self, size_t element_size,
|
|
275
221
|
uint32_t index, uint32_t old_count,
|
|
276
222
|
uint32_t new_count, const void *elements) {
|
|
277
|
-
uint32_t new_size =
|
|
223
|
+
uint32_t new_size = self->size + new_count - old_count;
|
|
278
224
|
uint32_t old_end = index + old_count;
|
|
279
225
|
uint32_t new_end = index + new_count;
|
|
280
|
-
assert(old_end <=
|
|
226
|
+
assert(old_end <= self->size);
|
|
281
227
|
|
|
282
|
-
|
|
228
|
+
_array__reserve(self, element_size, new_size);
|
|
283
229
|
|
|
284
|
-
char *contents = (char *)
|
|
285
|
-
if (
|
|
230
|
+
char *contents = (char *)self->contents;
|
|
231
|
+
if (self->size > old_end) {
|
|
286
232
|
memmove(
|
|
287
233
|
contents + new_end * element_size,
|
|
288
234
|
contents + old_end * element_size,
|
|
289
|
-
(
|
|
235
|
+
(self->size - old_end) * element_size
|
|
290
236
|
);
|
|
291
237
|
}
|
|
292
238
|
if (new_count > 0) {
|
|
@@ -304,9 +250,7 @@ static inline void *_array__splice(void *self_contents, uint32_t *size, uint32_t
|
|
|
304
250
|
);
|
|
305
251
|
}
|
|
306
252
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
return new_contents;
|
|
253
|
+
self->size += new_count - old_count;
|
|
310
254
|
}
|
|
311
255
|
|
|
312
256
|
/// A binary search routine, based on Rust's `std::slice::binary_search_by`.
|
package/tree-sitter-gram.wasm
CHANGED
|
Binary file
|