Skip to content

Commit

Permalink
用过程宏组织标准库
Browse files Browse the repository at this point in the history
  • Loading branch information
limuy2022 committed Feb 5, 2024
1 parent b30f3e8 commit 0b21bef
Show file tree
Hide file tree
Showing 24 changed files with 1,001 additions and 405 deletions.
5 changes: 1 addition & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,7 @@ testlog.log
*.a
*.exp
*.pdb
token.cpp
parser.cpp
parser.hpp
location.hh
tmp/

# 单元测试中的临时输出文件
*.out
22 changes: 16 additions & 6 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@ downcast-rs = "1.2.0"
lazy_static = "1.4.0"
num-bigint = "0.4.4"
reqwest = { version = "0.11.24", features = ["json", "multipart"] }
tokio = { version = "1.35.1", features = ["full"] }
tokio = { version = "1.36.0", features = ["full"] }
llvm-sys = "170.0.1"
derive = { path = "./derive" }

[profile.release]
panic = "abort"
lto = true
codegen-units = 1
strip = true

[workspace]
members = ["derive", "."]
14 changes: 14 additions & 0 deletions rust/derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "derive"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
syn = { version = "2.0.48", features = ["extra-traits", "full"] }
quote = "1.0.35"
proc-macro2 = "1.0.78"

[lib]
proc-macro = true
165 changes: 165 additions & 0 deletions rust/derive/src/def_module.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
use core::panic;
use proc_macro::{token_stream::IntoIter, TokenStream, TokenTree};
use quote::quote;

use crate::function;

pub fn lex_arrow(
left_push: &mut Vec<syn::Ident>,
right_push: &mut Vec<syn::Ident>,
iter: &mut IntoIter,
errormsg: &str,
) {
match iter.next().unwrap() {
proc_macro::TokenTree::Group(x, ..) => {
let mut left_name = TokenStream::new();
let mut right_name = TokenStream::new();
let mut control_which_put = false;
let mut iter = x.stream().into_iter();
while let Some(i) = iter.next() {
// println!("{}", i);
if let proc_macro::TokenTree::Punct(x) = i {
let x = x.to_string();
if x == "=" {
check_next_iter(&mut iter, ">");
// 切换左右边
control_which_put = true;
} else if x == "," {
// println!("item:{}", left_name);
left_push.push(syn::parse(left_name).expect("left push continue"));
right_push.push(syn::parse(right_name).expect("right push continue"));
left_name = TokenStream::new();
right_name = TokenStream::new();
control_which_put = false;
} else if x == "]" {
left_push.push(syn::parse(left_name).expect("left push break"));
right_push.push(syn::parse(right_name).expect("right push break"));
break;
}
} else {
if !control_which_put {
left_name.extend(std::iter::once(i));
} else {
right_name.extend(std::iter::once(i));
}
}
}
}
_ => {
panic!("{}", errormsg);
}
}
}

fn check_next_iter(iter: &mut IntoIter, check_str: &str) {
if let Some(i) = iter.next() {
if let proc_macro::TokenTree::Punct(x) = i {
if x.to_string() != check_str {
panic!("expected {}", check_str);
}
} else {
panic!("expected {}", check_str);
}
} else {
panic!("expected {}", check_str);
}
}

