Skip to content

Commit

Permalink
添加类型相关指令,提升性能
Browse files Browse the repository at this point in the history
update std
support var params
  • Loading branch information
limuy2022 committed Feb 14, 2024
1 parent 8a0dbf2 commit 1205443
Show file tree
Hide file tree
Showing 28 changed files with 983 additions and 553 deletions.
38 changes: 21 additions & 17 deletions rust/Cargo.lock

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

5 changes: 3 additions & 2 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ repository = "https://github.com/limuy2022/trc"

[dependencies]
rand = "0.8.5"
clap = { version = "4.4.18", features = ["derive"] }
clap = { version = "4.5.0", features = ["derive"] }
gettext-rs = "0.7.0"
colored = "2.1.0"
downcast-rs = "1.2.0"
num-bigint = "0.4.4"
llvm-sys = "170.0.1"
derive = { path = "./derive" }
libloading = "0.8.1"
stdlib = { path = "./stdlib" }

[profile.release]
panic = "abort"
Expand All @@ -27,4 +28,4 @@ codegen-units = 1
strip = true

[workspace]
members = ["derive", "."]
members = ["derive", ".", "stdlib"]
13 changes: 11 additions & 2 deletions rust/README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
# The rust version of Trc language

<!--toc:start-->

- [The rust version of Trc language](#the-rust-version-of-trc-language)
- [using language is 100% rust](#using-language-is-100-rust)
- [Build](#build)
- [How to use](#how-to-use)
- [Provide translation for this project](#provide-translation-for-this-project)
<!--toc:end-->

## using language is 100% rust

As a modern language,rust provide us a lot of useful features and I enjoy myself in it.So this project is developed by pure rust.

## Build

Like other common rust project.Just use ```cargo build```
Like other common rust project.Just use `cargo build`

Running tests is like other rust project,too.Just ```cargo test```
Running tests is like other rust project,too.Just `cargo test`
But in order to read test data file,please run in the root dir.

## How to use
Expand Down
10 changes: 3 additions & 7 deletions rust/derive/src/def_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,9 @@ pub fn lex_arrow(
}
}

fn check_next_iter(iter: &mut IntoIter, check_str: &str) {
if let Some(i) = iter.next() {
if let TokenTree::Punct(x) = i {
if x.to_string() != check_str {
panic!("expected {}", check_str);
}
} else {
pub fn check_next_iter(iter: &mut IntoIter, check_str: &str) {
if let Some(TokenTree::Punct(x), ..) = iter.next() {
if x.to_string() != check_str {
panic!("expected {}", check_str);
}
} else {
Expand Down
52 changes: 49 additions & 3 deletions rust/derive/src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,57 @@ pub fn process_function_def(sig: &mut Signature) -> (Vec<Stmt>, Vec<TypePath>, T
_ => unreachable!(),
};
// println!("argv:{:#?}", path);
if path.path.segments[0].ident == "any" {
let typename = path.path.to_token_stream().to_string();
if typename.ends_with("any") {
args_type_required.push(parse_str("AnyType").unwrap());
new_stmts.push(
parse_str::<Stmt>(&format!(
"let mut {} = dydata.obj_stack.pop().unwrap();",
r#"let mut {} = dydata.obj_stack.pop().expect("any empty");"#,
arg_name
))
.unwrap(),
);
} else if typename.ends_with("str") {
args_type_required.push(parse_str("TrcStr").unwrap());
new_stmts.push(
parse_str(&format!(
r#"let mut {} = dydata.str_stack.pop().expect("str empty");"#,
arg_name
))
.unwrap(),
);
} else if typename.ends_with("int") {
args_type_required.push(parse_str("TrcInt").unwrap());
new_stmts.push(
parse_str(&format!(
r#"let mut {} = dydata.int_stack.pop().expect("int empty");"#,
arg_name
))
.unwrap(),
);
} else if typename.ends_with("bool") {
args_type_required.push(parse_str("TrcBool").unwrap());
new_stmts.push(
parse_str(&format!(
r#"let mut {} = dydata.bool_stack.pop().expect("bool empty");"#,
arg_name
))
.unwrap(),
);
} else if typename.ends_with("char") {
args_type_required.push(parse_str("TrcChar").unwrap());
new_stmts.push(
parse_str(&format!(
r#"let mut {} = dydata.char_stack.pop().expect("char empty"");"#,
arg_name
))
.unwrap(),
);
} else if typename.ends_with("float") {
args_type_required.push(parse_str("TrcFloat").unwrap());
new_stmts.push(
parse_str(&format!(
r#"let mut {} = dydata.float_stack.pop().expect("float empty");"#,
arg_name
))
.unwrap(),
Expand All @@ -59,7 +105,7 @@ pub fn process_function_def(sig: &mut Signature) -> (Vec<Stmt>, Vec<TypePath>, T
args_type_required.push(path.clone());
new_stmts.push(
parse_str::<Stmt>(&format!(
"let mut {} = dydata.obj_stack.pop().unwrap().downcast::<{}>().unwrap();",
r#"let mut {} = dydata.obj_stack.pop().unwrap().downcast::<{}>().expect("obj empty");"#,
arg_name, path.to_token_stream()
))
.unwrap(),
Expand Down
78 changes: 65 additions & 13 deletions rust/derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use def_module::check_next_iter;
use function::process_function_def;
use proc_macro::TokenStream;
use proc_macro::{TokenStream, TokenTree};
use quote::{quote, ToTokens};
use syn::ImplItem;
use syn::{
Expand All @@ -10,11 +11,72 @@ mod def_module;
mod function;

#[proc_macro_attribute]
/// # warning
/// 返回值一定要加上return
/// # usage
/// 在开头加上#[trc_function]即可,想表示任意类型就用any表示,想表示返回值为空就用void表示(留空当然可以)
/// 对可变参数的支持在于,你可以通过指定var_params=true来支持可变参数,可变参数会附加到你的最后一个参数后面,类型是任意,我们会把它读取到va_list Vec里面
/// 如果你要表示这是一个类的方法,你不能直接加上这个,还需要添加参数method=true,而你的方法需要写成类似fn a(type s, int a){}这样,第一个参数是你定义到的类型
/// 在这里面写基础类型,需要以trc内部的名字书写,例如,你不能写TrcInt,而需要写int,但是书写别的类型需要以rust内部定义的名字类书写,例如,写Sam而不是sam
pub fn trc_function(attr: TokenStream, input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as ItemFn);
let (mut new_stmts, args_type_required, output) = process_function_def(&mut input.sig);
let name = input.sig.ident.clone();
let mut function_path: syn::Path = parse_str(&name.to_string()).unwrap();
let mut attr_iter = attr.into_iter();
let mut if_enable_var_params: syn::Expr = parse_str("false").unwrap();
while let Some(i) = attr_iter.next() {
match i {
TokenTree::Ident(ident_name) => {
let ident_name = ident_name.to_string();
if ident_name == "method" {
check_next_iter(&mut attr_iter, "=");
let bol = attr_iter.next().unwrap().to_string();
if bol == "true" {
function_path = parse_str(&format!("Self::{}", name)).unwrap();
} else if bol == "false" {
} else {
panic!("expected true or false, not {}", bol);
}
} else if ident_name == "var_params" {
check_next_iter(&mut attr_iter, "=");
let bol = attr_iter.next().unwrap().to_string();
if bol == "true" {
// 既然是可变参数,还要做一点手脚,可变参数是第一个到来的参数
if_enable_var_params = parse_str("true").unwrap();
let mut var_lex_tmp: Vec<Stmt> = vec![
parse_str("let mut va_list = vec![];").unwrap(),
parse_str("let args_num = dydata.int_stack.pop().unwrap() as usize;")
.unwrap(),
parse_str("va_list.reserve(args_num);").unwrap(),
parse_str(
r#"for i in 0..args_num {
va_list.push(dydata.obj_stack.pop().unwrap());
}"#,
)
.expect("Err on lex loop"),
];
// 将自己放到new_stmts的前面
var_lex_tmp.extend(new_stmts);
new_stmts = var_lex_tmp;
} else if bol == "false" {
} else {
panic!("expected true or false, not {}", bol);
}
} else {
panic!("unexpected:{}", ident_name);
}
}
TokenTree::Punct(sym) => {
if sym.to_string() == "," {
continue;
}
}
_ => {
panic!("unexpected:{}", i);
}
}
}
input.sig.output = parse_str::<syn::ReturnType>("-> RuntimeResult<()>").expect("err1");
let return_stmt = parse_str::<Stmt>("return Ok(());").expect("err2");
for i in input.block.stmts {
Expand Down Expand Up @@ -51,22 +113,13 @@ pub fn trc_function(attr: TokenStream, input: TokenStream) -> TokenStream {
let info_func_name =
parse_str::<Ident>(&function::convent_to_info_func(name.to_string())).expect("name error");
// println!("{}{:#?}", name.to_string(), info_function_self);
let function_path: syn::Path;
if let Some(ty) = attr.into_iter().next() {
if ty.to_string() == "true" {
function_path = parse_str(&format!("Self::{}", name)).unwrap();
} else {
function_path = parse_str(&name.to_string()).unwrap();
}
} else {
function_path = parse_str(&name.to_string()).unwrap();
}

let rettmp = quote!(#input
fn #info_func_name() -> RustFunction {
use crate::base::stdlib::*;
use crate::compiler::scope::TypeAllowNull;
let ret_classes = vec![#(#args_type_required::export_info()),*];
return RustFunction::new(stringify!(#name), #function_path, IOType::new(ret_classes, #output));
return RustFunction::new(stringify!(#name), #function_path, IOType::new(ret_classes, #output, #if_enable_var_params));
}
);
// println!("{}", rettmp.to_token_stream());
Expand Down Expand Up @@ -166,7 +219,6 @@ pub fn trc_class(_: TokenStream, input: TokenStream) -> TokenStream {

#[proc_macro_attribute]
/// 返回值一定要加上return
/// 定义一个函数体为空的函数会被当成接口声明,用于宏生成的接口
pub fn trc_method(_: TokenStream, input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemImpl);
// 生成一个function_export,返回一个vec,里面存着functions
Expand Down
27 changes: 27 additions & 0 deletions rust/docs/developer/function.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# function call rule

The order that values be pushed into the stack is the same as the order that you defined in your code.

So you can get function arguments like this:

If arguments is `a,b,c`

You should let valc = stack.pop().let valb = stack.pop(),let vala = stack.pop();

The order you read is opposite to the order you define.

You can define an interface class and use it to define your class.

by this way,we call the fuction by read the vtable.

We will store the functions in a table,no matter what is the kind of your function.

because we just allow one-depth class,so we just store a table like this:

A large table of different interface.A global alloc id of any class is the difference of this,

So we should first find the right interface of this.Then we should call the right function of the right interface.

By the following instructions,LOAD_INTERFACE XXX and CALL_METHOD XXX to call the right function.

The common method is just called by CALL_METHOD,so virtual function is slower than common function.
Loading

0 comments on commit 1205443

Please sign in to comment.