Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c9531c6
feat(codegen): Extract shared emission toolkit
zharinov Jul 9, 2026
f53b138
feat(codegen): Extract target-neutral output schema
zharinov Jul 9, 2026
dfd941f
feat(codegen): Extract target-neutral matcher plan
zharinov Jul 9, 2026
627c18b
feat(codegen): Extract target-neutral replay plan
zharinov Jul 9, 2026
1ef8477
feat(codegen): Plan generated runtime limits
zharinov Jul 9, 2026
8b1f9b5
feat(codegen): Add portable regex automata
zharinov Jul 9, 2026
c583537
feat(docs): Define generated runtime interface
zharinov Jul 9, 2026
2d86813
feat(conformance): Export VM oracle corpus
zharinov Jul 10, 2026
91bf09e
feat(regex): Normalize semantics across targets
zharinov Jul 10, 2026
ba78e28
test(conformance): Add regex portability cases
zharinov Jul 10, 2026
95b0342
feat(codegen): Add Rust generation product loop
zharinov Jul 10, 2026
4a149f7
fix(codegen): Ignore inspection effects in generated matchers
zharinov Jul 10, 2026
b34ac50
refactor(compiler): Hoist shared source generation
zharinov Jul 10, 2026
0c0c095
refactor(typegen): Share Rust representation model
zharinov Jul 10, 2026
13cc954
refactor(codegen): Correct semantic ownership boundaries
zharinov Jul 10, 2026
33daa41
refactor(codegen): Isolate Rust generation contracts
zharinov Jul 10, 2026
7847d88
fix(codegen): isolate template substitutions
zharinov Jul 10, 2026
faef7a8
fix(conformance): preserve source-like fixture rules
zharinov Jul 10, 2026
90f2f8c
perf(playground): generate Rust matcher on demand
zharinov Jul 10, 2026
827cb60
fix(playground): stabilize clipboard feedback
zharinov Jul 10, 2026
4b374e2
fix(compiler): report total output member overflow
zharinov Jul 10, 2026
67fec75
perf(typegen): skip unused semantic ranges
zharinov Jul 10, 2026
e6824b4
refactor(conformance): reuse grammar identity
zharinov Jul 10, 2026
54a0c23
refactor(conformance): share file discovery
zharinov Jul 10, 2026
ba0da21
refactor(regex): share literal metacharacters
zharinov Jul 10, 2026
692e8b1
refactor(codegen): reuse reader type context
zharinov Jul 10, 2026
2ccc045
refactor(cli): trust generate argument conflicts
zharinov Jul 10, 2026
5b00915
feat(compiler): unify emission targets
zharinov Jul 10, 2026
1f5d008
test(conformance): remove exported corpus
zharinov Jul 10, 2026
ee8bfdd
Remove obsolete conformance test module
zharinov Jul 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ tree-sitter-plotnik/src/

# Generated by `make wasm-web`
web/src/lib/plotnik-wasm/

# Generated by `make shot` through the VM-oracle exporter
conformance/corpus/
87 changes: 80 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ members = [
]

[workspace.package]
version = "0.3.3"
version = "0.4.0"
license = "Apache-2.0"
repository = "https://github.com/plotnik-lang/plotnik"
edition = "2024"

[workspace.dependencies]
plotnik-lib = { path = "crates/plotnik-lib", version = "0.3.3" }
plotnik-rt = { path = "crates/plotnik-rt", version = "0.3.3", default-features = false }
plotnik-lib = { path = "crates/plotnik-lib", version = "0.4.0" }
plotnik-rt = { path = "crates/plotnik-rt", version = "0.4.0", default-features = false }

[workspace.lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] }
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ dynamic values:

```toml
[dependencies]
plotnik = "0.3"
plotnik = "0.4"
tree-sitter-javascript = "0.25"
```

Expand Down
4 changes: 2 additions & 2 deletions crates/plotnik-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ lang-zsh = ["dep:arborium-zsh"]
[dependencies]
clap = { version = "4.5", features = ["derive", "string"] }
clap_complete = "4.5"
plotnik-lib = { path = "../plotnik-lib", version = "0.3.3", default-features = false, features = ["vm"] }
plotnik-lib = { path = "../plotnik-lib", version = "0.4.0", default-features = false, features = ["vm"] }
serde_json = "1"
tree-sitter = "0.26.10"
# @generated:lang-deps:begin
Expand Down Expand Up @@ -379,7 +379,7 @@ libc = "0.2"
[build-dependencies]
cargo_metadata = "0.23"
flate2 = "1.1"
plotnik-lib = { path = "../plotnik-lib", version = "0.3.3", default-features = false }
plotnik-lib = { path = "../plotnik-lib", version = "0.4.0", default-features = false }

