mv compiler to compiler/
This commit is contained in:
parent
db534b3ac2
commit
9e5f7d5631
1686 changed files with 941 additions and 1051 deletions
195
compiler/rustc_macros/src/symbols.rs
Normal file
195
compiler/rustc_macros/src/symbols.rs
Normal file
|
@ -0,0 +1,195 @@
|
|||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use std::collections::HashSet;
|
||||
use syn::parse::{Parse, ParseStream, Result};
|
||||
use syn::{braced, parse_macro_input, Ident, LitStr, Token};
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
mod kw {
|
||||
syn::custom_keyword!(Keywords);
|
||||
syn::custom_keyword!(Symbols);
|
||||
}
|
||||
|
||||
struct Keyword {
|
||||
name: Ident,
|
||||
value: LitStr,
|
||||
}
|
||||
|
||||
impl Parse for Keyword {
|
||||
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
||||
let name = input.parse()?;
|
||||
input.parse::<Token![:]>()?;
|
||||
let value = input.parse()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
|
||||
Ok(Keyword { name, value })
|
||||
}
|
||||
}
|
||||
|
||||
struct Symbol {
|
||||
name: Ident,
|
||||
value: Option<LitStr>,
|
||||
}
|
||||
|
||||
impl Parse for Symbol {
|
||||
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
||||
let name = input.parse()?;
|
||||
let value = match input.parse::<Token![:]>() {
|
||||
Ok(_) => Some(input.parse()?),
|
||||
Err(_) => None,
|
||||
};
|
||||
input.parse::<Token![,]>()?;
|
||||
|
||||
Ok(Symbol { name, value })
|
||||
}
|
||||
}
|
||||
|
||||
/// A type used to greedily parse another type until the input is empty.
|
||||
struct List<T>(Vec<T>);
|
||||
|
||||
impl<T: Parse> Parse for List<T> {
|
||||
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
||||
let mut list = Vec::new();
|
||||
while !input.is_empty() {
|
||||
list.push(input.parse()?);
|
||||
}
|
||||
Ok(List(list))
|
||||
}
|
||||
}
|
||||
|
||||
struct Input {
|
||||
keywords: List<Keyword>,
|
||||
symbols: List<Symbol>,
|
||||
}
|
||||
|
||||
impl Parse for Input {
|
||||
fn parse(input: ParseStream<'_>) -> Result<Self> {
|
||||
input.parse::<kw::Keywords>()?;
|
||||
let content;
|
||||
braced!(content in input);
|
||||
let keywords = content.parse()?;
|
||||
|
||||
input.parse::<kw::Symbols>()?;
|
||||
let content;
|
||||
braced!(content in input);
|
||||
let symbols = content.parse()?;
|
||||
|
||||
Ok(Input { keywords, symbols })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn symbols(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as Input);
|
||||
|
||||
let mut keyword_stream = quote! {};
|
||||
let mut symbols_stream = quote! {};
|
||||
let mut digits_stream = quote! {};
|
||||
let mut prefill_stream = quote! {};
|
||||
let mut counter = 0u32;
|
||||
let mut keys = HashSet::<String>::new();
|
||||
let mut prev_key: Option<String> = None;
|
||||
let mut errors = Vec::<String>::new();
|
||||
|
||||
let mut check_dup = |str: &str, errors: &mut Vec<String>| {
|
||||
if !keys.insert(str.to_string()) {
|
||||
errors.push(format!("Symbol `{}` is duplicated", str));
|
||||
}
|
||||
};
|
||||
|
||||
let mut check_order = |str: &str, errors: &mut Vec<String>| {
|
||||
if let Some(ref prev_str) = prev_key {
|
||||
if str < prev_str {
|
||||
errors.push(format!("Symbol `{}` must precede `{}`", str, prev_str));
|
||||
}
|
||||
}
|
||||
prev_key = Some(str.to_string());
|
||||
};
|
||||
|
||||
// Generate the listed keywords.
|
||||
for keyword in &input.keywords.0 {
|
||||
let name = &keyword.name;
|
||||
let value = &keyword.value;
|
||||
check_dup(&value.value(), &mut errors);
|
||||
prefill_stream.extend(quote! {
|
||||
#value,
|
||||
});
|
||||
keyword_stream.extend(quote! {
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const #name: Symbol = Symbol::new(#counter);
|
||||
});
|
||||
counter += 1;
|
||||
}
|
||||
|
||||
// Generate the listed symbols.
|
||||
for symbol in &input.symbols.0 {
|
||||
let name = &symbol.name;
|
||||
let value = match &symbol.value {
|
||||
Some(value) => value.value(),
|
||||
None => name.to_string(),
|
||||
};
|
||||
check_dup(&value, &mut errors);
|
||||
check_order(&name.to_string(), &mut errors);
|
||||
prefill_stream.extend(quote! {
|
||||
#value,
|
||||
});
|
||||
symbols_stream.extend(quote! {
|
||||
#[allow(rustc::default_hash_types)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const #name: Symbol = Symbol::new(#counter);
|
||||
});
|
||||
counter += 1;
|
||||
}
|
||||
|
||||
// Generate symbols for the strings "0", "1", ..., "9".
|
||||
for n in 0..10 {
|
||||
let n = n.to_string();
|
||||
check_dup(&n, &mut errors);
|
||||
prefill_stream.extend(quote! {
|
||||
#n,
|
||||
});
|
||||
digits_stream.extend(quote! {
|
||||
Symbol::new(#counter),
|
||||
});
|
||||
counter += 1;
|
||||
}
|
||||
|
||||
if !errors.is_empty() {
|
||||
for error in errors.into_iter() {
|
||||
eprintln!("error: {}", error)
|
||||
}
|
||||
panic!("errors in `Keywords` and/or `Symbols`");
|
||||
}
|
||||
|
||||
let tt = TokenStream::from(quote! {
|
||||
macro_rules! keywords {
|
||||
() => {
|
||||
#keyword_stream
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! define_symbols {
|
||||
() => {
|
||||
#symbols_stream
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const digits_array: &[Symbol; 10] = &[
|
||||
#digits_stream
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
impl Interner {
|
||||
pub fn fresh() -> Self {
|
||||
Interner::prefill(&[
|
||||
#prefill_stream
|
||||
])
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// To see the generated code generated, uncomment this line, recompile, and
|
||||
// run the resulting output through `rustfmt`.
|
||||
//eprintln!("{}", tt);
|
||||
|
||||
tt
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue