/// Generates the methods for parsing parameters of operand kind enumerants.
/// Returns a vector of tuples, with the first element being the enumerant
/// symbol, and the second element being a list of parameter kinds to that
/// enumerant.
Generates the methods for parsing parameters of operand kind enumerants.
Returns a vector of tuples, with the first element being the enumerant
symbol, and the second element being a list of parameter kinds to that
enumerant.
Generates the methods for parsing parameters of operand kind enumerants . Returns a vector of tuples with the first element being the enumerant symbol and the second element being a list of parameter kinds to that enumerant .
fn gen_operand_param_parse_methods(grammar: &[structs::OperandKind]) -> Vec<(&str, TokenStream)> {
    grammar.iter().filter(|element| {
        // Filter out all the operand kinds without any enumerants.
        !element.enumerants.is_empty()
    }).filter_map(|element| {
        // Get the symbol and all the parameters for each enumerant.
        let pairs: Vec<(&str, Vec<&str>)> = element.enumerants.iter()
            .scan(HashSet::new(), |seen_values, e| Some(if seen_values.insert(e.value) { Some(e) } else { None })).flatten()
            .filter_map(|e| {
                let params: Vec<&str> = e.parameters.iter().map(
                    |p| { p.kind.as_str() }
                ).collect();
                if params.is_empty() {
                    // Filter out enumerants without further parameters.
                    None
                } else {
                    Some((e.symbol.as_str(),  params))
                }
            }).collect();
        if pairs.is_empty() {
            // Skip those operand kinds that don't have parameters for
            // further parsing.
            return None
        }
        let kind = as_ident(&element.kind);
        let lo_kind = as_ident(&element.kind.to_snake_case());
        let function_name = as_ident(&format!("parse_{}_arguments", lo_kind));
        let method = if element.category == structs::Category::BitEnum {
            // For each operand kind in the BitEnum category, its
            // enumerants are bit masks. If a certain bit having associated
            // parameters is set, we also need to decode the corresponding
            // parameters. E.g., for MemoryAccess Aigned, an additional
            // LiteralInteger, which stands for the known alignment, should
            // be decoded.
            // Compose bit-set-clear check for each bit requiring
            // associated parameters.
            let cases = pairs.into_iter().map(|(symbol, params)| {
                let params = params.iter().map(|element| {
                    let op_kind = get_dr_operand_kind(element);
                    let decode = get_decode_method(element);
                    quote! { dr::Operand::#op_kind(self.decoder.#decode()?) }
                });
                let bit = as_ident(&symbol.to_shouty_snake_case());
                quote! {
                    if #lo_kind.contains(spirv::#kind::#bit) {
                        params.append(&mut vec![#(#params),*]);
                    }
                }
            });
            quote! {
                fn #function_name(&mut self, #lo_kind: spirv::#kind) -> Result<Vec<dr::Operand>> {
                    let mut params = vec![];
                    #(#cases)*
                    Ok(params)
                }
            }
        } else {  // ValueEnum
            let cases = pairs.into_iter().map(|(symbol, params)| {
                let params = params.iter().map(|element| {
                    let op_kind = get_dr_operand_kind(element);
                    let decode = get_decode_method(element);
                    quote! { dr::Operand::#op_kind(self.decoder.#decode()?) }
                });
                let symbol = as_ident(symbol);
                quote! {
                    spirv::#kind::#symbol => vec![#(#params),*]
                }
            });
            // TODO: filter duplicated symbols mapping to the same discriminator to avoid
            // unreachable patterns.
            quote! {
                #[allow(unreachable_patterns)]
                fn #function_name(&mut self, #lo_kind: spirv::#kind) -> Result<Vec<dr::Operand>> {
                    Ok(match #lo_kind {
                        #(#cases),*,
                        _ => vec![],
                    })
                }
            }
        };
        Some((element.kind.as_str(), method))
    }).collect()
}
fn gen_operand_param_parse_methods ( grammar : & [ structs :: OperandKind ] ) -> Vec < ( & str , TokenStream ) > { grammar . iter ( ) . filter ( | element | { // Filter out all the operand kinds without any enumerants. ! element . enumerants . is_empty ( ) } ) . filter_map ( | element | { // Get the symbol and all the parameters for each enumerant. let pairs : Vec < ( & str , Vec < & str > ) > = element . enumerants . iter ( ) . scan ( HashSet :: new ( ) , | seen_values , e | Some ( if seen_values . insert ( e . value ) { Some ( e ) } else { None } ) ) . flatten ( ) . filter_map ( | e | { let params : Vec < & str > = e . parameters . iter ( ) . map ( | p | { p . kind . as_str ( ) } ) . collect ( ) ; if params . is_empty ( ) { // Filter out enumerants without further parameters. None } else { Some ( ( e . symbol . as_str ( ) , params ) ) } } ) . collect ( ) ; if pairs . is_empty ( ) { // Skip those operand kinds that don't have parameters for // further parsing. return None } let kind = as_ident ( & element . kind ) ; let lo_kind = as_ident ( & element . kind . to_snake_case ( ) ) ; let function_name = as_ident ( & format ! ( " " lo_kind ) ) ; let method = if element . category == structs :: Category :: BitEnum { // For each operand kind in the BitEnum category, its // enumerants are bit masks. If a certain bit having associated // parameters is set, we also need to decode the corresponding // parameters. E.g., for MemoryAccess Aigned, an additional // LiteralInteger, which stands for the known alignment, should // be decoded. // Compose bit-set-clear check for each bit requiring // associated parameters. let cases = pairs . into_iter ( ) . map ( | ( symbol , params ) | { let params = params . iter ( ) . map ( | element | { let op_kind = get_dr_operand_kind ( element ) ; let decode = get_decode_method ( element ) ; quote ! { dr Operand op_kind ( self decoder decode ( ) ) } } ) ; let bit = as_ident ( & symbol . to_shouty_snake_case ( ) ) ; quote ! { if lo_kind contains ( spirv kind bit ) { params append ( mut vec [ ( params ) ] ) } } } ) ; quote ! { fn function_name ( mut self lo_kind spirv kind ) Result Vec dr Operand { let mut params vec [ ] ( cases ) Ok ( params ) } } } else { // ValueEnum let cases = pairs . into_iter ( ) . map ( | ( symbol , params ) | { let params = params . iter ( ) . map ( | element | { let op_kind = get_dr_operand_kind ( element ) ; let decode = get_decode_method ( element ) ; quote ! { dr Operand op_kind ( self decoder decode ( ) ) } } ) ; let symbol = as_ident ( symbol ) ; quote ! { spirv kind symbol vec [ ( params ) ] } } ) ; // TODO: filter duplicated symbols mapping to the same discriminator to avoid // unreachable patterns. quote ! { [ allow ( unreachable_patterns ) ] fn function_name ( mut self lo_kind spirv kind ) Result Vec dr Operand { Ok ( match lo_kind { ( cases ) vec [ ] } ) } } } ; Some ( ( element . kind . as_str ( ) , method ) ) } ) . collect ( ) }
Generates the methods for parsing parameters of operand kind enumerants.
Generates the methods for parsing parameters of operand kind enumerants .
grammar
&[structs::OperandKind]