[dev-dependencies]
indoc = "=2.0.7"
Expand Down
4 changes: 4 additions & 0 deletions crates/plotnik-cli/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ fn main() {
env_key,
out_path.display()
);
println!(
"cargo::rustc-env=PLOTNIK_GRAMMAR_SOURCE_{}={}@{}",
env_key, package.name, package.version
);
println!("cargo::rerun-if-changed={grammar_path}");
}

Expand Down
20 changes: 20 additions & 0 deletions crates/plotnik-cli/src/cli/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use std::path::PathBuf;

use clap::{Arg, ArgAction, value_parser};

use crate::commands::generate::GenerateTarget;

pub fn query_path_arg() -> Arg {
Arg::new("query_path")
.value_name("QUERY")
Expand Down Expand Up @@ -122,6 +124,24 @@ pub fn output_file_arg() -> Arg {
.help("Write output to file")
}

pub fn target_arg() -> Arg {
Arg::new("target")
.long("target")
.value_name("TARGET")
.value_parser(value_parser!(GenerateTarget))
.required(true)
.help("Generated-code target (rust)")
}

pub fn grammar_arg() -> Arg {
Arg::new("grammar")
.long("grammar")
.value_name("GRAMMAR_JSON")
.value_parser(value_parser!(PathBuf))
.conflicts_with("lang")
.help("Link against this exact grammar.json instead of the registry")
}

pub fn compact_arg() -> Arg {
Arg::new("compact")
.long("compact")
Expand Down
31 changes: 31 additions & 0 deletions crates/plotnik-cli/src/cli/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,44 @@ Run 'plotnik <command> --help' for examples."#,
.subcommand(check_command())
.subcommand(ast_command())
.subcommand(infer_command())
.subcommand(generate_command())
.subcommand(dump_command())
.subcommand(trace_command())
.subcommand(inspect_command())
.subcommand(lang_command())
.subcommand(completions_command())
}

pub fn generate_command() -> Command {
Command::new("generate")
.about("Generate a compiled matcher module")
.override_usage(
"\
plotnik generate <QUERY> --target rust -l <LANG>
plotnik generate <QUERY> --target rust --grammar <grammar.json>
plotnik generate -q <TEXT> --target rust -l <LANG>",
)
.after_help(
r#"EXAMPLES:
plotnik generate query.ptk --target rust -l typescript
plotnik generate query.ptk --target rust --grammar node_modules/tree-sitter-typescript/typescript/src/grammar.json
plotnik generate query.ptk --target rust -l javascript -o query.rs

The generated module depends on the `plotnik-rt` crate and records the exact
grammar name, SHA-256, and source used during linking."#,
)
.arg(query_path_arg())
.next_help_heading("Input options")
.arg(query_text_arg())
.arg(lang_arg())
.arg(grammar_arg())
.next_help_heading("Generation options")
.arg(target_arg())
.arg(output_file_arg())
.next_help_heading("Global options")
.arg(color_arg())
}

pub fn ast_command() -> Command {
let cmd = Command::new("ast")
.about("Show AST of query and/or source file")
Expand Down
42 changes: 42 additions & 0 deletions crates/plotnik-cli/src/cli/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use super::limits::resolve_limit_spec;
use crate::commands::ast::AstArgs;
use crate::commands::check::CheckArgs;
use crate::commands::dump::DumpArgs;
use crate::commands::generate::{GenerateArgs, GenerateTarget};
use crate::commands::infer::InferArgs;
use crate::commands::inspect::InspectArgs;
use crate::commands::run::RunArgs;
Expand Down Expand Up @@ -188,6 +189,47 @@ impl From<InferOpts> for InferArgs {
}
}

pub struct GenerateOpts {
pub query_path: Option<PathBuf>,
pub query_text: Option<String>,
pub lang: Option<String>,
pub grammar: Option<PathBuf>,
pub target: GenerateTarget,
pub output: Option<PathBuf>,
pub color: ColorChoice,
}

impl GenerateOpts {
pub fn from_matches(m: &ArgMatches) -> Self {
Self {
query_path: m.get_one::<PathBuf>("query_path").cloned(),
query_text: m.get_one::<String>("query_text").cloned(),
lang: m.get_one::<String>("lang").cloned(),
grammar: m.get_one::<PathBuf>("grammar").cloned(),
target: m
.get_one::<GenerateTarget>("target")
.copied()
.expect("clap guarantees --target is present"),
output: m.get_one::<PathBuf>("output").cloned(),
color: ColorChoice::from_matches(m),
}
}
}

impl From<GenerateOpts> for GenerateArgs {
fn from(options: GenerateOpts) -> Self {
Self {
query_path: options.query_path,
query_text: options.query_text,
lang: options.lang,
grammar: options.grammar,
target: options.target,
output: options.output,
color: options.color.should_colorize(),
}
}
}

pub struct RunOpts {
pub query_path: Option<PathBuf>,
pub query_text: Option<String>,
Expand Down
Loading
Loading