From 1205443c1474d8aaea311a1af4353767f4f2e0d5 Mon Sep 17 00:00:00 2001 From: limuy Date: Thu, 8 Feb 2024 11:01:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=B1=BB=E5=9E=8B=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=8C=87=E4=BB=A4=EF=BC=8C=E6=8F=90=E5=8D=87=E6=80=A7?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit update std support var params --- rust/Cargo.lock | 38 +- rust/Cargo.toml | 5 +- rust/README.md | 13 +- rust/derive/src/def_module.rs | 10 +- rust/derive/src/function.rs | 52 ++- rust/derive/src/lib.rs | 78 +++- rust/docs/developer/function.md | 27 ++ rust/docs/usage.md | 32 +- rust/locales/zh_CN/LC_MESSAGES/trans.mo | Bin 2100 -> 2313 bytes rust/locales/zh_CN/LC_MESSAGES/trans.po | 9 + rust/src/base/codegen.rs | 39 +- rust/src/base/error.rs | 3 + rust/src/base/stdlib.rs | 27 +- rust/src/compiler/ast.rs | 388 +++++++++++----- rust/src/compiler/llvm_convent.rs | 11 +- rust/src/compiler/scope.rs | 7 +- rust/src/compiler/token.rs | 92 +++- rust/src/tvm.rs | 549 ++++++++++------------- rust/src/tvm/stdlib/prelude.rs | 52 ++- rust/src/tvm/types.rs | 4 +- rust/src/tvm/types/data_structure/sam.rs | 6 +- rust/src/tvm/types/trcbool.rs | 8 +- rust/src/tvm/types/trcchar.rs | 2 +- rust/src/tvm/types/trcfloat.rs | 27 +- rust/src/tvm/types/trcint.rs | 43 +- rust/src/tvm/types/trcstr.rs | 4 +- rust/stdlib/Cargo.toml | 9 + rust/stdlib/src/lib.rs | 1 + 28 files changed, 983 insertions(+), 553 deletions(-) create mode 100644 rust/docs/developer/function.md create mode 100644 rust/stdlib/Cargo.toml create mode 100644 rust/stdlib/src/lib.rs diff --git a/rust/Cargo.lock b/rust/Cargo.lock index ec576af7..c9e2afc3 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -27,9 +27,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" @@ -94,9 +94,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.4.18" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +checksum = "80c21025abd42669a92efc996ef13cfb2c5c627858421ea58d5c3b331a6c134f" dependencies = [ "clap_builder", "clap_derive", @@ -104,9 +104,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.18" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +checksum = "458bf1f341769dfcf849846f65dffdf9146daa56bcd2a47cb4e1de9915567c99" dependencies = [ "anstream", "anstyle", @@ -116,9 +116,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" dependencies = [ "heck", "proc-macro2", @@ -128,9 +128,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "colorchoice" @@ -277,19 +277,18 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] @@ -418,11 +417,15 @@ version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +[[package]] +name = "stdlib" +version = "0.1.0" + [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" [[package]] name = "syn" @@ -454,6 +457,7 @@ dependencies = [ "llvm-sys", "num-bigint", "rand", + "stdlib", ] [[package]] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 196b31d5..b082f1a9 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -11,7 +11,7 @@ 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" @@ -19,6 +19,7 @@ num-bigint = "0.4.4" llvm-sys = "170.0.1" derive = { path = "./derive" } libloading = "0.8.1" +stdlib = { path = "./stdlib" } [profile.release] panic = "abort" @@ -27,4 +28,4 @@ codegen-units = 1 strip = true [workspace] -members = ["derive", "."] +members = ["derive", ".", "stdlib"] diff --git a/rust/README.md b/rust/README.md index 1afe4ea7..6f322739 100644 --- a/rust/README.md +++ b/rust/README.md @@ -1,14 +1,23 @@ # The rust version of Trc language + + +- [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) + + ## 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 diff --git a/rust/derive/src/def_module.rs b/rust/derive/src/def_module.rs index 0add8b6e..81484716 100644 --- a/rust/derive/src/def_module.rs +++ b/rust/derive/src/def_module.rs @@ -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 { diff --git a/rust/derive/src/function.rs b/rust/derive/src/function.rs index ab870dce..04d71f59 100644 --- a/rust/derive/src/function.rs +++ b/rust/derive/src/function.rs @@ -46,11 +46,57 @@ pub fn process_function_def(sig: &mut Signature) -> (Vec, Vec, 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::(&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(), @@ -59,7 +105,7 @@ pub fn process_function_def(sig: &mut Signature) -> (Vec, Vec, T args_type_required.push(path.clone()); new_stmts.push( parse_str::(&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(), diff --git a/rust/derive/src/lib.rs b/rust/derive/src/lib.rs index 3f1aef3d..a5233b9f 100644 --- a/rust/derive/src/lib.rs +++ b/rust/derive/src/lib.rs @@ -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::{ @@ -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 = 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::("-> RuntimeResult<()>").expect("err1"); let return_stmt = parse_str::("return Ok(());").expect("err2"); for i in input.block.stmts { @@ -51,22 +113,13 @@ pub fn trc_function(attr: TokenStream, input: TokenStream) -> TokenStream { let info_func_name = parse_str::(&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()); @@ -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 diff --git a/rust/docs/developer/function.md b/rust/docs/developer/function.md new file mode 100644 index 00000000..8f7842e9 --- /dev/null +++ b/rust/docs/developer/function.md @@ -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. diff --git a/rust/docs/usage.md b/rust/docs/usage.md index 793f968f..41a0bcaf 100644 --- a/rust/docs/usage.md +++ b/rust/docs/usage.md @@ -31,23 +31,23 @@ Tip3:The form like 001 is supported The next is the string value. To make you to write strings more easily: | Way | Explain | -|:------------------|:----------------------------------------------| +| :---------------- | :-------------------------------------------- | | "hello world" | commom value | -| 'hello_world' | another method that equals to "hello world" | +| 'h' | A way to store character | | """hello world""" | this method is for code across multiple lines | There are also many easape char in the string: | escape char | meaning | -|:------------|:----------------------------------| +| :---------- | :-------------------------------- | --- | | \t | tab | | \n | new line | -| \\\\|\| | | +| \\\\ | \| | | | \' | ' | | \" | " | | \0 | the tick of the end of the string | -If you add ```r``` or ```R``` in front of the string.Trc will treat it as a raw string. +If you add `r` or `R` in front of the string.Trc will treat it as a raw string. Yes.These rules are from Python.I love its grammar rules ok.now you know how to write value in Trc.Then let's go to the next part. @@ -59,14 +59,14 @@ the operators for basic types of trc is like others language. Here are the operator support | Operator | Explain | -|:---------|:-------------------------| +| :------- | :----------------------- | | + | addition | | - | subtraction | -| * | multiplication | +| \* | multiplication | | / | division | | // | divisible | | % | mod | -| ** | exponent | +| \*\* | exponent | | < | less than | | > | greater than | | <= | less than or equal to | @@ -83,9 +83,9 @@ Here are the operator support | >> | bit right shift | | ! | not | -Obviously,operators like ```+=``` is supported,too. +Obviously,operators like `+=` is supported,too. -But,something should be noticed is that you cannot use logical operators for ```int``` or anything else,just for bool. +But,something should be noticed is that you cannot use logical operators for `int` or anything else,just for bool. So,code like this cannot be compiled successfully: @@ -111,7 +111,7 @@ the compiler will report an error ## the control flow of Trc -First,you can use ```if ... else if ... else``` statements +First,you can use `if ... else if ... else` statements An example: @@ -125,7 +125,7 @@ if 1 == 1 { } ``` -```for``` support two kinds +`for` support two kinds First: @@ -143,15 +143,15 @@ for i in xxx { } ``` -```xxx``` should be a iterable var +`xxx` should be a iterable var ## the comments of Trc Trc support two kinds of comments -the first is use ```#```,from ```#``` to the end of the line belongs to the comment +the first is use `#`,from `#` to the end of the line belongs to the comment -the second is use ```/**/```,this kind can cross the line,like: +the second is use `/**/`,this kind can cross the line,like: ```cpp /* @@ -180,7 +180,7 @@ int a:=90 Std lib provide many kinds of data structures for Trc.Here is the list: | Structure | -|:-----------------| +| :--------------- | | St table | | suffix automaton | | ac automaton | diff --git a/rust/locales/zh_CN/LC_MESSAGES/trans.mo b/rust/locales/zh_CN/LC_MESSAGES/trans.mo index 31e9c9597a6dfd12202884ea54e66144e2d794cc..4815671868cfd5aa706c8a7c7bee1a4f934230fc 100644 GIT binary patch delta 872 zcmXxhO=uHA6u|LGn%LG>-NdS`wK`Zx>m`DEuon-0fnG!uya_c~-C&!@CW3e{7ZrpA z4_jO67rnFxQDR%6t%>xa=Lq6S@nSZyC#m2`6#s8`J23gp%x2!qd-KM45HEg+dBM<8n}z~kzjrvIK+0`6*2}JV9FY` zb>7O|982pfrY=~fzUuu`k7cf#dg#_r(n&|&8#$ Uz0%oy`ob-(tlcX+{T+S(0h1hv@c;k- delta 674 zcmX}py)T1N6vy$~S1mb|sQo97SE#&Y#|O;ty@u*UQ@>N+M7W+3B~dq-L~UHbIBubCc8VHP1ylHp zgZPO$STJC>)Fd3!s3}tCKbVT0L!DE1Ro^bI1Pa|$ZBwXSOu;@3HSB2TQ-@-9h6dO- z(VP|3Grg<<)(}gf1F9<;0h4IOTw!f*Bfq)3P_Q1|%heH2$z{EHYgWZ~Up?|)x~xp# J#`+G#{{ZU}Jd^+c diff --git a/rust/locales/zh_CN/LC_MESSAGES/trans.po b/rust/locales/zh_CN/LC_MESSAGES/trans.po index 6e993b61..4eff2fd6 100644 --- a/rust/locales/zh_CN/LC_MESSAGES/trans.po +++ b/rust/locales/zh_CN/LC_MESSAGES/trans.po @@ -83,3 +83,12 @@ msgstr "期望类型{}.但是传入类型是{}" msgid "unclosed comment" msgstr "未闭合的注释" +msgid "FormatStringError" +msgstr "格式化字符串错误" + +msgid "{ is not matched." +msgstr "{未匹配" + +msgid "char should be the format like 'x'." +msgstr "字符应当以类似'x'的格式书写." + diff --git a/rust/src/base/codegen.rs b/rust/src/base/codegen.rs index 1bcf3a35..14b369d4 100644 --- a/rust/src/base/codegen.rs +++ b/rust/src/base/codegen.rs @@ -2,7 +2,7 @@ use super::func; use core::cmp::max; use std::fmt::Display; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Opcode { Add, AddInt, @@ -17,8 +17,8 @@ pub enum Opcode { Div, DivInt, DivFloat, - ExtraDiv, - ExtraDivInt, + ExactDiv, + ExactDivInt, ExtraDivFloat, Mod, ModInt, @@ -66,8 +66,6 @@ pub enum Opcode { BitLeftShiftInt, BitRightShift, BitRightShiftInt, - // change pc counter - Goto, // return from a function PopFrame, // create a frame to hold the function @@ -81,7 +79,14 @@ pub enum Opcode { // Load a bigint from const pool LoadBigInt, // Load a local var to the stack + LoadChar, + LoadBool, LoadLocal, + MoveInt, + MoveFloat, + MoveChar, + MoveBool, + MoveStr, // Store a local var StoreLocal, // Do Nothing @@ -92,6 +97,8 @@ pub enum Opcode { SelfNegativeFloat, // call native func CallNative, + JumpIfFalse, + Jump, } impl Display for Opcode { @@ -110,9 +117,7 @@ pub struct ConstPool { impl ConstPool { pub fn new() -> Self { Self { - intpool: Vec::new(), - stringpool: Vec::new(), - floatpool: Vec::new(), + ..Default::default() } } } @@ -131,6 +136,17 @@ impl Inst { } } +#[derive(Clone, Copy)] +pub enum VmStackType { + Int, + Float, + Str, + Char, + Bool, + Object, +} + +#[derive(Default)] pub struct StaticData { pub constpool: ConstPool, pub inst: Vec, @@ -138,17 +154,14 @@ pub struct StaticData { pub sym_table_sz: usize, pub line_table: Vec, pub has_line_table: bool, + pub type_list: Vec>, } impl StaticData { pub fn new(has_line_table: bool) -> StaticData { Self { - constpool: ConstPool::new(), - inst: vec![], - funcs: vec![], - sym_table_sz: 0, - line_table: vec![], has_line_table, + ..Default::default() } } diff --git a/rust/src/base/error.rs b/rust/src/base/error.rs index b1ec4b9c..87711070 100644 --- a/rust/src/base/error.rs +++ b/rust/src/base/error.rs @@ -11,8 +11,10 @@ pub const NUMBER_OVER_FLOW: &str = "NumberOverFlowError"; pub const SYMBOL_ERROR: &str = "SymbolError"; pub const TYPE_ERROR: &str = "TypeError"; pub const ARGUMENT_ERROR: &str = "ArgumentError"; +pub const FORMAT_STR_ERROR: &str = "FormatStringError"; pub const STRING_WITHOUT_END: &str = "this string should be ended with {}"; +pub const CHAR_FORMAT: &str = "char should be the format like 'x'."; pub const UNMATCHED_BRACE: &str = "{} is unmatched"; pub const OPERATOR_IS_NOT_SUPPORT: &str = "operator {} is not supported for type {}"; pub const VM_DATA_NUMBER: &str = @@ -30,6 +32,7 @@ pub const TYPE_NOT_THE_SAME: &str = "Type {} and {} are not the same"; pub const ARGU_NUMBER: &str = "expect {}.But given {}"; pub const EXPECT_TYPE: &str = "Expect type {}.But given type {}"; pub const UNCLODED_COMMENT: &str = "unclosed comment"; +pub const UNCLOSED_FORMAT: &str = "{ is not matched."; #[derive(Debug)] pub struct ErrorInfo { diff --git a/rust/src/base/stdlib.rs b/rust/src/base/stdlib.rs index 09ca357c..efba0e24 100644 --- a/rust/src/base/stdlib.rs +++ b/rust/src/base/stdlib.rs @@ -1,4 +1,4 @@ -use super::error::*; +use super::{codegen::Opcode, error::*}; use crate::{ base::error::{ARGUMENT_ERROR, ARGU_NUMBER, EXPECT_TYPE}, compiler::{ @@ -19,6 +19,8 @@ const ANY_TYPE_ID: usize = 0; #[derive(Clone, Debug)] pub struct IOType { + // 如果有这个参数,代表在函数末尾是可变参数 + pub var_params: bool, pub argvs_type: Vec, pub return_type: TypeAllowNull, } @@ -32,10 +34,11 @@ pub struct RustFunction { } impl IOType { - pub fn new(argvs_type: Vec, return_type: TypeAllowNull) -> IOType { + pub fn new(argvs_type: Vec, return_type: TypeAllowNull, var_params: bool) -> IOType { IOType { argvs_type, return_type, + var_params, } } @@ -104,7 +107,7 @@ pub trait ClassInterface: Downcast + Sync + Send + ClassClone + Debug + Display self.get_id() == 0 } - fn get_override_func(&self, oper_token: TokenType) -> Option<&IOType>; + fn get_override_func(&self, oper_token: TokenType) -> Option<&OverrideWrapper>; } impl ClassClone for T @@ -134,11 +137,23 @@ impl FunctionInterface for RustFunction { } } +#[derive(Debug, Clone)] +pub struct OverrideWrapper { + pub opcode: Opcode, + pub io: IOType, +} + +impl OverrideWrapper { + pub fn new(opcode: Opcode, io: IOType) -> OverrideWrapper { + OverrideWrapper { opcode, io } + } +} + #[derive(Debug, Clone)] pub struct RustClass { pub members: HashMap, pub functions: HashMap, - pub overrides: HashMap, + pub overrides: HashMap, pub id: usize, pub name: &'static str, } @@ -149,7 +164,7 @@ impl RustClass { name: &'static str, members: HashMap, functions: Option>, - overrides: Option>, + overrides: Option>, id: usize, ) -> RustClass { RustClass { @@ -196,7 +211,7 @@ impl ClassInterface for RustClass { self.name } - fn get_override_func(&self, oper_token: TokenType) -> Option<&IOType> { + fn get_override_func(&self, oper_token: TokenType) -> Option<&OverrideWrapper> { match self.overrides.get(&oper_token) { Some(i) => Some(i), None => None, diff --git a/rust/src/compiler/ast.rs b/rust/src/compiler/ast.rs index a92aa879..ff47013c 100644 --- a/rust/src/compiler/ast.rs +++ b/rust/src/compiler/ast.rs @@ -1,17 +1,47 @@ use super::token::TokenType; -use super::TokenLex; +use super::{scope, TokenLex}; use super::{scope::*, InputSource}; -use crate::base::codegen::{Inst, Opcode, NO_ARG}; -use crate::base::stdlib::{get_stdlib, RustFunction}; +use crate::base::codegen::{Inst, Opcode, VmStackType, NO_ARG}; +use crate::base::func::Func; +use crate::base::stdlib::{get_stdlib, FunctionInterface, RustFunction}; use crate::base::{codegen::StaticData, error::*}; use gettextrs::gettext; +use std::borrow::Borrow; use std::cell::RefCell; use std::rc::Rc; +/// 过程间分析用的结构 +struct LexProcess { + stack_type: Vec, +} + +impl LexProcess { + pub fn new() -> Self { + Self { stack_type: vec![] } + } + + pub fn new_type(&mut self, ty: VmStackType) { + self.stack_type.push(ty); + } + + pub fn get_last_ty(&self) -> Option { + self.stack_type.last().copied() + } + + /// pop two val at the top of stack + pub fn cal_val(&mut self, ty: VmStackType) { + assert!(self.stack_type.len() >= 2); + self.stack_type.pop(); + self.stack_type.pop(); + self.new_type(ty) + } +} + pub struct AstBuilder<'a> { token_lexer: TokenLex<'a>, staticdata: StaticData, self_scope: Rc>, + process_info: LexProcess, } type AstError = RunResult; @@ -28,7 +58,7 @@ macro_rules! try_err { } macro_rules! tmp_expe_function_gen { - ($tmpfuncname:ident, $next_item_func:ident, $($accepted_token:path => $add_opcode:path),*) => { + ($tmpfuncname:ident, $next_item_func:ident, $($accepted_token:path),*) => { fn $tmpfuncname(&mut self, istry: bool, extend: usize) -> AstError { let next_sym = self.token_lexer.next_token()?; match next_sym.tp { @@ -46,7 +76,7 @@ macro_rules! tmp_expe_function_gen { ) ), Some(v) => { - if let Ok(_) = v.check_argvs(vec![tya]) {} + if let Ok(_) = v.io.check_argvs(vec![tya]) {} else { return try_err!(istry, Box::new(self.token_lexer.compiler_data.content.clone()), @@ -55,9 +85,10 @@ macro_rules! tmp_expe_function_gen { } } let io_check = io_check.unwrap(); - self.add_bycode($add_opcode, NO_ARG); - let stage_ty = io_check.return_type.unwrap(); + self.add_bycode(io_check.opcode.clone(), NO_ARG); + let stage_ty = io_check.io.return_type.unwrap(); let tyb = self.$tmpfuncname(istry, stage_ty)?; + self.process_info.cal_val(self.convert_to_vm_type(stage_ty)); match tyb { TypeAllowNull::No => { return Ok(TypeAllowNull::Yes(stage_ty)); @@ -78,8 +109,8 @@ macro_rules! tmp_expe_function_gen { /// there are a log of similar operators to be generated macro_rules! expr_gen { - ($funcname:ident, $tmpfuncname:ident, $next_item_func:ident, $($accepted_token:path => $add_opcode:path),*) => { - tmp_expe_function_gen!($tmpfuncname, $next_item_func, $($accepted_token => $add_opcode),*); + ($funcname:ident, $tmpfuncname:ident, $next_item_func:ident, $($accepted_token:path),*) => { + tmp_expe_function_gen!($tmpfuncname, $next_item_func, $($accepted_token),*); fn $funcname(&mut self, istry: bool) -> AstError { let t1 = self.$next_item_func(istry)?; if let TypeAllowNull::No = t1 { @@ -110,6 +141,7 @@ impl<'a> AstBuilder<'a> { token_lexer, staticdata: StaticData::new(!optimize), self_scope: root_scope, + process_info: LexProcess::new(), }; ret.self_scope .as_ref() @@ -118,27 +150,40 @@ impl<'a> AstBuilder<'a> { ret } - expr_gen!(expr9, expr9_, factor, TokenType::Power => Opcode::Power); - expr_gen!(expr8, expr8_, expr9, TokenType::Mul => Opcode::Mul, - TokenType::Div => Opcode::Div, - TokenType::Mod => Opcode::Mod, - TokenType::ExactDiv => Opcode::ExtraDiv); - expr_gen!(expr7, expr7_, expr8, TokenType::Add => Opcode::Add, - TokenType::Sub => Opcode::Sub); - expr_gen!(expr6, expr6_, expr7, TokenType::BitLeftShift => Opcode::BitLeftShift, - TokenType::BitRightShift => Opcode::BitRightShift); - expr_gen!(expr5, expr5_, expr6, TokenType::BitAnd => Opcode::BitAnd); - expr_gen!(expr4, expr4_, expr5, TokenType::Xor => Opcode::Xor); - expr_gen!(expr3, expr3_, expr4, TokenType::BitOr => Opcode::BitOr); - expr_gen!(expr2, expr2_, expr3, TokenType::Equal => Opcode::Eq, - TokenType::NotEqual => Opcode::Ne, - TokenType::Less => Opcode::Lt, - TokenType::LessEqual => Opcode::Le, - TokenType::Greater => Opcode::Gt, - TokenType::GreaterEqual => Opcode::Ge + expr_gen!(expr9, expr9_, factor, TokenType::Power); + expr_gen!( + expr8, + expr8_, + expr9, + TokenType::Mul, + TokenType::Div, + TokenType::Mod, + TokenType::ExactDiv ); - expr_gen!(expr1, expr1_, expr2, TokenType::And => Opcode::And); - expr_gen!(expr, expr_, expr1, TokenType::Or => Opcode::Or); + expr_gen!(expr7, expr7_, expr8, TokenType::Sub, TokenType::Add); + expr_gen!( + expr6, + expr6_, + expr7, + TokenType::BitLeftShift, + TokenType::BitRightShift + ); + expr_gen!(expr5, expr5_, expr6, TokenType::BitAnd); + expr_gen!(expr4, expr4_, expr5, TokenType::Xor); + expr_gen!(expr3, expr3_, expr4, TokenType::BitOr); + expr_gen!( + expr2, + expr2_, + expr3, + TokenType::Equal, + TokenType::NotEqual, + TokenType::Less, + TokenType::LessEqual, + TokenType::Greater, + TokenType::GreaterEqual + ); + expr_gen!(expr1, expr1_, expr2, TokenType::And); + expr_gen!(expr, expr_, expr1, TokenType::Or); pub fn return_static_data(mut self) -> StaticData { self.staticdata.constpool = self.token_lexer.compiler_data.const_pool.store_val_to_vm(); @@ -171,27 +216,95 @@ impl<'a> AstBuilder<'a> { Ok(()) } - fn opt_args(&mut self) -> AstError> { + /// 解析出函数参数 + fn opt_args(&mut self, lex_func_obj: &scope::Func) -> AstError> { let mut ret = vec![]; + let mut var_params_num = 0; + let io_tmp = lex_func_obj.get_io(); loop { let t = self.expr(true); match t { Err(_) => { + if io_tmp.var_params { + let tmp = self + .token_lexer + .compiler_data + .const_pool + .add_int(var_params_num); + self.add_bycode(Opcode::LoadInt, tmp); + } return Ok(ret); } Ok(ty) => match ty { TypeAllowNull::No => { + if io_tmp.var_params { + let tmp = self + .token_lexer + .compiler_data + .const_pool + .add_int(var_params_num); + self.add_bycode(Opcode::LoadInt, tmp); + } return Ok(ret); } - TypeAllowNull::Yes(t) => ret.push(t), + TypeAllowNull::Yes(t) => { + // 如果是可变参数是需要将其转入obj_stack的 + if io_tmp.var_params && io_tmp.argvs_type.len() <= ret.len() { + // the values that have been stored is more than exact requirement of function + self.move_val_into_obj_stack(); + var_params_num += 1; + } + ret.push(t) + } }, } } } + fn get_type_id(&self, ty_name: &str) -> usize { + self.self_scope.as_ref().borrow().get_type( + *self + .token_lexer + .compiler_data + .const_pool + .name_pool + .get(ty_name) + .unwrap(), + ) + } + + fn convert_to_vm_type(&self, ty: usize) -> VmStackType { + if ty == self.get_type_id("int") { + VmStackType::Int + } else if ty == self.get_type_id("float") { + VmStackType::Float + } else if ty == self.get_type_id("str") { + VmStackType::Str + } else if ty == self.get_type_id("char") { + VmStackType::Char + } else if ty == self.get_type_id("bool") { + VmStackType::Bool + } else { + VmStackType::Object + } + } + + fn move_val_into_obj_stack(&mut self) { + let obj_top = self.process_info.stack_type.pop().unwrap(); + match obj_top { + VmStackType::Int => self.add_bycode(Opcode::MoveInt, NO_ARG), + VmStackType::Float => self.add_bycode(Opcode::MoveFloat, NO_ARG), + VmStackType::Str => self.add_bycode(Opcode::MoveStr, NO_ARG), + VmStackType::Char => self.add_bycode(Opcode::MoveChar, NO_ARG), + VmStackType::Bool => self.add_bycode(Opcode::MoveBool, NO_ARG), + VmStackType::Object => {} + } + self.process_info.new_type(VmStackType::Object); + } + fn val(&mut self, istry: bool) -> AstError { let t = self.token_lexer.next_token()?; - return if t.tp == TokenType::ID { + if t.tp == TokenType::ID { let token_data = t.data.unwrap(); let idx = self.self_scope.as_ref().borrow().get_sym_idx(token_data); if idx.is_none() { @@ -210,11 +323,21 @@ impl<'a> AstBuilder<'a> { let idx = idx.unwrap(); let nxt = self.token_lexer.next_token()?; if nxt.tp == TokenType::LeftSmallBrace { - let argv_list = self.opt_args()?; + let func_obj = self.self_scope.as_ref().borrow().get_function(idx).unwrap(); + let argv_list = self.opt_args(&func_obj)?; // match ) self.check_next_token(TokenType::RightSmallBrace)?; - let tmp = self.self_scope.as_ref().borrow(); - let func_obj = tmp.get_function(idx).unwrap(); + // 阐明此处设计,首先我们的函数模板会以any的方式来占位,接下来调用的时候有几种情况,第一种就是入参有any,这种情况下我们会保留一份虚函数调用版本 + // 第二种情况就是入参有明确的类型 + // 接下来在这种情况的基础上再分两种情况 + // 第一种情况是自定义函数,这种情况下我们会像cpp模板那样对应生成版本 + // 第二种情况是rust函数,这种情况下我们只能记录类型,然后由rust函数自己判断从哪个栈中取出函数 + // 还有一种情况是any类型传入到函数中 + // 这种情况无论是哪种函数我们都会插入一条尝试转换类型的指令,将类型栈进行移动 + // 但是仅仅提供将其它类型移动到TrcObj的指令和从TrcObj转换到类型栈的函数 + // 类型之间会互相转换我们会以内置函数形式提供 + // 这是为了加速 + // 可变参数的话,因为类型不确定,我们会将其生成指令移入obj栈中 if let Err(e) = func_obj.get_io().check_argvs(argv_list) { return try_err!( istry, @@ -222,7 +345,6 @@ impl<'a> AstBuilder<'a> { e ); } - drop(tmp); if let Some(obj) = func_obj.downcast_ref::() { self.add_bycode(Opcode::CallNative, obj.buildin_id); } @@ -244,7 +366,7 @@ impl<'a> AstBuilder<'a> { gettextrs::gettext(SYNTAX_ERROR), ) ) - }; + } } fn item(&mut self, istry: bool) -> AstError { @@ -252,48 +374,31 @@ impl<'a> AstBuilder<'a> { return Ok(v); } let t = self.token_lexer.next_token()?; - return match t.tp { + match t.tp { TokenType::IntValue => { self.add_bycode(Opcode::LoadInt, t.data.unwrap()); - Ok(TypeAllowNull::Yes( - self.self_scope.as_ref().borrow().get_type( - *self - .token_lexer - .compiler_data - .const_pool - .name_pool - .get("int") - .unwrap(), - ), - )) + self.process_info.new_type(VmStackType::Int); + Ok(TypeAllowNull::Yes(self.get_type_id("int"))) } TokenType::FloatValue => { self.add_bycode(Opcode::LoadFloat, t.data.unwrap()); - Ok(TypeAllowNull::Yes( - self.self_scope.as_ref().borrow().get_type( - *self - .token_lexer - .compiler_data - .const_pool - .name_pool - .get("float") - .unwrap(), - ), - )) + self.process_info.new_type(VmStackType::Float); + Ok(TypeAllowNull::Yes(self.get_type_id("float"))) } TokenType::StringValue => { self.add_bycode(Opcode::LoadString, t.data.unwrap()); - Ok(TypeAllowNull::Yes( - self.self_scope.as_ref().borrow().get_type( - *self - .token_lexer - .compiler_data - .const_pool - .name_pool - .get("str") - .unwrap(), - ), - )) + self.process_info.new_type(VmStackType::Str); + Ok(TypeAllowNull::Yes(self.get_type_id("str"))) + } + TokenType::CharValue => { + self.add_bycode(Opcode::LoadChar, t.data.unwrap()); + self.process_info.new_type(VmStackType::Char); + Ok(TypeAllowNull::Yes(self.get_type_id("char"))) + } + TokenType::BoolValue => { + self.add_bycode(Opcode::LoadBool, t.data.unwrap()); + self.process_info.new_type(VmStackType::Bool); + Ok(TypeAllowNull::Yes(self.get_type_id("bool"))) } _ => { self.token_lexer.next_back(t.clone()); @@ -306,28 +411,68 @@ impl<'a> AstBuilder<'a> { ) ) } - }; + } + } + + fn unary_opcode_impl( + &mut self, + istry: bool, + optoken: TokenType, + valtype: usize, + ) -> AstError { + let class_obj = self + .self_scope + .as_ref() + .borrow() + .get_class(valtype) + .unwrap(); + let oride = class_obj.get_override_func(optoken.clone()); + match oride { + Some(v) => { + let tmp = v.io.check_argvs(vec![]); + match tmp { + Ok(_) => { + self.add_bycode(v.opcode.clone(), NO_ARG); + Ok(v.io.return_type.clone()) + } + Err(e) => { + try_err!( + istry, + Box::new(self.token_lexer.compiler_data.content.clone()), + e + ) + } + } + } + None => { + try_err!( + istry, + Box::new(self.token_lexer.compiler_data.content.clone()), + ErrorInfo::new( + gettext!(OPERATOR_IS_NOT_SUPPORT, optoken, class_obj.get_name()), + gettext(OPERATOR_ERROR), + ) + ) + } + } } fn factor(&mut self, istry: bool) -> AstError { let next_token = self.token_lexer.next_token()?; match next_token.tp { TokenType::Sub => { - let ret = self.factor(istry)?; - self.add_bycode(Opcode::SelfNegative, NO_ARG); - Ok(ret) + let ret = self.factor(istry)?.unwrap(); + self.unary_opcode_impl(istry, TokenType::SelfNegative, ret) } TokenType::BitNot => { - let ret = self.factor(istry)?; - self.add_bycode(Opcode::BitNot, NO_ARG); - Ok(ret) + let ret = self.factor(istry)?.unwrap(); + self.unary_opcode_impl(istry, TokenType::BitNot, ret) } TokenType::Not => { - let ret = self.factor(istry)?; - self.add_bycode(Opcode::Not, NO_ARG); - Ok(ret) + let ret = self.factor(istry)?.unwrap(); + self.unary_opcode_impl(istry, TokenType::Not, ret) } - TokenType::Add => Ok(self.factor(istry)?), + TokenType::Add => self.factor(istry), TokenType::LeftSmallBrace => { let ret = self.expr(istry)?; self.check_next_token(TokenType::RightSmallBrace)?; @@ -517,8 +662,8 @@ mod tests { vec![ Inst::new(Opcode::LoadInt, 2), Inst::new(Opcode::LoadInt, 3), - Inst::new(Opcode::BitNot, NO_ARG), - Inst::new(Opcode::Add, NO_ARG) + Inst::new(Opcode::BitNotInt, NO_ARG), + Inst::new(Opcode::AddInt, NO_ARG) ] ); } @@ -532,9 +677,9 @@ mod tests { vec![ Inst::new(Opcode::LoadInt, 2), Inst::new(Opcode::LoadInt, 3), - Inst::new(Opcode::Sub, NO_ARG), + Inst::new(Opcode::SubInt, NO_ARG), Inst::new(Opcode::LoadInt, 3), - Inst::new(Opcode::Sub, NO_ARG) + Inst::new(Opcode::SubInt, NO_ARG) ] ) } @@ -548,9 +693,9 @@ mod tests { vec![ Inst::new(Opcode::LoadInt, 2), Inst::new(Opcode::LoadInt, 3), - Inst::new(Opcode::Sub, NO_ARG), + Inst::new(Opcode::SubInt, NO_ARG), Inst::new(Opcode::LoadInt, 4), - Inst::new(Opcode::Mul, NO_ARG) + Inst::new(Opcode::MulInt, NO_ARG) ] ) } @@ -564,13 +709,13 @@ mod tests { vec![ Inst::new(Opcode::LoadInt, INT_VAL_POOL_ONE), Inst::new(Opcode::LoadInt, 2), - Inst::new(Opcode::Add, NO_ARG), + Inst::new(Opcode::AddInt, NO_ARG), Inst::new(Opcode::LoadInt, 3), Inst::new(Opcode::LoadInt, 4), Inst::new(Opcode::LoadInt, 5), - Inst::new(Opcode::Power, NO_ARG), - Inst::new(Opcode::Mul, NO_ARG), - Inst::new(Opcode::Sub, NO_ARG), + Inst::new(Opcode::PowerInt, NO_ARG), + Inst::new(Opcode::MulInt, NO_ARG), + Inst::new(Opcode::SubInt, NO_ARG), ] ); } @@ -584,24 +729,24 @@ mod tests { vec![ Inst::new(Opcode::LoadInt, INT_VAL_POOL_ONE), Inst::new(Opcode::LoadInt, 2), - Inst::new(Opcode::SelfNegative, NO_ARG), - Inst::new(Opcode::Add, NO_ARG), + Inst::new(Opcode::SelfNegativeInt, NO_ARG), + Inst::new(Opcode::AddInt, NO_ARG), Inst::new(Opcode::LoadInt, 3), - Inst::new(Opcode::Mul, NO_ARG), + Inst::new(Opcode::MulInt, NO_ARG), Inst::new(Opcode::LoadInt, 4), Inst::new(Opcode::LoadInt, 5), Inst::new(Opcode::LoadInt, 6), - Inst::new(Opcode::Power, NO_ARG), - Inst::new(Opcode::Power, NO_ARG), - Inst::new(Opcode::ExtraDiv, NO_ARG), + Inst::new(Opcode::PowerInt, NO_ARG), + Inst::new(Opcode::PowerInt, NO_ARG), + Inst::new(Opcode::ExactDivInt, NO_ARG), Inst::new(Opcode::LoadInt, 1), - Inst::new(Opcode::Eq, NO_ARG), + Inst::new(Opcode::EqInt, NO_ARG), Inst::new(Opcode::LoadInt, 7), Inst::new(Opcode::LoadInt, 8), Inst::new(Opcode::LoadInt, 9), - Inst::new(Opcode::BitAnd, NO_ARG), - Inst::new(Opcode::Eq, NO_ARG), - Inst::new(Opcode::Or, NO_ARG), + Inst::new(Opcode::BitAndInt, NO_ARG), + Inst::new(Opcode::EqInt, NO_ARG), + Inst::new(Opcode::OrBool, NO_ARG), ] ); } @@ -649,4 +794,43 @@ mod tests { gen_test_env!(r#""90"+28"#, t); t.generate_code().unwrap(); } + + #[test] + fn test_if() { + gen_test_env!( + r#"a:=9 +if a<8{ + +} else if a>11 { + +} else { +if 8 == 7 { + +} else { + +} +}"#, + t + ); + t.generate_code().unwrap(); + assert_eq!( + t.staticdata.inst, + vec![ + Inst::new(Opcode::LoadInt, 9), + Inst::new(Opcode::LoadInt, 8), + Inst::new(Opcode::LtInt, NO_ARG), + Inst::new(Opcode::JumpIfFalse, 0), + Inst::new(Opcode::LoadInt, 0), + Inst::new(Opcode::Jump, 0), + Inst::new(Opcode::LoadInt, 0), + Inst::new(Opcode::LoadInt, 11), + Inst::new(Opcode::GtInt, NO_ARG), + Inst::new(Opcode::JumpIfFalse, 0), + Inst::new(Opcode::LoadInt, 0), + Inst::new(Opcode::Jump, 0), + Inst::new(Opcode::LoadInt, 0), + Inst::new(Opcode::LoadInt, 7) + ] + ) + } } diff --git a/rust/src/compiler/llvm_convent.rs b/rust/src/compiler/llvm_convent.rs index 719067c0..e6e86c5d 100644 --- a/rust/src/compiler/llvm_convent.rs +++ b/rust/src/compiler/llvm_convent.rs @@ -1,4 +1,9 @@ -use llvm_sys::core::{LLVMContextCreate, LLVMCreateBuilderInContext, LLVMModuleCreateWithName}; +use std::ptr::null_mut; + +use llvm_sys::core::{ + LLVMAddFunction, LLVMContextCreate, LLVMCreateBuilderInContext, LLVMFunctionType, + LLVMInt32TypeInContext, LLVMModuleCreateWithName, +}; use crate::base::codegen::StaticData; @@ -7,5 +12,9 @@ pub fn convert(tvm_data: StaticData) { let context = LLVMContextCreate(); let module = LLVMModuleCreateWithName(b"main\0".as_ptr() as *const i8); let builder = LLVMCreateBuilderInContext(context); + let i32_ty = LLVMInt32TypeInContext(context); + // 创建main函数 + let main_ty = LLVMFunctionType(i32_ty, null_mut(), 0, 0); + let main_func = LLVMAddFunction(module, b"main\0".as_ptr() as *const _, main_ty); } } diff --git a/rust/src/compiler/scope.rs b/rust/src/compiler/scope.rs index b4d83395..1f5e9acb 100644 --- a/rust/src/compiler/scope.rs +++ b/rust/src/compiler/scope.rs @@ -1,7 +1,7 @@ use super::ValuePool; use crate::base::stdlib::{ - get_stdclass_end, get_stdlib, ClassInterface, FunctionInterface, IOType, Stdlib, - STD_CLASS_TABLE, + get_stdclass_end, get_stdlib, ClassInterface, FunctionInterface, IOType, OverrideWrapper, + Stdlib, STD_CLASS_TABLE, }; use std::{cell::RefCell, collections::HashMap, fmt::Display, rc::Rc}; @@ -72,6 +72,7 @@ impl Var { } pub type Type = Box; +pub type Func = Box; /// Manager of type #[derive(Clone, Debug)] @@ -134,7 +135,7 @@ impl ClassInterface for CommonType { &self.origin_name } - fn get_override_func(&self, oper_token: super::token::TokenType) -> Option<&IOType> { + fn get_override_func(&self, oper_token: super::token::TokenType) -> Option<&OverrideWrapper> { None } } diff --git a/rust/src/compiler/token.rs b/rust/src/compiler/token.rs index 7cf3adbf..8e3f3a13 100644 --- a/rust/src/compiler/token.rs +++ b/rust/src/compiler/token.rs @@ -1,8 +1,8 @@ use super::{Compiler, Content, Float}; use crate::{ base::error::{ - self, ErrorContent, ErrorInfo, RunResult, RuntimeError, FLOAT_OVER_FLOW, NUMBER_OVER_FLOW, - PREFIX_FOR_FLOAT, SYNTAX_ERROR, UNCLODED_COMMENT, + self, ErrorContent, ErrorInfo, RunResult, RuntimeError, CHAR_FORMAT, FLOAT_OVER_FLOW, + NUMBER_OVER_FLOW, PREFIX_FOR_FLOAT, SYNTAX_ERROR, UNCLODED_COMMENT, }, cfg::FLOAT_OVER_FLOW_LIMIT, hash_map, @@ -84,6 +84,8 @@ pub enum TokenType { StringValue, FloatValue, LongIntValue, + CharValue, + BoolValue, // ||= SelfOr, // &&= @@ -197,6 +199,8 @@ impl Display for TokenType { TokenType::SelfAnd => "&&=", TokenType::SelfOr => "||=", TokenType::SelfNegative => "-", + TokenType::CharValue => "char", + TokenType::BoolValue => "bool", }; write!(f, "{}", res) } @@ -329,10 +333,18 @@ impl TokenLex<'_> { let tmp = get_keywords().get(&retname); match tmp { Some(val) => Token::new((*val).clone(), None), - None => Token::new( - TokenType::ID, - Some(self.compiler_data.const_pool.add_id(retname)), - ), + None => { + if retname == "true" { + return Ok(Token::new(TokenType::BoolValue, Some(1))); + } + if retname == "false" { + return Ok(Token::new(TokenType::BoolValue, Some(0))); + } + Token::new( + TokenType::ID, + Some(self.compiler_data.const_pool.add_id(retname)), + ) + } } }) } @@ -369,14 +381,14 @@ impl TokenLex<'_> { matches!(c, ' ' | '\n' | '\t' | '\0') } - fn is_string_begin(c: char) -> bool { + fn is_string_or_char_begin(c: char) -> bool { matches!(c, '"' | '\'') } fn is_id_char(c: char) -> bool { !(Self::check_whether_symbol(c) || c.is_ascii_digit() - || Self::is_string_begin(c) + || Self::is_string_or_char_begin(c) || Self::is_useless_char(c)) } @@ -701,10 +713,10 @@ impl TokenLex<'_> { } } - fn lex_str(&mut self, start_char: char) -> RunResult { + fn lex_str(&mut self) -> RunResult { let mut s = String::new(); let mut c = self.compiler_data.input.read(); - while c != start_char { + while c != '"' { if c == '\\' { c = self.compiler_data.input.read(); c = match c { @@ -726,7 +738,7 @@ impl TokenLex<'_> { RuntimeError::new( Box::new(self.compiler_data.content.clone()), ErrorInfo::new( - gettext!(error::STRING_WITHOUT_END, start_char), + gettext!(error::STRING_WITHOUT_END, '"'), gettext(SYNTAX_ERROR), ), ); @@ -738,6 +750,18 @@ impl TokenLex<'_> { )) } + fn lex_char(&mut self) -> RunResult { + let c = self.compiler_data.input.read(); + let end = self.compiler_data.input.read(); + if end != '\'' { + return Err(RuntimeError::new( + Box::new(self.compiler_data.content.clone()), + ErrorInfo::new(gettext(CHAR_FORMAT), gettext(SYNTAX_ERROR)), + )); + } + Ok(Token::new(TokenType::CharValue, Some(c as usize))) + } + pub fn next_token(&mut self) -> RunResult { if !self.unget_token.is_empty() { let tmp = self.unget_token.pop().unwrap(); @@ -773,8 +797,11 @@ impl TokenLex<'_> { if presecnt_lex.is_ascii_digit() { return self.lex_num(presecnt_lex); } - if Self::is_string_begin(presecnt_lex) { - return self.lex_str(presecnt_lex); + if presecnt_lex == '"' { + return self.lex_str(); + } + if presecnt_lex == '\'' { + return self.lex_char(); } if Self::check_whether_symbol(presecnt_lex) { return self.lex_symbol(presecnt_lex); @@ -980,23 +1007,22 @@ mod tests { #[test] fn test_string_lex() { - gen_test_token_env!(r#""s"'sd''sdscdcdfvf'"depkd"''"\n\t"'ttt\tt'"#, t); + gen_test_token_env!(r#""s"'s'"sdscdcdfvf""depkd""""\n\t""ttt\tt""#, t); check( &mut t, vec![ Token::new(TokenType::StringValue, Some(0)), + Token::new(TokenType::CharValue, Some('s' as usize)), Token::new(TokenType::StringValue, Some(1)), Token::new(TokenType::StringValue, Some(2)), Token::new(TokenType::StringValue, Some(3)), Token::new(TokenType::StringValue, Some(4)), Token::new(TokenType::StringValue, Some(5)), - Token::new(TokenType::StringValue, Some(6)), ], ); check_pool( vec![ String::from("s"), - String::from("sd"), String::from("sdscdcdfvf"), String::from("depkd"), String::from(""), @@ -1160,6 +1186,40 @@ func main() { ); } + #[test] + #[should_panic(expected = "SyntaxError")] + fn test_wrong_char1() { + gen_test_token_env!(r#"''"#, t); + t.next_token().unwrap(); + } + + #[test] + #[should_panic(expected = "SyntaxError")] + fn test_wrong_char2() { + gen_test_token_env!(r#"'sasa'"#, t); + t.next_token().unwrap(); + } + + #[test] + #[should_panic(expected = "SyntaxError")] + fn test_wrong_char3() { + gen_test_token_env!(r#"'"#, t); + t.next_token().unwrap(); + } + + #[test] + fn test_bool() { + gen_test_token_env!(r#"true tru false"#, t); + check( + &mut t, + vec![ + Token::new(TokenType::BoolValue, Some(1)), + Token::new(TokenType::ID, Some(0)), + Token::new(TokenType::BoolValue, Some(0)), + ], + ) + } + #[test] #[should_panic] fn test_braces_check2() { diff --git a/rust/src/tvm.rs b/rust/src/tvm.rs index a2211204..ca70451b 100644 --- a/rust/src/tvm.rs +++ b/rust/src/tvm.rs @@ -9,7 +9,7 @@ use self::types::trcfloat::{div_float, exact_div_float, TrcFloat}; use self::types::trcint::{div_int, exact_div_int, mod_int, power_int, TrcInt}; use self::types::trcstr::TrcStr; use self::types::{TrcBool, TrcChar, TrcObj}; -use crate::base::codegen::{self, StaticData}; +use crate::base::codegen::{self, Opcode, StaticData}; use crate::base::stdlib::STD_FUNC_TABLE; use crate::{base::error::*, cfg}; use gettextrs::gettext; @@ -18,19 +18,23 @@ use libloading::Library; #[derive(Default)] pub struct DynaData<'a> { obj_stack: Vec>, + int_stack: Vec, + str_stack: Vec, + float_stack: Vec, + bool_stack: Vec, + char_stack: Vec, frames_stack: Vec>, } impl<'a> DynaData<'a> { pub fn new() -> Self { Self { - obj_stack: Vec::new(), - frames_stack: vec![], + ..Default::default() } } - pub fn check_stack(&self, require: usize) -> RuntimeResult<()> { - if self.obj_stack.len() < require { + pub fn check_stack(obj: &[T], require: usize) -> RuntimeResult<()> { + if obj.len() < require { return Err(ErrorInfo::new( gettext!(VM_DATA_NUMBER, require), gettext(VM_ERROR), @@ -135,6 +139,27 @@ macro_rules! operator_opcode { } }}; } +macro_rules! impl_opcode { + ($obj_stack:expr, $sself:expr, 2) => {{ + let tmp = DynaData::check_stack(&$obj_stack, 2); + $sself.throw_err_info(tmp)?; + let second = $obj_stack.pop().unwrap(); + let first = $obj_stack.pop().unwrap(); + (first, second) + }}; + ($obj_stack:expr, $sself:expr, 1) => {{ + let tmp = DynaData::check_stack(&$obj_stack, 1); + $sself.throw_err_info(tmp)?; + let first = $obj_stack.pop().unwrap(); + (first) + }}; +} + +impl Default for Vm<'_> { + fn default() -> Self { + Self::new() + } +} impl<'a> Vm<'a> { pub fn new() -> Self { @@ -146,40 +171,7 @@ impl<'a> Vm<'a> { } } - pub fn impl_ty_opcode(&mut self) -> RunResult<(Box, Box)> { - let tmp = self.dynadata.check_stack(2); - self.throw_err_info(tmp)?; - let second = self - .dynadata - .obj_stack - .pop() - .unwrap() - .downcast::() - .unwrap(); - let first = self - .dynadata - .obj_stack - .pop() - .unwrap() - .downcast::() - .unwrap(); - Ok((first, second)) - } - - pub fn impl_unary_opcode(&mut self) -> RunResult> { - let tmp = self.dynadata.check_stack(1); - self.throw_err_info(tmp)?; - let first = self - .dynadata - .obj_stack - .pop() - .unwrap() - .downcast::() - .unwrap(); - Ok(first) - } - - pub fn new_init(static_data: StaticData) -> Self { + fn new_init(static_data: StaticData) -> Self { Self { pc: 0, dynadata: DynaData::new(), @@ -192,7 +184,7 @@ impl<'a> Vm<'a> { self.static_data = static_data; } - pub fn throw_err_info(&self, info: RuntimeResult) -> RunResult { + fn throw_err_info(&self, info: RuntimeResult) -> RunResult { match info { Ok(data) => Ok(data), Err(e) => Err(RuntimeError::new(Box::new(self.run_contnet.clone()), e)), @@ -206,325 +198,282 @@ impl<'a> Vm<'a> { .set_line(self.static_data.line_table[self.pc]); } match self.static_data.inst[self.pc].opcode { - codegen::Opcode::Add => operator_opcode!(add, self), - codegen::Opcode::Sub => operator_opcode!(sub, self), - codegen::Opcode::Mul => operator_opcode!(mul, self), - codegen::Opcode::Div => operator_opcode!(div, self), - codegen::Opcode::ExtraDiv => operator_opcode!(extra_div, self), - codegen::Opcode::Mod => operator_opcode!(modd, self), - codegen::Opcode::Gt => operator_opcode!(gt, self), - codegen::Opcode::Lt => operator_opcode!(lt, self), - codegen::Opcode::Ge => operator_opcode!(ge, self), - codegen::Opcode::Le => operator_opcode!(le, self), - codegen::Opcode::Eq => operator_opcode!(eq, self), - codegen::Opcode::Ne => operator_opcode!(ne, self), - codegen::Opcode::And => operator_opcode!(and, self), - codegen::Opcode::Or => operator_opcode!(or, self), - codegen::Opcode::Power => operator_opcode!(power, self), - codegen::Opcode::Not => operator_opcode!(not, self), - codegen::Opcode::Xor => operator_opcode!(xor, self), - codegen::Opcode::NewFrame => {} - codegen::Opcode::PopFrame => { + Opcode::Add => operator_opcode!(add, self), + Opcode::Sub => operator_opcode!(sub, self), + Opcode::Mul => operator_opcode!(mul, self), + Opcode::Div => operator_opcode!(div, self), + Opcode::ExactDiv => operator_opcode!(extra_div, self), + Opcode::Mod => operator_opcode!(modd, self), + Opcode::Gt => operator_opcode!(gt, self), + Opcode::Lt => operator_opcode!(lt, self), + Opcode::Ge => operator_opcode!(ge, self), + Opcode::Le => operator_opcode!(le, self), + Opcode::Eq => operator_opcode!(eq, self), + Opcode::Ne => { + operator_opcode!(ne, self) + } + Opcode::And => operator_opcode!(and, self), + Opcode::Or => operator_opcode!(or, self), + Opcode::Power => operator_opcode!(power, self), + Opcode::Not => operator_opcode!(not, self), + Opcode::Xor => operator_opcode!(xor, self), + Opcode::NewFrame => {} + Opcode::PopFrame => { let ret = self.dynadata.frames_stack.pop(); - if let None = ret { + if ret.is_none() { return Err(RuntimeError::new( Box::new(self.run_contnet.clone()), ErrorInfo::new(gettext(VM_FRAME_EMPTY), gettext(VM_ERROR)), )); } } - codegen::Opcode::Goto => { - self.pc = self.static_data.inst[self.pc].operand; - } - codegen::Opcode::LoadInt => { - self.dynadata.obj_stack.push(Box::new(TrcInt::new( + Opcode::LoadInt => { + self.dynadata.int_stack.push( self.static_data.constpool.intpool[self.static_data.inst[self.pc].operand], - ))); - } - codegen::Opcode::BitAnd => operator_opcode!(bit_and, self), - codegen::Opcode::BitOr => operator_opcode!(bit_or, self), - codegen::Opcode::BitNot => operator_opcode!(bit_not, self), - codegen::Opcode::BitLeftShift => operator_opcode!(bit_left_shift, self), - codegen::Opcode::BitRightShift => operator_opcode!(bit_right_shift, self), - codegen::Opcode::LoadLocal => {} - codegen::Opcode::StoreLocal => {} - codegen::Opcode::LoadString => { - self.dynadata.obj_stack.push(Box::new(TrcStr::new( + ); + } + Opcode::BitAnd => operator_opcode!(bit_and, self), + Opcode::BitOr => operator_opcode!(bit_or, self), + Opcode::BitNot => operator_opcode!(bit_not, self), + Opcode::BitLeftShift => operator_opcode!(bit_left_shift, self), + Opcode::BitRightShift => operator_opcode!(bit_right_shift, self), + Opcode::LoadLocal => {} + Opcode::StoreLocal => {} + Opcode::LoadString => { + self.dynadata.str_stack.push( self.static_data.constpool.stringpool [self.static_data.inst[self.pc].operand] .clone(), - ))); + ); } - codegen::Opcode::LoadFloat => { - self.dynadata.obj_stack.push(Box::new(TrcFloat::new( + Opcode::LoadFloat => { + self.dynadata.float_stack.push( self.static_data.constpool.floatpool [self.static_data.inst[self.pc].operand], - ))); + ); } - codegen::Opcode::LoadBigInt => {} - codegen::Opcode::Empty => {} - codegen::Opcode::SelfNegative => { + Opcode::LoadBigInt => {} + Opcode::Empty => {} + Opcode::SelfNegative => { operator_opcode!(self_negative, self); } - codegen::Opcode::CallNative => unsafe { + Opcode::CallNative => unsafe { let tmp = STD_FUNC_TABLE[self.static_data.inst[self.pc].operand](&mut self.dynadata); self.throw_err_info(tmp)?; }, - codegen::Opcode::AddInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcInt::new(first._value + second._value))); + Opcode::AddInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); + self.dynadata.int_stack.push(first + second); } - codegen::Opcode::AddFloat => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcFloat::new(first._value + second._value))); - } - codegen::Opcode::AddStr => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata.obj_stack.push(Box::new(TrcStr::new(format!( - "{}{}", - first._value, second._value - )))); - } - codegen::Opcode::SubInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcInt::new(first._value - second._value))); + Opcode::AddFloat => { + let (first, second) = impl_opcode!(self.dynadata.float_stack, self, 2); + self.dynadata.float_stack.push(first + second); } - codegen::Opcode::SubFloat => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcFloat::new(first._value - second._value))); + Opcode::AddStr => { + let (first, second) = impl_opcode!(self.dynadata.str_stack, self, 2); + self.dynadata.str_stack.push(format!("{}{}", first, second)); } - codegen::Opcode::MulInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcInt::new(first._value * second._value))); + Opcode::SubInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); + self.dynadata.int_stack.push(first - second); } - codegen::Opcode::MulFloat => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcFloat::new(first._value * second._value))); - } - codegen::Opcode::DivInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata.obj_stack.push(Box::new(TrcFloat::new( - self.throw_err_info(div_int(first._value, second._value))?, - ))); - } - codegen::Opcode::DivFloat => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata.obj_stack.push(Box::new(TrcFloat::new( - self.throw_err_info(div_float(first._value, second._value))?, - ))); - } - codegen::Opcode::ExtraDivInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata.obj_stack.push(Box::new(TrcInt::new( - self.throw_err_info(exact_div_int(first._value, second._value))?, - ))); - } - codegen::Opcode::ExtraDivFloat => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata.obj_stack.push(Box::new(TrcInt::new( - self.throw_err_info(exact_div_float(first._value, second._value))?, - ))); - } - codegen::Opcode::ModInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata.obj_stack.push(Box::new(TrcInt::new( - self.throw_err_info(mod_int(first._value, second._value))?, - ))); - } - codegen::Opcode::PowerInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata.obj_stack.push(Box::new(TrcInt::new(power_int( - first._value, - second._value, - )))); - } - codegen::Opcode::EqInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value == second._value))); + Opcode::SubFloat => { + let (first, second) = impl_opcode!(self.dynadata.float_stack, self, 2); + self.dynadata.float_stack.push(first - second); } - codegen::Opcode::EqFloat => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value == second._value))); + Opcode::MulInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); + self.dynadata.int_stack.push(first * second); } - codegen::Opcode::EqStr => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value == second._value))); + Opcode::MulFloat => { + let (first, second) = impl_opcode!(self.dynadata.float_stack, self, 2); + self.dynadata.float_stack.push(first * second); } - codegen::Opcode::EqChar => { - let (first, second) = self.impl_ty_opcode::()?; + Opcode::DivInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value == second._value))); + .float_stack + .push(self.throw_err_info(div_int(first, second))?); } - codegen::Opcode::EqBool => { - let (first, second) = self.impl_ty_opcode::()?; + Opcode::DivFloat => { + let (first, second) = impl_opcode!(self.dynadata.float_stack, self, 2); self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value == second._value))); + .float_stack + .push(self.throw_err_info(div_float(first, second))?); } - codegen::Opcode::NeInt => { - let (first, second) = self.impl_ty_opcode::()?; + Opcode::ExactDivInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value != second._value))); + .int_stack + .push(self.throw_err_info(exact_div_int(first, second))?); } - codegen::Opcode::NeFloat => { - let (first, second) = self.impl_ty_opcode::()?; + Opcode::ExtraDivFloat => { + let (first, second) = impl_opcode!(self.dynadata.float_stack, self, 2); self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value != second._value))); + .int_stack + .push(self.throw_err_info(exact_div_float(first, second))?); } - codegen::Opcode::NeStr => { - let (first, second) = self.impl_ty_opcode::()?; + Opcode::ModInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value != second._value))); + .int_stack + .push(self.throw_err_info(mod_int(first, second))?); } - codegen::Opcode::NeChar => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value != second._value))); + Opcode::PowerInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); + self.dynadata.int_stack.push(power_int(first, second)); } - codegen::Opcode::NeBool => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value != second._value))); + Opcode::EqInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); + self.dynadata.bool_stack.push(first == second); } - codegen::Opcode::LtInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value < second._value))); + Opcode::EqFloat => { + let (first, second) = impl_opcode!(self.dynadata.float_stack, self, 2); + self.dynadata.bool_stack.push(first == second); } - codegen::Opcode::LtFloat => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value < second._value))); + Opcode::EqStr => { + let (first, second) = impl_opcode!(self.dynadata.str_stack, self, 2); + self.dynadata.bool_stack.push(first == second); } - codegen::Opcode::LeInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value <= second._value))); + Opcode::EqChar => { + let (first, second) = impl_opcode!(self.dynadata.char_stack, self, 2); + self.dynadata.bool_stack.push(first == second); } - codegen::Opcode::LeFloat => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value <= second._value))); + Opcode::EqBool => { + let (first, second) = impl_opcode!(self.dynadata.bool_stack, self, 2); + self.dynadata.bool_stack.push(first == second); } - codegen::Opcode::GtInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value > second._value))); + Opcode::NeInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); + self.dynadata.bool_stack.push(first != second); } - codegen::Opcode::GtFloat => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value > second._value))); + Opcode::NeFloat => { + let (first, second) = impl_opcode!(self.dynadata.float_stack, self, 2); + self.dynadata.bool_stack.push(first != second); } - codegen::Opcode::GeInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value >= second._value))); + Opcode::NeStr => { + let (first, second) = impl_opcode!(self.dynadata.str_stack, self, 2); + self.dynadata.bool_stack.push(first != second); } - codegen::Opcode::GeFloat => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value >= second._value))); + Opcode::NeChar => { + let (first, second) = impl_opcode!(self.dynadata.char_stack, self, 2); + self.dynadata.bool_stack.push(first != second); } - codegen::Opcode::AndBool => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value && second._value))); + Opcode::NeBool => { + let (first, second) = impl_opcode!(self.dynadata.bool_stack, self, 2); + self.dynadata.bool_stack.push(first != second); } - codegen::Opcode::OrBool => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(first._value || second._value))); + Opcode::LtInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); + self.dynadata.bool_stack.push(first < second); } - codegen::Opcode::NotBool => { - let first = self.impl_unary_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcBool::new(!first._value))); + Opcode::LtFloat => { + let (first, second) = impl_opcode!(self.dynadata.float_stack, self, 2); + self.dynadata.bool_stack.push(first < second); } - codegen::Opcode::XorInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcInt::new(first._value ^ second._value))); + Opcode::LeInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); + self.dynadata.bool_stack.push(first <= second); } - codegen::Opcode::BitNotInt => { - let first = self.impl_unary_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcInt::new(!first._value))); + Opcode::LeFloat => { + let (first, second) = impl_opcode!(self.dynadata.float_stack, self, 2); + self.dynadata.bool_stack.push(first <= second); } - codegen::Opcode::BitAndInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcInt::new(first._value & second._value))); + Opcode::GtInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); + self.dynadata.bool_stack.push(first > second); } - codegen::Opcode::BitOrInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcInt::new(first._value | second._value))); + Opcode::GtFloat => { + let (first, second) = impl_opcode!(self.dynadata.float_stack, self, 2); + self.dynadata.bool_stack.push(first > second); } - codegen::Opcode::BitLeftShiftInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcInt::new(first._value << second._value))); + Opcode::GeInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); + self.dynadata.bool_stack.push(first >= second); } - codegen::Opcode::BitRightShiftInt => { - let (first, second) = self.impl_ty_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcInt::new(first._value >> second._value))); + Opcode::GeFloat => { + let (first, second) = impl_opcode!(self.dynadata.float_stack, self, 2); + self.dynadata.bool_stack.push(first >= second); } - codegen::Opcode::SelfNegativeInt => { - let first = self.impl_unary_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcInt::new(-first._value))); + Opcode::AndBool => { + let (first, second) = impl_opcode!(self.dynadata.bool_stack, self, 2); + self.dynadata.bool_stack.push(first && second); } - codegen::Opcode::SelfNegativeFloat => { - let first = self.impl_unary_opcode::()?; - self.dynadata - .obj_stack - .push(Box::new(TrcFloat::new(-first._value))); + Opcode::OrBool => { + let (first, second) = impl_opcode!(&mut self.dynadata.bool_stack, self, 2); + self.dynadata.bool_stack.push(first || second); } + Opcode::NotBool => { + let first = impl_opcode!(self.dynadata.bool_stack, self, 1); + self.dynadata.bool_stack.push(!first); + } + Opcode::XorInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); + self.dynadata.int_stack.push(first ^ second); + } + Opcode::BitNotInt => { + let first = impl_opcode!(self.dynadata.int_stack, self, 1); + self.dynadata.int_stack.push(!first); + } + Opcode::BitAndInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); + self.dynadata.int_stack.push(first & second); + } + Opcode::BitOrInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); + self.dynadata.int_stack.push(first | second); + } + Opcode::BitLeftShiftInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); + self.dynadata.int_stack.push(first << second); + } + Opcode::BitRightShiftInt => { + let (first, second) = impl_opcode!(self.dynadata.int_stack, self, 2); + self.dynadata.int_stack.push(first >> second); + } + Opcode::SelfNegativeInt => { + let first = impl_opcode!(self.dynadata.int_stack, self, 1); + self.dynadata.int_stack.push(-first); + } + Opcode::SelfNegativeFloat => { + let first = impl_opcode!(self.dynadata.float_stack, self, 1); + self.dynadata.float_stack.push(-first); + } + Opcode::JumpIfFalse => { + let condit = impl_opcode!(self.dynadata.bool_stack, self, 1); + if !condit { + self.pc = self.static_data.inst[self.pc].operand; + } + } + Opcode::Jump => { + self.pc = self.static_data.inst[self.pc].operand; + } + Opcode::LoadChar => unsafe { + self.dynadata.char_stack.push(char::from_u32_unchecked( + self.static_data.inst[self.pc].operand as u32, + )); + }, + Opcode::LoadBool => { + self.dynadata + .bool_stack + .push(self.static_data.inst[self.pc].operand != 0); + } + Opcode::MoveInt => self.dynadata.obj_stack.push(Box::new(TrcInt::new( + self.dynadata.int_stack.pop().unwrap(), + ))), + Opcode::MoveFloat => self.dynadata.obj_stack.push(Box::new(TrcFloat::new( + self.dynadata.float_stack.pop().unwrap(), + ))), + Opcode::MoveChar => self.dynadata.obj_stack.push(Box::new(TrcChar::new( + self.dynadata.char_stack.pop().unwrap(), + ))), + Opcode::MoveBool => self.dynadata.obj_stack.push(Box::new(TrcBool::new( + self.dynadata.bool_stack.pop().unwrap(), + ))), + Opcode::MoveStr => self.dynadata.obj_stack.push(Box::new(TrcStr::new( + self.dynadata.str_stack.pop().unwrap(), + ))), } self.pc += 1; } diff --git a/rust/src/tvm/stdlib/prelude.rs b/rust/src/tvm/stdlib/prelude.rs index fd09db9c..03a7b2f5 100644 --- a/rust/src/tvm/stdlib/prelude.rs +++ b/rust/src/tvm/stdlib/prelude.rs @@ -1,16 +1,56 @@ +use std::io::{self, Write}; + use super::super::types::*; use crate::base::stdlib::*; use crate::{base::error::*, tvm::DynaData}; use derive::{def_module, trc_function}; +use gettextrs::gettext; -#[trc_function] -pub fn print(obj: any) -> void { - print!("{}", obj); +#[trc_function(var_params = true)] +pub fn print(fmt_string: str) -> void { + let mut iter = va_list.iter(); + let mut output_iter = fmt_string.chars(); + while let Some(i) = output_iter.next() { + if i == '{' { + io::stdout() + .write_all(iter.next().unwrap().to_string().as_bytes()) + .unwrap(); + if let Some(j) = output_iter.next() { + if j != '}' { + return Err(ErrorInfo::new( + gettext(UNCLOSED_FORMAT), + gettext(FORMAT_STR_ERROR), + )); + } + } + } else { + io::stdout().write_all(&[i as u8]).unwrap(); + } + } } -#[trc_function] -pub fn println(obj: any) -> void { - println!("{}", obj); +#[trc_function(var_params = true)] +pub fn println(fmt_string: str) -> void { + let mut iter = va_list.iter(); + let mut output_iter = fmt_string.chars(); + while let Some(i) = output_iter.next() { + if i == '{' { + io::stdout() + .write_all(iter.next().unwrap().to_string().as_bytes()) + .unwrap(); + if let Some(j) = output_iter.next() { + if j != '}' { + return Err(ErrorInfo::new( + gettext(UNCLOSED_FORMAT), + gettext(FORMAT_STR_ERROR), + )); + } + } + } else { + io::stdout().write_all(&[i as u8]).unwrap(); + } + } + io::stdout().write_all(b"\n").unwrap(); } def_module!(module_name = prelude, functions = [print => print, println => print], classes = [ diff --git a/rust/src/tvm/types.rs b/rust/src/tvm/types.rs index 92e50f35..6f226986 100644 --- a/rust/src/tvm/types.rs +++ b/rust/src/tvm/types.rs @@ -87,7 +87,7 @@ macro_rules! impl_single_oper { macro_rules! gen_interface { ($funcname:ident, 2) => { pub fn $funcname(dydata: &mut DynaData) -> RuntimeResult<()> { - dydata.check_stack(2)?; + DynaData::check_stack(&mut dydata.obj_stack, 2)?; let t2 = dydata.obj_stack.pop().unwrap(); let t1 = dydata.obj_stack.pop().unwrap(); dydata.obj_stack.push(t1.$funcname(t2)?); @@ -96,7 +96,7 @@ macro_rules! gen_interface { }; ($funcname:ident, 1) => { pub fn $funcname(dydata: &mut DynaData) -> RuntimeResult<()> { - dydata.check_stack(1)?; + DynaData::check_stack(&mut dydata.obj_stack, 1)?; let t1 = dydata.obj_stack.pop().unwrap(); dydata.obj_stack.push(t1.$funcname()?); Ok(()) diff --git a/rust/src/tvm/types/data_structure/sam.rs b/rust/src/tvm/types/data_structure/sam.rs index 617a4c0b..26bc0ca0 100644 --- a/rust/src/tvm/types/data_structure/sam.rs +++ b/rust/src/tvm/types/data_structure/sam.rs @@ -1,5 +1,5 @@ use crate::base::error::*; -use crate::base::stdlib::RustFunction; +use crate::base::stdlib::{OverrideWrapper, RustFunction}; use crate::tvm::types::trcchar::TrcChar; use crate::tvm::types::TrcObj; use crate::tvm::DynaData; @@ -32,7 +32,7 @@ pub struct Sam { } impl Sam { - fn override_export() -> HashMap { + fn override_export() -> HashMap { hash_map![] } @@ -45,7 +45,7 @@ impl Sam { #[trc_method] impl Sam { - #[trc_function(true)] + #[trc_function(method = true)] pub fn extend(s: Sam, c: TrcChar) { let id: usize = s._states.len(); // 后缀自动机最后一个节点 diff --git a/rust/src/tvm/types/trcbool.rs b/rust/src/tvm/types/trcbool.rs index 1f201406..c7ee77f7 100644 --- a/rust/src/tvm/types/trcbool.rs +++ b/rust/src/tvm/types/trcbool.rs @@ -44,11 +44,11 @@ impl TrcBool { Self { _value: value } } - fn override_export() -> HashMap { + fn override_export() -> HashMap { hash_map![ - TokenType::And => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::Or => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::Not => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())) + TokenType::And => OverrideWrapper::new(crate::base::codegen::Opcode::AndBool, IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::Or => OverrideWrapper::new(crate::base::codegen::Opcode::OrBool, IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::Not => OverrideWrapper::new(crate::base::codegen::Opcode::NotBool, IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)) ] } } diff --git a/rust/src/tvm/types/trcchar.rs b/rust/src/tvm/types/trcchar.rs index 41ec1c10..a55d62db 100644 --- a/rust/src/tvm/types/trcchar.rs +++ b/rust/src/tvm/types/trcchar.rs @@ -30,7 +30,7 @@ impl TrcChar { Self { _value: value } } - fn override_export() -> HashMap { + fn override_export() -> HashMap { hash_map![] } } diff --git a/rust/src/tvm/types/trcfloat.rs b/rust/src/tvm/types/trcfloat.rs index 2f70a983..23bb27c5 100644 --- a/rust/src/tvm/types/trcfloat.rs +++ b/rust/src/tvm/types/trcfloat.rs @@ -1,6 +1,7 @@ use super::trcbool::TrcBool; use super::TrcInt; use super::TrcObj; +use crate::base::codegen::Opcode; use crate::base::error::*; use crate::base::stdlib::*; use crate::compiler::scope::TypeAllowNull; @@ -25,20 +26,20 @@ impl TrcFloat { Self { _value: value } } - fn override_export() -> HashMap { + fn override_export() -> HashMap { hash_map![ - TokenType::Add => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::Sub => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::Mul => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::Div => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::ExactDiv => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcInt::export_info())), - TokenType::Equal => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info())), - TokenType::NotEqual => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info())), - TokenType::Less => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info())), - TokenType::LessEqual => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info())), - TokenType::Greater => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info())), - TokenType::GreaterEqual => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info())), - TokenType::SelfNegative => IOType::new(vec![], TypeAllowNull::Yes(Self::export_info())) + TokenType::Add => OverrideWrapper::new(Opcode::AddFloat, IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::Sub => OverrideWrapper::new(Opcode::SubFloat, IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::Mul => OverrideWrapper::new(Opcode::MulFloat, IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::Div => OverrideWrapper::new(Opcode::DivFloat, IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::ExactDiv => OverrideWrapper::new(Opcode::ExtraDivFloat, IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcInt::export_info()), false)), + TokenType::Equal => OverrideWrapper::new(Opcode::EqFloat, IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info()), false)), + TokenType::NotEqual => OverrideWrapper::new(Opcode::NeFloat, IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info()), false)), + TokenType::Less => OverrideWrapper::new(Opcode::LtFloat, IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info()), false)), + TokenType::LessEqual => OverrideWrapper::new(Opcode::LeFloat, IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info()), false)), + TokenType::Greater => OverrideWrapper::new(Opcode::GtFloat, IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info()), false)), + TokenType::GreaterEqual => OverrideWrapper::new(Opcode::GeFloat, IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info()), false)), + TokenType::SelfNegative => OverrideWrapper::new(Opcode::SelfNegativeFloat, IOType::new(vec![], TypeAllowNull::Yes(Self::export_info()), false)) ] } } diff --git a/rust/src/tvm/types/trcint.rs b/rust/src/tvm/types/trcint.rs index 94617354..479b7edc 100644 --- a/rust/src/tvm/types/trcint.rs +++ b/rust/src/tvm/types/trcint.rs @@ -1,6 +1,7 @@ use super::trcbool::TrcBool; use super::trcfloat::TrcFloat; use super::TrcObj; +use crate::base::codegen::Opcode; use crate::base::stdlib::*; use crate::compiler::scope::TypeAllowNull; use crate::compiler::token::TokenType; @@ -24,27 +25,27 @@ impl TrcInt { TrcInt { _value: value } } - fn override_export() -> HashMap { - hash_map![TokenType::Add => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::Sub => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::Mul => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::Div => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcFloat::export_info())), - TokenType::Mod => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::Power => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::BitAnd => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::BitOr => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::Xor => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::ExactDiv => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::BitLeftShift => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::BitRightShift => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())), - TokenType::BitNot => IOType::new(vec![], TypeAllowNull::Yes(Self::export_info())), - TokenType::SelfNegative => IOType::new(vec![], TypeAllowNull::Yes(Self::export_info())), - TokenType::Equal => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info())), - TokenType::NotEqual => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info())), - TokenType::Less => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info())), - TokenType::LessEqual => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info())), - TokenType::Greater => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info())), - TokenType::GreaterEqual => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info())) + fn override_export() -> HashMap { + hash_map![TokenType::Add => OverrideWrapper::new(Opcode::AddInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::Sub => OverrideWrapper::new(Opcode::SubInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::Mul => OverrideWrapper::new(Opcode::MulInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::Div => OverrideWrapper::new(Opcode::DivInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcFloat::export_info()), false)), + TokenType::Mod => OverrideWrapper::new(Opcode::ModInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::Power => OverrideWrapper::new(Opcode::PowerInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::BitAnd => OverrideWrapper::new(Opcode::BitAndInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::BitOr => OverrideWrapper::new(Opcode::BitOrInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::Xor => OverrideWrapper::new(Opcode::XorInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::ExactDiv => OverrideWrapper::new(Opcode::ExactDivInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::BitLeftShift => OverrideWrapper::new(Opcode::BitLeftShiftInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::BitRightShift => OverrideWrapper::new(Opcode::BitRightShiftInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::BitNot => OverrideWrapper::new(Opcode::BitNotInt,IOType::new(vec![], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::SelfNegative => OverrideWrapper::new(Opcode::SelfNegativeInt,IOType::new(vec![], TypeAllowNull::Yes(Self::export_info()), false)), + TokenType::Equal => OverrideWrapper::new(Opcode::EqInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info()), false)), + TokenType::NotEqual => OverrideWrapper::new(Opcode::NeInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info()), false)), + TokenType::Less => OverrideWrapper::new(Opcode::LtInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info()), false)), + TokenType::LessEqual => OverrideWrapper::new(Opcode::LeInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info()), false)), + TokenType::Greater => OverrideWrapper::new(Opcode::GtInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info()), false)), + TokenType::GreaterEqual => OverrideWrapper::new(Opcode::GeInt,IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(TrcBool::export_info()), false)) ] } } diff --git a/rust/src/tvm/types/trcstr.rs b/rust/src/tvm/types/trcstr.rs index 0f80a270..55acea83 100644 --- a/rust/src/tvm/types/trcstr.rs +++ b/rust/src/tvm/types/trcstr.rs @@ -40,9 +40,9 @@ impl TrcStr { Self { _value: value } } - fn override_export() -> HashMap { + fn override_export() -> HashMap { hash_map![ - TokenType::Add => IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info())) + TokenType::Add => OverrideWrapper::new(crate::base::codegen::Opcode::AddStr, IOType::new(vec![Self::export_info()], TypeAllowNull::Yes(Self::export_info()), false)) ] } } diff --git a/rust/stdlib/Cargo.toml b/rust/stdlib/Cargo.toml new file mode 100644 index 00000000..41bf08c9 --- /dev/null +++ b/rust/stdlib/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "stdlib" +version = "0.1.0" +edition = "2021" + +[dependencies] + +[lib] +name = "stdlib" diff --git a/rust/stdlib/src/lib.rs b/rust/stdlib/src/lib.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/rust/stdlib/src/lib.rs @@ -0,0 +1 @@ +