#![cfg(feature = "c-parser")]
use c_grammar_gen::{c11_lexer::build_c11_lexer_dfa, wire::PackedBlob};
use vyre::DispatchConfig;
use vyre_emit_naga::program::emit_module;
use vyre_libs::parsing::c::lex::keyword::{c_keyword, C_KEYWORDS};
use vyre_libs::parsing::c::lex::lexer::c11_lexer;
use vyre_libs::parsing::c::lower::c_lower_ast_to_pg_nodes;
use vyre_libs::parsing::c::parse::structure::{c11_extract_calls, c11_extract_functions};
use vyre_libs::parsing::c::parse::vast::{c11_build_vast_nodes, c11_classify_vast_node_kinds};
use vyre_libs::parsing::c::sema::c_sema_scope;
use vyre_primitives::graph::program_graph::NAME_NODES;
const TEST_WORKGROUP_SIZE: [u32; 3] = [1, 1, 1];
const C11_PIPELINE_SMOKE_TOKENS: u32 = 9;
fn emit_wgsl(program: &vyre::ir::Program) -> String {
let module = emit_module(program, &DispatchConfig::default(), TEST_WORKGROUP_SIZE)
.expect("Program must lower to a valid Naga module");
let info = naga::valid::Validator::new(
naga::valid::ValidationFlags::all(),
naga::valid::Capabilities::all(),
)
.validate(&module)
.expect("Naga must accept the Program");
naga::back::wgsl::write_string(&module, &info, naga::back::wgsl::WriterFlags::empty())
.expect("Program must serialize to WGSL")
}
#[test]
fn c11_dfa_builder_produces_populated_table() {
let table = build_c11_lexer_dfa();
assert!(
table.num_states >= 16,
"C11 DFA must reach ≥16 states (identifiers + punctuation + keyword starts), got {}",
table.num_states
);
assert!(
table.num_classes >= 2,
"C11 DFA must have ≥2 char classes populated, got {}",
table.num_classes
);
let blob = PackedBlob::from_dfa(&table);
assert!(!blob.bytes.is_empty(), "packed DFA blob must be non-empty");
assert_eq!(
&blob.bytes[0..4],
b"SGGC",
"packed DFA blob must start with the SGGC magic"
);
}
#[test]
fn c11_lexer_program_validates_and_emits_wgsl() {
let program = c11_lexer(
"haystack",
"out_tok_types",
"out_tok_starts",
"out_tok_lens",
"out_counts",
4096,
);
let errors = vyre::validate(&program);
assert!(errors.is_empty(), "c11_lexer must IR-validate: {errors:?}");
let wgsl = emit_wgsl(&program);
assert!(
wgsl.contains("@compute"),
"c11_lexer WGSL must declare a @compute entry: {wgsl}"
);
assert!(
wgsl.contains("out_counts"),
"c11_lexer must publish the compact token count for downstream parser stages: {wgsl}"
);
}
#[test]
fn c11_keyword_program_validates_and_emits_wgsl() {
let program = c_keyword(
"tok_types",
"tok_starts",
"tok_lens",
"counts",
"haystack",
"keyword_map",
4096,
C_KEYWORDS.len() as u32,
4096,
);
let errors = vyre::validate(&program);
assert!(errors.is_empty(), "c_keyword must IR-validate: {errors:?}");
let wgsl = emit_wgsl(&program);
assert!(
wgsl.contains("@compute"),
"c_keyword WGSL must declare a compute entry: {wgsl}"
);
}
#[test]
fn c11_extract_functions_program_validates_and_emits_wgsl() {
let program = c11_extract_functions(
"tok_types",
"paren_pairs",
"brace_pairs",
vyre::ir::Expr::u32(4096),
"out_functions",
"out_counts",
);
let errors = vyre::validate(&program);
assert!(
errors.is_empty(),
"c11_extract_functions must IR-validate: {errors:?}"
);
let wgsl = emit_wgsl(&program);
assert!(
wgsl.contains("@compute"),
"c11_extract_functions WGSL must declare a compute entry: {wgsl}"
);
}
#[test]
fn c11_extract_calls_program_validates_and_emits_wgsl() {
let program = c11_extract_calls(
"tok_types",
"paren_pairs",
"functions",
vyre::ir::Expr::u32(4096),
vyre::ir::Expr::u32(128),
"out_calls",
"out_counts",
);
let errors = vyre::validate(&program);
assert!(
errors.is_empty(),
"c11_extract_calls must IR-validate: {errors:?}"
);
let wgsl = emit_wgsl(&program);
assert!(
wgsl.contains("@compute"),
"c11_extract_calls WGSL must declare a compute entry: {wgsl}"
);
}
#[test]
fn c11_build_vast_nodes_program_validates_and_emits_wgsl() {
let program = c11_build_vast_nodes(
"tok_types",
"tok_starts",
"tok_lens",
vyre::ir::Expr::u32(C11_PIPELINE_SMOKE_TOKENS),
"vast_nodes",
"vast_count",
);
let errors = vyre::validate(&program);
assert!(
errors.is_empty(),
"c11_build_vast_nodes must IR-validate: {errors:?}"
);
let wgsl = emit_wgsl(&program);
assert!(
wgsl.contains("@compute"),
"c11_build_vast_nodes WGSL must declare a compute entry: {wgsl}"
);
}
#[test]
fn c11_classify_vast_node_kinds_program_validates_and_emits_wgsl() {
let program = c11_classify_vast_node_kinds(
"vast_nodes",
vyre::ir::Expr::u32(C11_PIPELINE_SMOKE_TOKENS),
"typed_vast_nodes",
);
let errors = vyre::validate(&program);
assert!(
errors.is_empty(),
"c11_classify_vast_node_kinds must IR-validate: {errors:?}"
);
let wgsl = emit_wgsl(&program);
assert!(
wgsl.contains("@compute"),
"c11_classify_vast_node_kinds WGSL must declare a compute entry: {wgsl}"
);
}
#[test]
fn c11_ast_to_program_graph_lowering_validates_and_emits_wgsl() {
let program = c_lower_ast_to_pg_nodes(
"vast_nodes",
vyre::ir::Expr::u32(C11_PIPELINE_SMOKE_TOKENS),
NAME_NODES,
);
let errors = vyre::validate(&program);
assert!(
errors.is_empty(),
"c_lower_ast_to_pg_nodes must IR-validate: {errors:?}"
);
let wgsl = emit_wgsl(&program);
assert!(
wgsl.contains(NAME_NODES),
"c_lower_ast_to_pg_nodes WGSL must write canonical ProgramGraph node buffer {NAME_NODES}: {wgsl}"
);
}
#[test]
fn c11_parser_pipeline_integrates_without_stitching_errors() {
let lexer = c11_lexer(
"haystack",
"out_tok_types",
"out_tok_starts",
"out_tok_lens",
"out_counts",
4096,
);
let functions = c11_extract_functions(
"tok_types",
"paren_pairs",
"brace_pairs",
vyre::ir::Expr::u32(4096),
"out_functions",
"out_counts",
);
let calls = c11_extract_calls(
"tok_types",
"paren_pairs",
"functions",
vyre::ir::Expr::u32(4096),
vyre::ir::Expr::u32(128),
"out_calls",
"out_counts",
);
let sema = c_sema_scope(
"tok_types",
"tok_starts",
"tok_lens",
"haystack",
vyre::ir::Expr::u32(4096),
vyre::ir::Expr::u32(4096),
"out_scope_tree",
);
let keywords = c_keyword(
"tok_types",
"tok_starts",
"tok_lens",
"counts",
"haystack",
"keyword_map",
4096,
C_KEYWORDS.len() as u32,
4096,
);
let vast = c11_build_vast_nodes(
"tok_types",
"tok_starts",
"tok_lens",
vyre::ir::Expr::u32(C11_PIPELINE_SMOKE_TOKENS),
"vast_nodes",
"vast_count",
);
let typed_vast = c11_classify_vast_node_kinds(
"vast_nodes",
vyre::ir::Expr::u32(C11_PIPELINE_SMOKE_TOKENS),
"typed_vast_nodes",
);
let pg_nodes = c_lower_ast_to_pg_nodes(
"typed_vast_nodes",
vyre::ir::Expr::u32(C11_PIPELINE_SMOKE_TOKENS),
NAME_NODES,
);
for (name, prog) in [
("c11_lexer", &lexer),
("c_keyword", &keywords),
("c11_build_vast_nodes", &vast),
("c11_classify_vast_node_kinds", &typed_vast),
("c_lower_ast_to_pg_nodes", &pg_nodes),
("c11_extract_functions", &functions),
("c11_extract_calls", &calls),
("c11_sema_scope", &sema),
] {
let errors = vyre::validate(prog);
assert!(
errors.is_empty(),
"{name} must validate in the unified smoke: {errors:?}"
);
let _ = emit_wgsl(prog);
}
}