1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use std::{collections::HashMap, path::PathBuf};

use quote::quote;

use crate::kernel::lints::{parse_ptx_lint_level, LintLevel, PtxLint};

pub(super) struct LinkKernelConfig {
    pub(super) kernel: syn::Ident,
    pub(super) kernel_hash: syn::Ident,
    pub(super) crate_name: String,
    pub(super) crate_path: PathBuf,
    pub(super) specialisation: String,
    pub(super) ptx_lint_levels: HashMap<PtxLint, LintLevel>,
}

impl syn::parse::Parse for LinkKernelConfig {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        let kernel: syn::Ident = input.parse()?;
        let kernel_hash: syn::Ident = input.parse()?;
        let name: syn::LitStr = input.parse()?;
        let path: syn::LitStr = input.parse()?;

        let specialisation = if input.parse::<Option<syn::token::Lt>>()?.is_some() {
            if input.parse::<Option<syn::token::Gt>>()?.is_some() {
                String::new()
            } else {
                let specialisation_types = syn::punctuated::Punctuated::<
                    syn::Type,
                    syn::token::Comma,
                >::parse_separated_nonempty(input)?;

                let _gt_token: syn::token::Gt = input.parse()?;

                (quote! { <#specialisation_types> })
                    .to_string()
                    .replace(&[' ', '\n', '\t'][..], "")
            }
        } else {
            String::new()
        };

        let attrs = syn::punctuated::Punctuated::<
            syn::MetaList,
            syn::token::Comma,
        >::parse_separated_nonempty(input)?;

        let mut ptx_lint_levels = HashMap::new();

        for attr in attrs {
            parse_ptx_lint_level(&attr, &mut ptx_lint_levels);
        }

        proc_macro_error2::abort_if_dirty();

        Ok(Self {
            kernel,
            kernel_hash,
            crate_name: name.value(),
            crate_path: PathBuf::from(path.value()),
            specialisation,
            ptx_lint_levels,
        })
    }
}

pub(super) struct CheckKernelConfig {
    pub(super) kernel: syn::Ident,
    pub(super) kernel_hash: syn::Ident,
    pub(super) crate_name: String,
    pub(super) crate_path: PathBuf,
}

impl syn::parse::Parse for CheckKernelConfig {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        let kernel: syn::Ident = input.parse()?;
        let kernel_hash: syn::Ident = input.parse()?;
        let name: syn::LitStr = input.parse()?;
        let path: syn::LitStr = input.parse()?;

        Ok(Self {
            kernel,
            kernel_hash,
            crate_name: name.value(),
            crate_path: PathBuf::from(path.value()),
        })
    }
}