mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-03 07:04:34 +00:00
159 lines
6.2 KiB
Rust
159 lines
6.2 KiB
Rust
extern crate proc_macro;
|
|
use proc_macro::{Spacing, TokenStream};
|
|
use quote::ToTokens;
|
|
use sixtyfps_compilerlib::*;
|
|
|
|
fn fill_token_vec(stream: TokenStream, vec: &mut Vec<parser::Token>) {
|
|
let mut prev_spacing = Spacing::Alone;
|
|
for t in stream {
|
|
use parser::SyntaxKind;
|
|
use proc_macro::TokenTree;
|
|
|
|
match t {
|
|
TokenTree::Ident(i) => {
|
|
vec.push(parser::Token {
|
|
kind: SyntaxKind::Identifier,
|
|
text: i.to_string().into(),
|
|
span: Some(i.span()),
|
|
..Default::default()
|
|
});
|
|
}
|
|
TokenTree::Punct(p) => {
|
|
let kind = match p.as_char() {
|
|
':' => SyntaxKind::Colon,
|
|
'=' => {
|
|
if let Some(last) = vec.last_mut() {
|
|
if last.kind == SyntaxKind::Colon && prev_spacing == Spacing::Joint {
|
|
last.kind = SyntaxKind::ColonEqual;
|
|
last.text = ":=".into();
|
|
continue;
|
|
}
|
|
if last.kind == SyntaxKind::Plus && prev_spacing == Spacing::Joint {
|
|
last.kind = SyntaxKind::PlusEqual;
|
|
last.text = "+=".into();
|
|
continue;
|
|
}
|
|
if last.kind == SyntaxKind::Minus && prev_spacing == Spacing::Joint {
|
|
last.kind = SyntaxKind::MinusEqual;
|
|
last.text = "-=".into();
|
|
continue;
|
|
}
|
|
if last.kind == SyntaxKind::Div && prev_spacing == Spacing::Joint {
|
|
last.kind = SyntaxKind::DivEqual;
|
|
last.text = "/=".into();
|
|
continue;
|
|
}
|
|
if last.kind == SyntaxKind::Star && prev_spacing == Spacing::Joint {
|
|
last.kind = SyntaxKind::StarEqual;
|
|
last.text = "*=".into();
|
|
continue;
|
|
}
|
|
}
|
|
SyntaxKind::Equal
|
|
}
|
|
';' => SyntaxKind::Semicolon,
|
|
'!' => SyntaxKind::Bang,
|
|
'.' => SyntaxKind::Dot,
|
|
'+' => SyntaxKind::Plus,
|
|
'-' => SyntaxKind::Minus,
|
|
'*' => SyntaxKind::Star,
|
|
'/' => SyntaxKind::Div,
|
|
'<' => SyntaxKind::LAngle,
|
|
'>' => {
|
|
if let Some(last) = vec.last_mut() {
|
|
if last.kind == SyntaxKind::Equal && prev_spacing == Spacing::Joint {
|
|
last.kind = SyntaxKind::FatArrow;
|
|
last.text = "=>".into();
|
|
continue;
|
|
}
|
|
}
|
|
SyntaxKind::RAngle
|
|
}
|
|
'?' => SyntaxKind::Question,
|
|
_ => SyntaxKind::Error,
|
|
};
|
|
prev_spacing = p.spacing();
|
|
vec.push(parser::Token {
|
|
kind,
|
|
text: p.to_string().into(),
|
|
span: Some(p.span()),
|
|
..Default::default()
|
|
});
|
|
}
|
|
TokenTree::Literal(l) => {
|
|
let s = l.to_string();
|
|
// Why can't the rust API give me the type of the literal
|
|
let f = s.chars().next().unwrap();
|
|
let kind = if f == '"' {
|
|
SyntaxKind::StringLiteral
|
|
} else if f.is_digit(10) {
|
|
SyntaxKind::NumberLiteral
|
|
} else {
|
|
SyntaxKind::Error
|
|
};
|
|
vec.push(parser::Token {
|
|
kind,
|
|
text: s.into(),
|
|
span: Some(l.span()),
|
|
..Default::default()
|
|
});
|
|
}
|
|
TokenTree::Group(g) => {
|
|
use proc_macro::Delimiter::*;
|
|
use SyntaxKind::*;
|
|
let (l, r, sl, sr) = match g.delimiter() {
|
|
Parenthesis => (LParent, RParent, "(", ")"),
|
|
Brace => (LBrace, RBrace, "{", "}"),
|
|
Bracket => todo!(),
|
|
None => todo!(),
|
|
};
|
|
vec.push(parser::Token {
|
|
kind: l,
|
|
text: sl.into(),
|
|
span: Some(g.span()), // span_open is not stable
|
|
..Default::default()
|
|
});
|
|
fill_token_vec(g.stream(), vec);
|
|
vec.push(parser::Token {
|
|
kind: r,
|
|
text: sr.into(),
|
|
span: Some(g.span()), // span_clone is not stable
|
|
..Default::default()
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[proc_macro]
|
|
pub fn sixtyfps(stream: TokenStream) -> TokenStream {
|
|
let mut tokens = vec![];
|
|
fill_token_vec(stream, &mut tokens);
|
|
|
|
let (syntax_node, mut diag) = parser::parse_tokens(tokens.clone());
|
|
|
|
if let Some(cargo_manifest) = std::env::var_os("CARGO_MANIFEST_DIR") {
|
|
diag.current_path = cargo_manifest.into();
|
|
diag.current_path.push("Cargo.toml");
|
|
}
|
|
|
|
//println!("{:#?}", syntax_node);
|
|
let mut tr = typeregister::TypeRegister::builtin();
|
|
let tree = object_tree::Document::from_node(syntax_node, &mut diag, &mut tr);
|
|
let compiler_config = CompilerConfiguration::default();
|
|
run_passes(&tree, &mut diag, &mut tr, &compiler_config);
|
|
//println!("{:#?}", tree);
|
|
if diag.has_error() {
|
|
diag.map_offsets_to_span(&tokens);
|
|
return diag.into_token_stream().into();
|
|
}
|
|
|
|
let result = generator::rust::generate(&tree.root_component, &mut diag);
|
|
|
|
result
|
|
.unwrap_or_else(|| {
|
|
diag.map_offsets_to_span(&tokens);
|
|
diag.into_token_stream()
|
|
})
|
|
.into()
|
|
}
|