pub fn def_impl(content: TokenStream) -> TokenStream {
let mut module_ident = None;
let mut iter = content.into_iter();
let mut left_func = vec![];
let mut right_func = vec![];
let mut left_class = vec![];
let mut right_class = vec![];
let mut submodules = vec![];
while let Some(i) = iter.next() {
match i {
proc_macro::TokenTree::Ident(x) => {
let x = x.to_string();
if x == "module_name" {
check_next_iter(&mut iter, "=");
if let TokenTree::Ident(tmp) = iter.next().expect("name is expected") {
if let Some(_) = module_ident {
panic!("double defined");
}
module_ident =
Some(syn::parse_str::<syn::Ident>(&tmp.to_string()).unwrap());
} else {
panic!("name is expected");
}
} else if x == "functions" {
check_next_iter(&mut iter, "=");
lex_arrow(
&mut left_func,
&mut right_func,
&mut iter,
"functions are expected",
)
} else if x == "classes" {
check_next_iter(&mut iter, "=");
lex_arrow(
&mut left_class,
&mut right_class,
&mut iter,
"classes are expected",
);
} else if x == "submodules" {
check_next_iter(&mut iter, "=");
if let proc_macro::TokenTree::Group(x, ..) = iter.next().unwrap() {
// println!("{}", x);
let mut iter = x.stream().into_iter();
while let Some(i) = iter.next() {
if let proc_macro::TokenTree::Ident(x) = i {
submodules
.push(syn::parse_str::<syn::Ident>(&(x.to_string())).unwrap());
} else if let proc_macro::TokenTree::Ident(x) = i {
let x = x.to_string();
if x != "," {
panic!("expected ,.get {}", x);
} else if x == "]" {
break;
}
}
}
} else {
panic!("expected group")
}
}
}
proc_macro::TokenTree::Punct(x) => {
if x.to_string() != "," {
panic!("expected ,");
}
}
_ => {
panic!("grammar error unexpected {}", i.to_string());
}
}
}
for i in &mut left_func {
*i = syn::parse_str::<syn::Ident>(&function::convent_to_info_func(i.to_string()))
.expect("name error");
}
let ret = quote!(
pub fn init() -> Stdlib {
use crate::base::stdlib::Stdlib;
use std::collections::hash_map::HashMap;
let mut functions = HashMap::new();
let mut classes = HashMap::new();
#(
functions.insert(stringify!(#right_func).to_string(), #left_func());
)*
#(
classes.insert(stringify!(#right_class).to_string(), #left_class::export_info());
)*
Stdlib::new(
stringify!(#module_ident),
HashMap::new(),
functions,
classes
)
}
);
ret.into()
}
68 changes: 68 additions & 0 deletions rust/derive/src/function.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use syn::{
parse_str, punctuated, token::Comma, FnArg, PatType, ReturnType, Signature, Stmt, Type,
TypePath,
};

pub fn process_function_def(sig: &mut Signature) -> (Vec<Stmt>, Vec<TypePath>, Type) {
let output = sig.output.clone();
let output: Type = match output {
ReturnType::Default => parse_str("TypeAllowNull::No").unwrap(),
ReturnType::Type(_, ty) => {
if let Type::Path(name) = (*ty).clone() {
let tyname = name.path.segments[0].ident.to_string();
if tyname == "void" {
parse_str("TypeAllowNull::No").unwrap()
} else if tyname == "any" {
parse_str("ANY_TYPE").unwrap()
} else {
(*ty).clone()
}
} else {
(*ty).clone()
}
}
};
let input_args = sig.inputs.clone();
let mut new_stmts = vec![];
let mut new_args: punctuated::Punctuated<FnArg, Comma> = syn::punctuated::Punctuated::new();
// 第一个参数是self
if input_args.len() >= 1 {
if let FnArg::Receiver(_) = &input_args[0] {
new_args.push(input_args[0].clone());
}
}
let mut args_type_required = vec![];

new_args.push(parse_str::<FnArg>("dydata: &mut DynaData").unwrap());
sig.inputs = new_args;
for i in &input_args {
if let FnArg::Typed(PatType { pat, ty, .. }, ..) = i {
if let Type::Path(path, ..) = &**ty {
let arg_name = match &**pat {
syn::Pat::Ident(syn::PatIdent { ident, .. }) => ident.to_string(),
_ => unreachable!(),
};
// println!("argv:{:#?}", path);
if path.path.segments[0].ident.to_string() == "any" {
args_type_required.push(parse_str("ANY_TYPE").unwrap());
} else {
args_type_required.push(path.clone());
}
new_stmts.push(
parse_str::<Stmt>(&format!(
"let mut {} = dydata.obj_stack.pop().unwrap();",
arg_name
))
.unwrap(),
);
}
}
}
// 栈是反的
new_stmts.reverse();
(new_stmts, args_type_required, output)
}

pub fn convent_to_info_func(name: impl Into<String>) -> String {
format!("{}_info", name.into())
}
Loading

0 comments on commit 0b21bef

Please sign in to comment.