use crate::parsing::c::lex::tokens::*;
use crate::parsing::composition::child_phase;
use crate::region::wrap_anonymous;
use vyre::ir::{BufferAccess, BufferDecl, DataType, Expr, Node, Program};
#[must_use]
pub fn opt_propagate_type_specifiers(
tok_types: &str,
tok_depths: &str,
node_out: &str,
num_tokens: Expr,
) -> Program {
let t = Expr::InvocationId { axis: 0 };
let loop_body = vec![
Node::let_bind("tok", Expr::load(tok_types, t.clone())),
Node::let_bind("depth", Expr::load(tok_depths, t.clone())),
Node::let_bind("active_type", Expr::u32(0)),
Node::let_bind("blocked", Expr::u32(0)),
Node::let_bind("brace_skip_depth", Expr::u32(0)),
Node::loop_for(
"scan_delta",
Expr::u32(0),
Expr::add(t.clone(), Expr::u32(1)),
vec![
Node::let_bind("scan_i", Expr::sub(t.clone(), Expr::var("scan_delta"))),
Node::let_bind("scan_tok", Expr::load(tok_types, Expr::var("scan_i"))),
Node::let_bind("scan_depth", Expr::load(tok_depths, Expr::var("scan_i"))),
Node::let_bind("scan_has_prev", Expr::gt(Expr::var("scan_i"), Expr::u32(0))),
Node::let_bind(
"scan_has_prev_prev",
Expr::gt(Expr::var("scan_i"), Expr::u32(1)),
),
Node::let_bind(
"prev_tok",
Expr::select(
Expr::var("scan_has_prev"),
Expr::load(tok_types, Expr::sub(Expr::var("scan_i"), Expr::u32(1))),
Expr::u32(TOK_EOF),
),
),
Node::let_bind(
"prev_prev_tok",
Expr::select(
Expr::var("scan_has_prev_prev"),
Expr::load(tok_types, Expr::sub(Expr::var("scan_i"), Expr::u32(2))),
Expr::u32(TOK_EOF),
),
),
Node::let_bind(
"same_or_outer_depth",
Expr::le(Expr::var("scan_depth"), Expr::var("depth")),
),
Node::if_then(
Expr::and(
Expr::eq(Expr::var("blocked"), Expr::u32(0)),
Expr::and(
Expr::var("same_or_outer_depth"),
Expr::gt(Expr::var("brace_skip_depth"), Expr::u32(0)),
),
),
vec![
Node::if_then(
Expr::eq(Expr::var("scan_tok"), Expr::u32(TOK_RBRACE)),
vec![Node::assign(
"brace_skip_depth",
Expr::add(Expr::var("brace_skip_depth"), Expr::u32(1)),
)],
),
Node::if_then(
Expr::eq(Expr::var("scan_tok"), Expr::u32(TOK_LBRACE)),
vec![
Node::assign(
"brace_skip_depth",
Expr::sub(Expr::var("brace_skip_depth"), Expr::u32(1)),
),
Node::if_then(
Expr::and(
Expr::eq(Expr::var("brace_skip_depth"), Expr::u32(0)),
Expr::not(is_aggregate_body_open(
Expr::var("prev_tok"),
Expr::var("prev_prev_tok"),
)),
),
vec![Node::assign("blocked", Expr::u32(1))],
),
],
),
],
),
Node::if_then(
Expr::and(
Expr::eq(Expr::var("blocked"), Expr::u32(0)),
Expr::and(
Expr::eq(Expr::var("brace_skip_depth"), Expr::u32(0)),
Expr::and(
Expr::var("same_or_outer_depth"),
Expr::eq(Expr::var("scan_tok"), Expr::u32(TOK_RBRACE)),
),
),
),
vec![Node::assign("brace_skip_depth", Expr::u32(1))],
),
Node::if_then(
Expr::and(
Expr::eq(Expr::var("blocked"), Expr::u32(0)),
Expr::and(
Expr::eq(Expr::var("brace_skip_depth"), Expr::u32(0)),
Expr::and(
Expr::var("same_or_outer_depth"),
is_declaration_boundary(
Expr::var("scan_tok"),
Expr::var("prev_tok"),
Expr::var("prev_prev_tok"),
),
),
),
),
vec![Node::assign("blocked", Expr::u32(1))],
),
Node::if_then(
Expr::and(
Expr::eq(Expr::var("blocked"), Expr::u32(0)),
Expr::and(
Expr::eq(Expr::var("active_type"), Expr::u32(0)),
Expr::and(
Expr::and(
Expr::eq(Expr::var("brace_skip_depth"), Expr::u32(0)),
Expr::var("same_or_outer_depth"),
),
is_propagatable_type_token(
Expr::var("scan_tok"),
Expr::var("prev_tok"),
Expr::var("prev_prev_tok"),
Expr::gt(Expr::var("scan_delta"), Expr::u32(0)),
),
),
),
),
vec![Node::assign("active_type", Expr::var("scan_tok"))],
),
],
),
Node::store(node_out, t.clone(), Expr::var("active_type")),
];
let tok_count = match &num_tokens {
Expr::LitU32(n) => *n,
_ => 1,
};
Program::wrapped(
vec![
BufferDecl::storage(tok_types, 0, BufferAccess::ReadOnly, DataType::U32)
.with_count(tok_count),
BufferDecl::storage(tok_depths, 1, BufferAccess::ReadOnly, DataType::U32)
.with_count(tok_count),
BufferDecl::output(node_out, 2, DataType::U32).with_count(tok_count),
],
[256, 1, 1],
vec![wrap_anonymous(
"vyre-libs::parsing::opt_propagate_type_specifiers",
vec![child_phase(
"vyre-libs::parsing::opt_propagate_type_specifiers",
vyre_primitives::parsing::ssa_dominance_scan::OP_ID,
vec![Node::if_then(Expr::lt(t.clone(), num_tokens), loop_body)],
)],
)],
)
.with_entry_op_id("vyre-libs::parsing::opt_propagate_type_specifiers")
.with_non_composable_with_self(true)
}
fn any_token_eq(token: Expr, values: &[u32]) -> Expr {
values
.iter()
.copied()
.fold(Expr::bool(false), |acc, value| {
Expr::or(acc, Expr::eq(token.clone(), Expr::u32(value)))
})
}
fn is_propagatable_type_token(
token: Expr,
prev: Expr,
prev_prev: Expr,
allow_identifier_typedef: Expr,
) -> Expr {
Expr::or(
is_type_specifier(token.clone()),
Expr::and(
allow_identifier_typedef,
Expr::and(
Expr::eq(token, Expr::u32(TOK_IDENTIFIER)),
is_typedef_name_position(prev, prev_prev),
),
),
)
}
fn is_type_specifier(token: Expr) -> Expr {
any_token_eq(
token,
&[
TOK_INT,
TOK_CHAR_KW,
TOK_VOID,
TOK_STRUCT,
TOK_UNION,
TOK_ENUM,
TOK_FLOAT_KW,
TOK_DOUBLE,
TOK_SHORT,
TOK_LONG,
TOK_SIGNED,
TOK_UNSIGNED,
TOK_BOOL,
TOK_COMPLEX,
TOK_IMAGINARY,
TOK_ATOMIC,
TOK_GNU_TYPEOF,
TOK_GNU_TYPEOF_UNQUAL,
TOK_GNU_AUTO_TYPE,
TOK_GNU_INT128,
TOK_GNU_BUILTIN_VA_LIST,
TOK_BITINT_KW,
TOK_FLOAT16_KW,
TOK_FLOAT32_KW,
TOK_FLOAT64_KW,
TOK_FLOAT128_KW,
TOK_GNU_FLOAT128_KW,
TOK_GNU_BF16_KW,
TOK_GNU_FP16_KW,
TOK_DECIMAL32_KW,
TOK_DECIMAL64_KW,
TOK_DECIMAL128_KW,
],
)
}
fn is_typedef_name_position(prev: Expr, prev_prev: Expr) -> Expr {
Expr::and(
Expr::not(is_aggregate_tag_name(prev.clone(), prev_prev)),
Expr::or(
is_declaration_start(prev.clone()),
is_declaration_prefix(prev),
),
)
}
fn is_declaration_start(token: Expr) -> Expr {
any_token_eq(
token,
&[
TOK_EOF,
TOK_SEMICOLON,
TOK_COMMA,
TOK_LBRACE,
TOK_RBRACE,
TOK_LPAREN,
],
)
}
fn is_declaration_prefix(token: Expr) -> Expr {
any_token_eq(
token,
&[
TOK_TYPEDEF,
TOK_EXTERN,
TOK_STATIC,
TOK_AUTO,
TOK_REGISTER,
TOK_INLINE,
TOK_CONST,
TOK_VOLATILE,
TOK_RESTRICT,
TOK_ALIGNAS,
TOK_NORETURN,
TOK_THREAD_LOCAL,
TOK_GNU_EXTENSION,
TOK_GNU_TYPEOF,
TOK_GNU_TYPEOF_UNQUAL,
TOK_GNU_AUTO_TYPE,
TOK_GNU_INT128,
TOK_GNU_BUILTIN_VA_LIST,
TOK_GNU_ADDRESS_SPACE,
],
)
}
fn is_aggregate_body_open(prev: Expr, prev_prev: Expr) -> Expr {
Expr::or(
any_token_eq(prev.clone(), &[TOK_STRUCT, TOK_UNION, TOK_ENUM]),
is_aggregate_tag_name(prev, prev_prev),
)
}
fn is_aggregate_tag_name(prev: Expr, prev_prev: Expr) -> Expr {
Expr::and(
Expr::eq(prev, Expr::u32(TOK_IDENTIFIER)),
any_token_eq(prev_prev, &[TOK_STRUCT, TOK_UNION, TOK_ENUM]),
)
}
fn is_declaration_boundary(token: Expr, prev: Expr, prev_prev: Expr) -> Expr {
Expr::or(
any_token_eq(token.clone(), &[TOK_SEMICOLON, TOK_PREPROC]),
Expr::and(
Expr::eq(token, Expr::u32(TOK_LBRACE)),
Expr::not(is_aggregate_body_open(prev, prev_prev)),
),
)
}
inventory::submit! {
crate::harness::OpEntry {
id: "vyre-libs::parsing::opt_propagate_type_specifiers",
build: || opt_propagate_type_specifiers("tok_types", "tok_depths", "node_out", Expr::u32(1024)),
test_inputs: Some(|| {
let mut tok_types = vec![0u8; 4 * 1024];
let mut tok_depths = vec![0u8; 4 * 1024];
for (i, tok) in [
TOK_INT,
TOK_IDENTIFIER,
TOK_COMMA,
TOK_IDENTIFIER,
TOK_SEMICOLON,
TOK_CHAR_KW,
TOK_IDENTIFIER,
TOK_SEMICOLON,
]
.into_iter()
.enumerate()
{
tok_types[i * 4..i * 4 + 4].copy_from_slice(&tok.to_le_bytes());
tok_depths[i * 4..i * 4 + 4].copy_from_slice(&0u32.to_le_bytes());
}
vec![vec![tok_types, tok_depths, vec![0u8; 4 * 1024]]]
}),
expected_output: Some(|| {
let mut out = vec![0u8; 4 * 1024];
for (i, tok) in [
TOK_INT, TOK_INT, TOK_INT, TOK_INT, 0, TOK_CHAR_KW, TOK_CHAR_KW, 0,
]
.into_iter()
.enumerate()
{
out[i * 4..i * 4 + 4].copy_from_slice(&tok.to_le_bytes());
}
vec![vec![out]]
}),
category: Some("parsing"),
}
}