From 0b21bef54b2a840580614a72b452bcf6e7241019 Mon Sep 17 00:00:00 2001 From: limuy Date: Fri, 2 Feb 2024 00:31:30 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=A8=E8=BF=87=E7=A8=8B=E5=AE=8F=E7=BB=84?= =?UTF-8?q?=E7=BB=87=E6=A0=87=E5=87=86=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 +- rust/Cargo.lock | 22 +- rust/Cargo.toml | 9 +- rust/derive/Cargo.toml | 14 ++ rust/derive/src/def_module.rs | 165 +++++++++++++++ rust/derive/src/function.rs | 68 ++++++ rust/derive/src/lib.rs | 155 ++++++++++++++ rust/derive/tests/import_module_test.rs | 5 + rust/script/gen_locales.py | 7 +- rust/src/base/error.rs | 12 +- rust/src/base/stdlib.rs | 266 +++++++++++++++++------- rust/src/base/utils.rs | 2 +- rust/src/compiler.rs | 4 +- rust/src/compiler/ast.rs | 42 ++-- rust/src/compiler/scope.rs | 149 ++++++------- rust/src/compiler/token.rs | 139 ++++++------- rust/src/tvm.rs | 99 ++++----- rust/src/tvm/stdlib.rs | 5 + rust/src/tvm/stdlib/prelude.rs | 20 +- rust/src/tvm/types.rs | 125 +++++++---- rust/src/tvm/types/trcbool.rs | 21 +- rust/src/tvm/types/trcfloat.rs | 22 +- rust/src/tvm/types/trcint.rs | 30 +-- rust/src/tvm/types/trcstr.rs | 20 +- 24 files changed, 1001 insertions(+), 405 deletions(-) create mode 100644 rust/derive/Cargo.toml create mode 100644 rust/derive/src/def_module.rs create mode 100644 rust/derive/src/function.rs create mode 100644 rust/derive/src/lib.rs create mode 100644 rust/derive/tests/import_module_test.rs diff --git a/.gitignore b/.gitignore index c2bafcaa..db6d02d3 100644 --- a/.gitignore +++ b/.gitignore @@ -41,10 +41,7 @@ testlog.log *.a *.exp *.pdb -token.cpp -parser.cpp -parser.hpp -location.hh +tmp/ # 单元测试中的临时输出文件 *.out diff --git a/rust/Cargo.lock b/rust/Cargo.lock index e759ec91..96695eb1 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -224,6 +224,15 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "derive" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "downcast-rs" version = "1.2.0" @@ -610,9 +619,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] @@ -968,9 +977,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.30" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ "bitflags 2.4.2", "errno", @@ -1195,9 +1204,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.1" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", @@ -1278,6 +1287,7 @@ version = "0.1.0" dependencies = [ "clap", "colored", + "derive", "downcast-rs", "gettext-rs", "lazy_static", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index a94332c1..cdb2b282 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -18,8 +18,15 @@ downcast-rs = "1.2.0" lazy_static = "1.4.0" num-bigint = "0.4.4" reqwest = { version = "0.11.24", features = ["json", "multipart"] } -tokio = { version = "1.35.1", features = ["full"] } +tokio = { version = "1.36.0", features = ["full"] } llvm-sys = "170.0.1" +derive = { path = "./derive" } [profile.release] panic = "abort" +lto = true +codegen-units = 1 +strip = true + +[workspace] +members = ["derive", "."] diff --git a/rust/derive/Cargo.toml b/rust/derive/Cargo.toml new file mode 100644 index 00000000..6de9e7a0 --- /dev/null +++ b/rust/derive/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "derive" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +syn = { version = "2.0.48", features = ["extra-traits", "full"] } +quote = "1.0.35" +proc-macro2 = "1.0.78" + +[lib] +proc-macro = true diff --git a/rust/derive/src/def_module.rs b/rust/derive/src/def_module.rs new file mode 100644 index 00000000..4d6651a5 --- /dev/null +++ b/rust/derive/src/def_module.rs @@ -0,0 +1,165 @@ +use core::panic; +use proc_macro::{token_stream::IntoIter, TokenStream, TokenTree}; +use quote::quote; + +use crate::function; + +pub fn lex_arrow( + left_push: &mut Vec, + right_push: &mut Vec, + iter: &mut IntoIter, + errormsg: &str, +) { + match iter.next().unwrap() { + proc_macro::TokenTree::Group(x, ..) => { + let mut left_name = TokenStream::new(); + let mut right_name = TokenStream::new(); + let mut control_which_put = false; + let mut iter = x.stream().into_iter(); + while let Some(i) = iter.next() { + // println!("{}", i); + if let proc_macro::TokenTree::Punct(x) = i { + let x = x.to_string(); + if x == "=" { + check_next_iter(&mut iter, ">"); + // 切换左右边 + control_which_put = true; + } else if x == "," { + // println!("item:{}", left_name); + left_push.push(syn::parse(left_name).expect("left push continue")); + right_push.push(syn::parse(right_name).expect("right push continue")); + left_name = TokenStream::new(); + right_name = TokenStream::new(); + control_which_put = false; + } else if x == "]" { + left_push.push(syn::parse(left_name).expect("left push break")); + right_push.push(syn::parse(right_name).expect("right push break")); + break; + } + } else { + if !control_which_put { + left_name.extend(std::iter::once(i)); + } else { + right_name.extend(std::iter::once(i)); + } + } + } + } + _ => { + panic!("{}", errormsg); + } + } +} + +fn check_next_iter(iter: &mut IntoIter, check_str: &str) { + if let Some(i) = iter.next() { + if let proc_macro::TokenTree::Punct(x) = i { + if x.to_string() != check_str { + panic!("expected {}", check_str); + } + } else { + panic!("expected {}", check_str); + } + } else { + panic!("expected {}", check_str); + } +} + +pub fn def_impl(content: TokenStream) -> TokenStream { + let mut module_ident = None; + let mut iter = content.into_iter(); + let mut left_func = vec![]; + let mut right_func = vec![]; + let mut left_class = vec![]; + let mut right_class = vec![]; + let mut submodules = vec![]; + while let Some(i) = iter.next() { + match i { + proc_macro::TokenTree::Ident(x) => { + let x = x.to_string(); + if x == "module_name" { + check_next_iter(&mut iter, "="); + if let TokenTree::Ident(tmp) = iter.next().expect("name is expected") { + if let Some(_) = module_ident { + panic!("double defined"); + } + module_ident = + Some(syn::parse_str::(&tmp.to_string()).unwrap()); + } else { + panic!("name is expected"); + } + } else if x == "functions" { + check_next_iter(&mut iter, "="); + lex_arrow( + &mut left_func, + &mut right_func, + &mut iter, + "functions are expected", + ) + } else if x == "classes" { + check_next_iter(&mut iter, "="); + lex_arrow( + &mut left_class, + &mut right_class, + &mut iter, + "classes are expected", + ); + } else if x == "submodules" { + check_next_iter(&mut iter, "="); + if let proc_macro::TokenTree::Group(x, ..) = iter.next().unwrap() { + // println!("{}", x); + let mut iter = x.stream().into_iter(); + while let Some(i) = iter.next() { + if let proc_macro::TokenTree::Ident(x) = i { + submodules + .push(syn::parse_str::(&(x.to_string())).unwrap()); + } else if let proc_macro::TokenTree::Ident(x) = i { + let x = x.to_string(); + if x != "," { + panic!("expected ,.get {}", x); + } else if x == "]" { + break; + } + } + } + } else { + panic!("expected group") + } + } + } + proc_macro::TokenTree::Punct(x) => { + if x.to_string() != "," { + panic!("expected ,"); + } + } + _ => { + panic!("grammar error unexpected {}", i.to_string()); + } + } + } + for i in &mut left_func { + *i = syn::parse_str::(&function::convent_to_info_func(i.to_string())) + .expect("name error"); + } + let ret = quote!( + pub fn init() -> Stdlib { + use crate::base::stdlib::Stdlib; + use std::collections::hash_map::HashMap; + let mut functions = HashMap::new(); + let mut classes = HashMap::new(); + #( + functions.insert(stringify!(#right_func).to_string(), #left_func()); + )* + #( + classes.insert(stringify!(#right_class).to_string(), #left_class::export_info()); + )* + Stdlib::new( + stringify!(#module_ident), + HashMap::new(), + functions, + classes + ) + } + ); + ret.into() +} diff --git a/rust/derive/src/function.rs b/rust/derive/src/function.rs new file mode 100644 index 00000000..ae525685 --- /dev/null +++ b/rust/derive/src/function.rs @@ -0,0 +1,68 @@ +use syn::{ + parse_str, punctuated, token::Comma, FnArg, PatType, ReturnType, Signature, Stmt, Type, + TypePath, +}; + +pub fn process_function_def(sig: &mut Signature) -> (Vec, Vec, Type) { + let output = sig.output.clone(); + let output: Type = match output { + ReturnType::Default => parse_str("TypeAllowNull::No").unwrap(), + ReturnType::Type(_, ty) => { + if let Type::Path(name) = (*ty).clone() { + let tyname = name.path.segments[0].ident.to_string(); + if tyname == "void" { + parse_str("TypeAllowNull::No").unwrap() + } else if tyname == "any" { + parse_str("ANY_TYPE").unwrap() + } else { + (*ty).clone() + } + } else { + (*ty).clone() + } + } + }; + let input_args = sig.inputs.clone(); + let mut new_stmts = vec![]; + let mut new_args: punctuated::Punctuated = syn::punctuated::Punctuated::new(); + // 第一个参数是self + if input_args.len() >= 1 { + if let FnArg::Receiver(_) = &input_args[0] { + new_args.push(input_args[0].clone()); + } + } + let mut args_type_required = vec![]; + + new_args.push(parse_str::("dydata: &mut DynaData").unwrap()); + sig.inputs = new_args; + for i in &input_args { + if let FnArg::Typed(PatType { pat, ty, .. }, ..) = i { + if let Type::Path(path, ..) = &**ty { + let arg_name = match &**pat { + syn::Pat::Ident(syn::PatIdent { ident, .. }) => ident.to_string(), + _ => unreachable!(), + }; + // println!("argv:{:#?}", path); + if path.path.segments[0].ident.to_string() == "any" { + args_type_required.push(parse_str("ANY_TYPE").unwrap()); + } else { + args_type_required.push(path.clone()); + } + new_stmts.push( + parse_str::(&format!( + "let mut {} = dydata.obj_stack.pop().unwrap();", + arg_name + )) + .unwrap(), + ); + } + } + } + // 栈是反的 + new_stmts.reverse(); + (new_stmts, args_type_required, output) +} + +pub fn convent_to_info_func(name: impl Into) -> String { + format!("{}_info", name.into()) +} diff --git a/rust/derive/src/lib.rs b/rust/derive/src/lib.rs new file mode 100644 index 00000000..39f67c26 --- /dev/null +++ b/rust/derive/src/lib.rs @@ -0,0 +1,155 @@ +use function::process_function_def; +use proc_macro::TokenStream; +use quote::{quote, ToTokens}; +use syn::ImplItem; +use syn::{ + parse_macro_input, parse_str, Expr, Ident, ItemFn, ItemImpl, ItemStruct, Stmt, Type, Visibility, +}; +mod def_module; +mod function; + +#[proc_macro_attribute] +/// 返回值一定要加上return +pub fn trc_function(_: 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(); + input.sig.output = parse_str::("-> RuntimeResult<()>").expect("err1"); + let return_stmt = parse_str::("return Ok(());").expect("err2"); + for i in input.block.stmts { + if let Stmt::Expr(Expr::Return(reexpr), ..) = i.clone() { + if reexpr.expr.is_none() { + continue; + } + let reexpr = *reexpr.expr.unwrap(); + let tmp = reexpr.to_token_stream().into_iter().next(); + if tmp.is_none() { + continue; + } + let tmp = tmp.unwrap().to_string(); + + if tmp == "Err" { + new_stmts.push(i); + continue; + } + + new_stmts.push( + parse_str::(&format!( + "dydata.obj_stack.push(Box::new({}));", + quote!(#reexpr) + )) + .unwrap(), + ); + new_stmts.push(return_stmt.clone()); + } else { + new_stmts.push(i); + } + } + new_stmts.push(return_stmt.clone()); + input.block.stmts = new_stmts; + // 将函数改写成正常的函数之后还需要生成一个函数来获取这个函数的信息,例如接收的参数和返回值 + 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 rettmp = quote!(#input + fn #info_func_name() -> RustFunction { + use crate::base::stdlib::*; + use crate::compiler::scope::TypeAllowNull; + let ret_classes = vec![#(#args_type_required.clone()),*]; + return RustFunction::new(stringify!(#name), #name, IOType::new(ret_classes, #output)); + } + ); + // println!("{}", rettmp.to_token_stream()); + rettmp.into() +} + +#[proc_macro] +/// def_module!(module_name = module_name, functions = [func1 => func1, func2 => func2], classes = [class1 => class1, class2 => class2], submodules=[submodule1, submodule2]) +pub fn def_module(input: TokenStream) -> TokenStream { + // let input = parse_macro_input!(input as DeriveInput); + let processed = def_module::def_impl(input); + processed +} + +#[proc_macro_attribute] +pub fn trc_class(_: TokenStream, input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as ItemStruct); + let name = input.ident.clone(); + // 为每个类生成一个export_info函数,控制导入到stdlib中的信息 + let mut members_ident: Vec = vec![]; + let mut members_ty: Vec = vec![]; + for i in &input.fields { + if let Visibility::Public(_) = i.vis { + // 说明是要导出的成员 + let varname = i.ident.clone().unwrap(); + let vartype = i.ty.clone(); + members_ident.push(varname); + members_ty.push(vartype); + } + } + // export_info函数会调用method宏生成function_export函数 + let ret = quote!(#input + use crate::base::stdlib::RustClass; + impl #name { + pub fn export_info() -> RustClass { + use std::collections::hash_map::HashMap; + use crate::compiler::scope::{Var}; + let mut members = HashMap::new(); + #( + members.insert(Var::new(stringify!(#members_ty), #members_ident)); + )* + let mut ret = RustClass::new( + stringify!(#name), + members, + Self::function_export(), + Self::override_export() + ); + ret + } + } + ); + // println!("{}", ret.to_string()); + ret.into() +} + +#[proc_macro_attribute] +/// 返回值一定要加上return +/// 定义一个函数体为空的函数会被当成接口声明,用于宏生成的接口 +pub fn trc_method(_: TokenStream, input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as ItemImpl); + // 生成一个function_export,返回一个vec,里面存着functions + let name = input.self_ty.clone(); + // for i in input + // print!("{:#?}", input); + // println!("!!!!!!!!!!!!!!!!!!!!!!!!!!:{:#?}", name); + let mut funcs = vec![]; + for i in &input.items { + match i { + ImplItem::Fn(func) => { + if let Visibility::Public(_) = func.vis { + funcs.push( + parse_str::(&function::convent_to_info_func( + func.sig.ident.to_string(), + )) + .unwrap(), + ); + } + } + _ => {} + } + } + let ret = quote!( + #input + impl #name { + fn function_export() -> HashMap { + let mut ret = HashMap::new(); + #( + ret.push(stringify!(#funcs).to_string(), self.#funcs()); + )* + ret + } + } + ); + // println!("{:#?}", ret.to_string()); + ret.into() +} diff --git a/rust/derive/tests/import_module_test.rs b/rust/derive/tests/import_module_test.rs new file mode 100644 index 00000000..2ec75fb8 --- /dev/null +++ b/rust/derive/tests/import_module_test.rs @@ -0,0 +1,5 @@ +use derive::{def_module, trc_class, trc_function, trc_method}; + +#[test] +/// just a place for developer,not real test +fn test_output() {} diff --git a/rust/script/gen_locales.py b/rust/script/gen_locales.py index f14f6941..193f5b7c 100644 --- a/rust/script/gen_locales.py +++ b/rust/script/gen_locales.py @@ -3,18 +3,19 @@ """ import os +import sys os.chdir("../locales") tt = os.listdir(".") for i in tt: os.chdir(i) os.chdir("LC_MESSAGES") - l = os.listdir() - for j in l: + subdirs = os.listdir() + for j in subdirs: tmp = os.path.splitext(j) if tmp[1] != ".po": continue if os.system(f"msgfmt -o {tmp[0]}.mo {j}"): print("Cannot generate your locales files.Stop.") - exit(1) + sys.exit(1) os.chdir("../..") diff --git a/rust/src/base/error.rs b/rust/src/base/error.rs index 1e3c9e82..e5b4d9fa 100644 --- a/rust/src/base/error.rs +++ b/rust/src/base/error.rs @@ -36,10 +36,10 @@ pub struct ErrorInfo { } impl ErrorInfo { - pub fn new(message: String, error_type: String) -> ErrorInfo { + pub fn new(message: impl Into, error_type: impl Into) -> ErrorInfo { ErrorInfo { - message, - error_type, + message: message.into(), + error_type: error_type.into(), } } } @@ -118,11 +118,9 @@ impl LightFakeContent { impl From for RuntimeError { fn from(_: LightFakeError) -> RuntimeError { - RuntimeError::new( - Box::new(LightFakeError::new()), - ErrorInfo::new("".to_string(), "".to_string()), - ) + RuntimeError::new(Box::new(LightFakeError::new()), ErrorInfo::new("", "")) } } pub type RunResult = Result; +pub type RuntimeResult = Result; diff --git a/rust/src/base/stdlib.rs b/rust/src/base/stdlib.rs index 34c2f778..2754d738 100644 --- a/rust/src/base/stdlib.rs +++ b/rust/src/base/stdlib.rs @@ -1,26 +1,64 @@ +use super::error::*; use crate::{ base::error::{ARGUMENT_ERROR, ARGU_NUMBER, EXPECT_TYPE}, - compiler::scope::{Type, TypeAllowNull}, - tvm::{stdlib::prelude::*, DynaData}, + compiler::{ + scope::{Type, TypeAllowNull, Var}, + token::TokenType, + }, + tvm::DynaData, }; use downcast_rs::{impl_downcast, Downcast}; use lazy_static::lazy_static; use std::{ - collections::{HashMap, HashSet}, - sync::{Arc, Mutex}, + cell::RefCell, + collections::HashMap, + fmt::{Debug, Display}, }; -use super::error::{ErrorInfo, RunResult}; +type StdlibFunc = fn(&mut DynaData) -> RuntimeResult<()>; -type StdlibFunc = fn(&mut DynaData) -> RunResult<()>; +#[derive(Clone, Debug)] +pub struct IOType { + pub argvs_type: Vec, + pub return_type: TypeAllowNull, +} -#[derive(Hash, PartialEq, Eq, Clone, Debug)] +#[derive(Clone, Debug)] pub struct RustFunction { pub name: String, pub buildin_id: usize, pub ptr: StdlibFunc, - pub argvs_type: Vec, - pub return_type: TypeAllowNull, + pub io: IOType, +} + +impl IOType { + pub fn new(argvs_type: Vec, return_type: TypeAllowNull) -> IOType { + IOType { + argvs_type, + return_type, + } + } + + pub fn check_argvs(&self, argvs: Vec) -> Result<(), ErrorInfo> { + if argvs.len() != self.argvs_type.len() { + return Err(ErrorInfo::new( + gettextrs::gettext!(ARGU_NUMBER, self.argvs_type.len(), argvs.len()), + gettextrs::gettext(ARGUMENT_ERROR), + )); + } + for i in 0..self.argvs_type.len() { + if self.argvs_type[i].is_any() { + continue; + } + if self.argvs_type[i].get_id() != argvs[i].get_id() { + return Err(ErrorInfo::new( + gettextrs::gettext!(EXPECT_TYPE, self.argvs_type[i], argvs[i]), + gettextrs::gettext(ARGUMENT_ERROR), + )); + } + } + Ok(()) + } } pub trait FunctionClone { @@ -37,8 +75,8 @@ where } pub trait FunctionInterface: Downcast + FunctionClone { - fn check_argvs(&self, argvs: Vec) -> Result<(), ErrorInfo>; - fn get_return_type(&self) -> &TypeAllowNull; + fn get_io(&self) -> &IOType; + fn get_name(&self) -> &str; } impl Clone for Box { @@ -49,108 +87,182 @@ impl Clone for Box { impl_downcast!(FunctionInterface); +pub trait ClassClone { + fn clone_box(&self) -> Box; +} + +pub trait ClassInterface: Downcast + Sync + Send + ClassClone + Debug + Display { + fn has_func(&self, funcname: &str) -> Option>; + + fn has_attr(&self, attrname: &str) -> Option; + + fn get_name(&self) -> &str; + + fn get_id(&self) -> usize; + + fn is_any(&self) -> bool { + self.get_id() == 0 + } +} + +impl ClassClone for T +where + T: 'static + ClassInterface + Clone, +{ + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } +} + +impl Clone for Box { + fn clone(&self) -> Self { + self.clone_box() + } +} + +impl_downcast!(ClassInterface); + impl FunctionInterface for RustFunction { - fn check_argvs(&self, argvs: Vec) -> Result<(), ErrorInfo> { - if argvs.len() != self.argvs_type.len() { - return Err(ErrorInfo::new( - gettextrs::gettext!(ARGU_NUMBER, self.argvs_type.len(), argvs.len()), - gettextrs::gettext(ARGUMENT_ERROR), - )); + fn get_io(&self) -> &IOType { + &self.io + } + + fn get_name(&self) -> &str { + &self.name + } +} + +#[derive(Debug, Clone)] +pub struct RustClass { + pub name: String, + pub members: HashMap, + pub functions: HashMap, + pub overrides: HashMap, + pub id: usize, +} + +/// 约定,0号id是any类型 +impl RustClass { + pub fn new( + name: impl Into, + members: HashMap, + functions: HashMap, + overrides: HashMap, + ) -> RustClass { + RustClass { + name: name.into(), + members, + functions, + overrides, + id: 0, } - for i in 0..self.argvs_type.len() { - if argvs[i] != self.argvs_type[i] && self.argvs_type[i] != Type::Any { - return Err(ErrorInfo::new( - gettextrs::gettext!(EXPECT_TYPE, self.argvs_type[i], argvs[i]), - gettextrs::gettext(ARGUMENT_ERROR), - )); + } + + pub fn add_function(&mut self, name: impl Into, func: RustFunction) { + self.functions.insert(name.into(), func); + } + + pub fn add_attr(&mut self, name: impl Into, attr: Var) { + self.members.insert(name.into(), attr); + } +} + +impl ClassInterface for RustClass { + fn has_func(&self, funcname: &str) -> Option> { + for i in &self.functions { + if i.0 == funcname { + return Some(Box::new(i.1.clone())); } } - Ok(()) + None + } + + fn get_name(&self) -> &str { + &self.name + } + + fn get_id(&self) -> usize { + self.id } - fn get_return_type(&self) -> &TypeAllowNull { - &self.return_type + fn has_attr(&self, attrname: &str) -> Option { + let ret = &self.members.get(attrname); + match ret { + Some(i) => Some(i.ty.clone()), + None => None, + } } } -pub struct RustClass { - pub name: String, - pub members: HashMap, - pub functions: HashSet, +impl Display for RustClass { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.name) + } } -pub static mut STD_FUNC_TABLE: Vec = vec![]; +thread_local! { + pub static STD_FUNC_TABLE: RefCell> = RefCell::new(vec![]); +} impl RustFunction { - pub fn new( - name: String, - ptr: StdlibFunc, - argvs_type: Vec, - return_type: TypeAllowNull, - ) -> RustFunction { - unsafe { - STD_FUNC_TABLE.push(ptr); - RustFunction { - name, - buildin_id: STD_FUNC_TABLE.len() - 1, - ptr, - return_type, - argvs_type, - } + pub fn new(name: impl Into, ptr: StdlibFunc, io: IOType) -> RustFunction { + Self { + name: name.into(), + buildin_id: STD_FUNC_TABLE.with(|std| { + std.borrow_mut().push(ptr); + std.borrow().len() + }) - 1, + ptr, + io, } } } #[derive(Debug, Clone)] -pub struct StdlibNode { +pub struct Stdlib { pub name: String, - pub sons: HashMap>>, - pub functions: HashSet, + pub sub_modules: HashMap, + pub functions: HashMap, + pub classes: HashMap, } -impl StdlibNode { - pub fn new(name: String) -> StdlibNode { - StdlibNode { - name, - sons: HashMap::new(), - functions: HashSet::new(), +impl Stdlib { + pub fn new( + name: impl Into, + sub_modules: HashMap, + functions: HashMap, + classes: HashMap, + ) -> Stdlib { + Stdlib { + name: name.into(), + sub_modules, + functions, + classes, } } - pub fn add_module(&mut self, name: String) -> Arc> { - let ret = Arc::new(Mutex::new(StdlibNode::new(name.clone()))); - self.sons.insert(name.clone(), ret.clone()); - ret + pub fn add_module(&mut self, name: String, module: Stdlib) { + let ret = self.sub_modules.insert(name, module); + debug_assert!(ret.is_none()); } - pub fn add_function(&mut self, name: RustFunction) { - self.functions.insert(name); + pub fn add_function(&mut self, name: String, func: RustFunction) { + self.functions.insert(name, func); } - pub fn get_module>(&self, mut path: T) -> Option { + pub fn get_module>(&self, mut path: T) -> Option { let item = path.next(); if item.is_none() { return Some(self.clone()); } let item = item.unwrap(); - let lock = self.sons.get(&item).unwrap().lock().unwrap(); + let lock = self.sub_modules.get(&item).unwrap(); return lock.get_module(path); } } -pub fn init() -> StdlibNode { - // init stdlib - let mut stdlib = StdlibNode::new("std".to_string()); - let prelude = stdlib.add_module("prelude".to_string()); - prelude.lock().unwrap().add_function(RustFunction::new( - "print".to_string(), - tvm_print, - vec![Type::Any], - TypeAllowNull::No, - )); - stdlib -} - lazy_static! { - pub static ref STDLIB_LIST: StdlibNode = init(); + pub static ref ANY_TYPE: RustClass = + RustClass::new("any", HashMap::new(), HashMap::new(), HashMap::new()); + pub static ref STDLIB_ROOT: Stdlib = crate::tvm::stdlib::init(); } diff --git a/rust/src/base/utils.rs b/rust/src/base/utils.rs index 28dd8883..cb3440c6 100644 --- a/rust/src/base/utils.rs +++ b/rust/src/base/utils.rs @@ -2,7 +2,7 @@ use std::ops::DivAssign; #[macro_export] macro_rules! hash_map { - ($($key:expr => $val:expr),*) => { + [$($key:expr => $val:expr),*] => { { use std::collections::hash_map::HashMap; let mut ret = HashMap::new(); diff --git a/rust/src/compiler.rs b/rust/src/compiler.rs index 6b492b73..33a7d330 100644 --- a/rust/src/compiler.rs +++ b/rust/src/compiler.rs @@ -3,7 +3,7 @@ mod ast; pub mod scope; -mod token; +pub mod token; use self::token::TokenLex; use crate::base::codegen::{ConstPool, StaticData}; @@ -350,7 +350,7 @@ impl Compiler { } } _ => { - panic!("Compiler construct Error, used {:?}", option.inputsource); + unreachable!() } } } diff --git a/rust/src/compiler/ast.rs b/rust/src/compiler/ast.rs index bdc229bd..b057dbe1 100644 --- a/rust/src/compiler/ast.rs +++ b/rust/src/compiler/ast.rs @@ -2,7 +2,7 @@ use super::token::TokenType; use super::TokenLex; use super::{scope::*, InputSource}; use crate::base::codegen::{Inst, Opcode, NO_ARG}; -use crate::base::stdlib::{RustFunction, STDLIB_LIST}; +use crate::base::stdlib::{RustFunction, STDLIB_ROOT}; use crate::base::{codegen::StaticData, error::*}; use gettextrs::gettext; use std::cell::RefCell; @@ -39,7 +39,10 @@ macro_rules! TmpExpeFunctionGen { if let TypeAllowNull::No = ty_after { return Ok(ty_now); } - if(ty_now == ty_after) { + if let TypeAllowNull::No = ty_now { + return Ok(ty_now) + } + if(ty_now.unwrap().get_id() == ty_after.unwrap().get_id()) { return Ok(ty_now); } return TryErr!(istry, @@ -66,7 +69,10 @@ macro_rules! ExprGen { if let TypeAllowNull::No = t2 { return Ok(t1); } - if t1 != t2 { + if let TypeAllowNull::No = t1 { + return Ok(t1); + } + if t1.unwrap().get_id() != t2.unwrap().get_id() { return TryErr!(istry, Box::new(self.token_lexer.compiler_data.content.clone()), ErrorInfo::new(gettext!(TYPE_NOT_THE_SAME, t1, @@ -86,18 +92,8 @@ impl<'a> AstBuilder<'a> { staticdata: StaticData::new(), self_scope: root_scope, }; - for i in &STDLIB_LIST - .sons - .get("prelude") - .unwrap() - .lock() - .unwrap() - .functions - { - ret.token_lexer - .compiler_data - .const_pool - .add_id(i.name.clone()); + for i in &STDLIB_ROOT.sub_modules.get("prelude").unwrap().functions { + ret.token_lexer.compiler_data.const_pool.add_id(i.0.clone()); } ret.self_scope .as_ref() @@ -151,7 +147,7 @@ impl<'a> AstBuilder<'a> { return Err(RuntimeError::new( Box::new(self.token_lexer.compiler_data.content.clone()), ErrorInfo::new( - gettext!(UNEXPECTED_TOKEN, next_sym.tp.to_string()), + gettext!(UNEXPECTED_TOKEN, next_sym.tp), gettextrs::gettext(SYNTAX_ERROR), ), )); @@ -203,7 +199,7 @@ impl<'a> AstBuilder<'a> { self.check_next_token(TokenType::RightSmallBrace)?; let tmp = self.self_scope.borrow(); let func_obj = tmp.get_function(idx).unwrap(); - match func_obj.check_argvs(argv_list) { + match func_obj.get_io().check_argvs(argv_list) { Err(e) => { return TryErr!( istry, @@ -218,7 +214,7 @@ impl<'a> AstBuilder<'a> { .inst .push(Inst::new(Opcode::CallNative, obj.buildin_id)); } - return Ok((*func_obj.get_return_type()).clone()); + return Ok((func_obj.get_io().return_type).clone()); } else { self.token_lexer.next_back(nxt); let varidx = self.self_scope.as_ref().borrow_mut().insert_sym(idx); @@ -226,7 +222,7 @@ impl<'a> AstBuilder<'a> { .inst .push(Inst::new(Opcode::LoadLocal, varidx)); let tt = self.self_scope.as_ref().borrow().get_type(varidx); - return Ok(TypeAllowNull::Yes(Type::Common(tt))); + return Ok(TypeAllowNull::Yes(tt)); } } else { self.token_lexer.next_back(t.clone()); @@ -234,7 +230,7 @@ impl<'a> AstBuilder<'a> { istry, Box::new(self.token_lexer.compiler_data.content.clone()), ErrorInfo::new( - gettext!(UNEXPECTED_TOKEN, t.tp.to_string()), + gettext!(UNEXPECTED_TOKEN, t.tp), gettextrs::gettext(SYNTAX_ERROR), ) ); @@ -271,7 +267,7 @@ impl<'a> AstBuilder<'a> { istry, Box::new(self.token_lexer.compiler_data.content.clone()), ErrorInfo::new( - gettext!(UNEXPECTED_TOKEN, t.tp.to_string()), + gettext!(UNEXPECTED_TOKEN, t.tp), gettextrs::gettext(SYNTAX_ERROR), ) ); @@ -333,7 +329,7 @@ impl<'a> AstBuilder<'a> { istry, Box::new(self.token_lexer.compiler_data.content.clone()), ErrorInfo::new( - gettext!(UNEXPECTED_TOKEN, path.tp.to_string()), + gettext!(UNEXPECTED_TOKEN, path.tp), gettextrs::gettext(SYNTAX_ERROR), ) ); @@ -434,7 +430,7 @@ impl<'a> AstBuilder<'a> { return Err(RuntimeError::new( Box::new(self.token_lexer.compiler_data.content.clone()), ErrorInfo::new( - gettext!(UNEXPECTED_TOKEN, t.tp.to_string()), + gettext!(UNEXPECTED_TOKEN, t.tp), gettextrs::gettext(SYNTAX_ERROR), ), )); diff --git a/rust/src/compiler/scope.rs b/rust/src/compiler/scope.rs index a1446015..67d7a65d 100644 --- a/rust/src/compiler/scope.rs +++ b/rust/src/compiler/scope.rs @@ -1,8 +1,6 @@ use super::{ValuePool, BOOL_ID_POS, FLOAT_ID_POS, INT_ID_POS, STR_ID_POS}; -use crate::base::error::*; -use crate::base::stdlib::{FunctionInterface, StdlibNode, STDLIB_LIST}; +use crate::base::stdlib::{ClassInterface, FunctionInterface, IOType, Stdlib, STDLIB_ROOT}; use lazy_static::lazy_static; -use std::borrow::Borrow; use std::{cell::RefCell, collections::HashMap, fmt::Display, rc::Rc}; lazy_static! { @@ -15,7 +13,7 @@ lazy_static! { ]; } -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug)] pub enum TypeAllowNull { Yes(Type), No, @@ -40,19 +38,19 @@ impl Display for TypeAllowNull { } /// Manager of function -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug)] pub struct Function { - args_type: Vec, - return_type: TypeAllowNull, + io: IOType, start_address: usize, + name: String, } impl Function { - pub fn new(return_type: TypeAllowNull, start_address: usize) -> Self { + pub fn new(io: IOType, start_address: usize, name: String) -> Self { Self { - args_type: vec![], - return_type, + io, start_address, + name, } } @@ -60,57 +58,31 @@ impl Function { } impl FunctionInterface for Function { - fn check_argvs(&self, argvs: Vec) -> Result<(), crate::base::error::ErrorInfo> { - if argvs.len() != self.args_type.len() { - return Err(ErrorInfo::new( - gettextrs::gettext!(ARGU_NUMBER, self.args_type.len(), argvs.len()), - gettextrs::gettext(ARGUMENT_ERROR), - )); - } - for i in 0..self.args_type.len() { - if argvs[i] != self.args_type[i] && self.args_type[i] != Type::Any { - return Err(ErrorInfo::new( - gettextrs::gettext!(EXPECT_TYPE, self.args_type[i], argvs[i]), - gettextrs::gettext(ARGUMENT_ERROR), - )); - } - } - Ok(()) + fn get_io(&self) -> &IOType { + &self.io } - fn get_return_type(&self) -> &TypeAllowNull { - &self.return_type + fn get_name(&self) -> &str { + &self.name } } -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug)] pub struct Var { - ty: Type, + pub ty: Box, + pub name: String, } impl Var { - pub fn new(ty: Type) -> Self { - Self { ty } + pub fn new(ty: Box, name: String) -> Self { + Self { ty, name } } } -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub enum Type { - Common(CommonType), - Any, -} - -impl Display for Type { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Type::Common(t) => write!(f, "{}", t), - Type::Any => write!(f, "any"), - } - } -} +pub type Type = Box; /// Manager of type -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug)] pub struct CommonType { attr: Vec, funcs: Vec, @@ -125,12 +97,12 @@ impl Display for CommonType { } impl CommonType { - pub fn new(name: usize, origin_name: String) -> Self { + pub fn new(name: usize, origin_name: impl Into) -> Self { Self { attr: vec![], funcs: vec![], name, - origin_name, + origin_name: origin_name.into(), } } @@ -142,22 +114,50 @@ impl CommonType { self.funcs.push(f); } } + +impl ClassInterface for CommonType { + fn has_func(&self, funcname: &str) -> Option> { + for i in &self.funcs { + if i.get_name() == funcname { + return Some(Box::new(i.clone())); + } + } + None + } + + fn has_attr(&self, attrname: &str) -> Option { + for i in &self.attr { + if i.name == attrname { + return Some(i.ty.clone()); + } + } + None + } + + fn get_name(&self) -> &str { + &self.origin_name + } + + fn get_id(&self) -> usize { + self.name + } +} + lazy_static! { - pub static ref INT_TYPE: Type = Type::Common(CommonType::new(INT_ID_POS, "int".to_string())); - pub static ref FLOAT_TYPE: Type = - Type::Common(CommonType::new(FLOAT_ID_POS, "float".to_string())); - pub static ref STR_TYPE: Type = Type::Common(CommonType::new(STR_ID_POS, "str".to_string())); - pub static ref BOOL_TYPE: Type = Type::Common(CommonType::new(BOOL_ID_POS, "bool".to_string())); + pub static ref INT_TYPE: Type = Box::new(CommonType::new(INT_ID_POS, "int")); + pub static ref FLOAT_TYPE: Type = Box::new(CommonType::new(FLOAT_ID_POS, "float")); + pub static ref STR_TYPE: Type = Box::new(CommonType::new(STR_ID_POS, "str")); + pub static ref BOOL_TYPE: Type = Box::new(CommonType::new(BOOL_ID_POS, "bool")); } pub struct SymScope { prev_scope: Option>>, sym_map: HashMap, scope_sym_id: usize, - types: HashMap, + types: HashMap, funcs: HashMap>, vars: HashMap, - modules: HashMap, + modules: HashMap, } impl SymScope { @@ -175,32 +175,26 @@ impl SymScope { Some(prev_scope) => { ret.scope_sym_id = prev_scope.as_ref().borrow().scope_sym_id; } - None => { - ret.add_type(INT_TYPE.clone()); - ret.add_type(FLOAT_TYPE.clone()); - ret.add_type(BOOL_TYPE.clone()); - ret.add_type(STR_TYPE.clone()); - } + None => {} } ret } /// import the module defined in rust - pub fn import_native_module(&mut self, id: usize, stdlib: &'static StdlibNode) { + pub fn import_native_module(&mut self, id: usize, stdlib: &'static Stdlib) { self.modules.insert(id, stdlib); } pub fn import_prelude(&mut self, const_pool: &ValuePool) { - let funcs = &STDLIB_LIST - .sons - .get("prelude") - .unwrap() - .lock() - .unwrap() - .functions; + let funcs = &STDLIB_ROOT.sub_modules.get("prelude").unwrap().functions; for i in funcs { - let idx = self.insert_sym(const_pool.name_pool[&i.name]); - self.add_func(idx, Box::new((*i).clone())); + let idx = self.insert_sym(const_pool.name_pool[i.0]); + self.add_func(idx, Box::new((*i.1).clone())); + } + let types = &STDLIB_ROOT.sub_modules.get("prelude").unwrap().classes; + for i in types { + let idx = self.insert_sym(const_pool.name_pool[i.0]); + self.add_type(idx, Box::new((*i.1).clone())); } } @@ -263,16 +257,11 @@ impl SymScope { self.vars.insert(id, v); } - pub fn add_type(&mut self, t: Type) { - match t { - Type::Common(t) => { - self.types.insert(t.name, t); - } - _ => {} - } + pub fn add_type(&mut self, id: usize, t: Type) { + self.types.insert(id, t); } - pub fn get_type(&self, id: usize) -> CommonType { + pub fn get_type(&self, id: usize) -> Type { return self.types.get(&id).unwrap().clone(); } diff --git a/rust/src/compiler/token.rs b/rust/src/compiler/token.rs index a0f74610..0deb005d 100644 --- a/rust/src/compiler/token.rs +++ b/rust/src/compiler/token.rs @@ -131,74 +131,73 @@ pub enum TokenType { impl Display for TokenType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let res: String; - match self { - TokenType::Dot => res = ".".to_string(), - TokenType::Comma => res = ",".to_string(), - TokenType::LeftBigBrace => res = "{".to_string(), - TokenType::RightBigBrace => res = "}".to_string(), - TokenType::LeftMiddleBrace => res = "[".to_string(), - TokenType::RightMiddleBrace => res = "]".to_string(), - TokenType::LeftSmallBrace => res = "(".to_string(), - TokenType::RightSmallBrace => res = ")".to_string(), - TokenType::Add => res = "+".to_string(), - TokenType::Sub => res = "-".to_string(), - TokenType::Mul => res = "*".to_string(), - TokenType::Div => res = "/".to_string(), - TokenType::Mod => res = "%".to_string(), - TokenType::ExactDiv => res = "//".to_string(), - TokenType::BitNot => res = "~".to_string(), - TokenType::BitLeftShift => res = "<<".to_string(), - TokenType::BitRightShift => res = ">>".to_string(), - TokenType::BitAnd => res = "&".to_string(), - TokenType::BitOr => res = "|".to_string(), - TokenType::Xor => res = "^".to_string(), - TokenType::Power => res = "**".to_string(), - TokenType::SelfAdd => res = "+=".to_string(), - TokenType::SelfSub => res = "-=".to_string(), - TokenType::SelfMul => res = "*=".to_string(), - TokenType::SelfDiv => res = "/=".to_string(), - TokenType::SelfExactDiv => res = "//=".to_string(), - TokenType::SelfMod => res = "%=".to_string(), - TokenType::SelfPower => res = "**=".to_string(), - TokenType::SelfBitLeftShift => res = "<<=".to_string(), - TokenType::SelfBitRightShift => res = ">>=".to_string(), - TokenType::SelfBitAnd => res = "&=".to_string(), - TokenType::SelfBitOr => res = "|=".to_string(), - TokenType::SelfXor => res = "^=".to_string(), - TokenType::IntValue => res = "integer".to_string(), - TokenType::StringValue => res = "string".to_string(), - TokenType::FloatValue => res = "float".to_string(), - TokenType::LongIntValue => res = "long integer".to_string(), - TokenType::Assign => res = "=".to_string(), - TokenType::Store => res = ":=".to_string(), - TokenType::Equal => res = "==".to_string(), - TokenType::NotEqual => res = "!=".to_string(), - TokenType::Greater => res = ">".to_string(), - TokenType::Less => res = "<".to_string(), - TokenType::LessEqual => res = "<=".to_string(), - TokenType::GreaterEqual => res = ">=".to_string(), - TokenType::Not => res = "!".to_string(), - TokenType::Or => res = "||".to_string(), - TokenType::And => res = "&&".to_string(), - TokenType::Colon => res = ":".to_string(), - TokenType::Semicolon => res = ";".to_string(), - TokenType::ID => res = "identifier".to_string(), - TokenType::While => res = "while".to_string(), - TokenType::For => res = "for".to_string(), - TokenType::If => res = "if".to_string(), - TokenType::Else => res = "else".to_string(), - TokenType::Class => res = "class".to_string(), - TokenType::Match => res = "match".to_string(), - TokenType::Func => res = "func".to_string(), - TokenType::EndOfLine => res = "EOL".to_string(), - TokenType::EndOfFile => res = "EOF".to_string(), - TokenType::Import => res = "import".to_string(), - TokenType::Arrow => res = "->".to_string(), - TokenType::Return => res = "return".to_string(), - TokenType::SelfAnd => res = "&&=".to_string(), - TokenType::SelfOr => res = "||=".to_string(), - } + let res = match self { + TokenType::Dot => ".", + TokenType::Comma => ",", + TokenType::LeftBigBrace => "{", + TokenType::RightBigBrace => "}", + TokenType::LeftMiddleBrace => "[", + TokenType::RightMiddleBrace => "]", + TokenType::LeftSmallBrace => "(", + TokenType::RightSmallBrace => ")", + TokenType::Add => "+", + TokenType::Sub => "-", + TokenType::Mul => "*", + TokenType::Div => "/", + TokenType::Mod => "%", + TokenType::ExactDiv => "//", + TokenType::BitNot => "~", + TokenType::BitLeftShift => "<<", + TokenType::BitRightShift => ">>", + TokenType::BitAnd => "&", + TokenType::BitOr => "|", + TokenType::Xor => "^", + TokenType::Power => "**", + TokenType::SelfAdd => "+=", + TokenType::SelfSub => "-=", + TokenType::SelfMul => "*=", + TokenType::SelfDiv => "/=", + TokenType::SelfExactDiv => "//=", + TokenType::SelfMod => "%=", + TokenType::SelfPower => "**=", + TokenType::SelfBitLeftShift => "<<=", + TokenType::SelfBitRightShift => ">>=", + TokenType::SelfBitAnd => "&=", + TokenType::SelfBitOr => "|=", + TokenType::SelfXor => "^=", + TokenType::IntValue => "integer", + TokenType::StringValue => "string", + TokenType::FloatValue => "float", + TokenType::LongIntValue => "long integer", + TokenType::Assign => "=", + TokenType::Store => ":=", + TokenType::Equal => "==", + TokenType::NotEqual => "!=", + TokenType::Greater => ">", + TokenType::Less => "<", + TokenType::LessEqual => "<=", + TokenType::GreaterEqual => ">=", + TokenType::Not => "!", + TokenType::Or => "||", + TokenType::And => "&&", + TokenType::Colon => ":", + TokenType::Semicolon => ";", + TokenType::ID => "identifier", + TokenType::While => "while", + TokenType::For => "for", + TokenType::If => "if", + TokenType::Else => "else", + TokenType::Class => "class", + TokenType::Match => "match", + TokenType::Func => "func", + TokenType::EndOfLine => "EOL", + TokenType::EndOfFile => "EOF", + TokenType::Import => "import", + TokenType::Arrow => "->", + TokenType::Return => "return", + TokenType::SelfAnd => "&&=", + TokenType::SelfOr => "||=", + }; write!(f, "{}", res) } } @@ -249,7 +248,7 @@ macro_rules! check_braces_match { }, )* _ => { - panic!("unmatched {}", $brace_record.c) + unreachable!() } } }} @@ -461,7 +460,7 @@ impl TokenLex<'_> { '&', ), _ => { - panic!("Not a symbol.Compiler error") + unreachable!() } }) } diff --git a/rust/src/tvm.rs b/rust/src/tvm.rs index cdaa39a5..6b2672c6 100644 --- a/rust/src/tvm.rs +++ b/rust/src/tvm.rs @@ -68,48 +68,14 @@ impl Content { } /// reduce the duplicate code to solve the operator running -macro_rules! binary_opcode { +macro_rules! operator_opcode { ($trait_used:ident, $sself:expr) => {{ - let t2 = $sself.dynadata.obj_stack.pop(); - let t1 = $sself.dynadata.obj_stack.pop(); - if t1.is_none() || t2.is_none() { - return Err(RuntimeError::new( - Box::new($sself.run_contnet.clone()), - ErrorInfo::new(gettext!(VM_DATA_NUMBER, 2), gettext(VM_ERROR)), - )); - } - let t1 = t1.unwrap(); - let t2 = t2.unwrap(); - let ret = t1.$trait_used(t2); + let ret = types::$trait_used(&mut $sself.dynadata); match ret { Err(e) => { return Err(RuntimeError::new(Box::new($sself.run_contnet.clone()), e)); } - Ok(t) => { - $sself.dynadata.obj_stack.push(t); - } - } - }}; -} - -macro_rules! unary_opcode { - ($trait_used:ident, $sself:expr) => {{ - let t1 = $sself.dynadata.obj_stack.pop(); - if t1.is_none() { - return Err(RuntimeError::new( - Box::new($sself.run_contnet.clone()), - ErrorInfo::new(gettext!(VM_DATA_NUMBER, 1), gettext(VM_ERROR)), - )); - } - let t1 = t1.unwrap(); - let ret = t1.$trait_used(); - match ret { - Err(e) => { - return Err(RuntimeError::new(Box::new($sself.run_contnet.clone()), e)); - } - Ok(t) => { - $sself.dynadata.obj_stack.push(t); - } + Ok(_) => {} } }}; } @@ -140,23 +106,23 @@ impl<'a> Vm<'a> { pub fn run(&mut self) -> Result<(), RuntimeError> { while self.pc < self.static_data.inst.len() { match self.static_data.inst[self.pc].opcode { - codegen::Opcode::Add => binary_opcode!(add, self), - codegen::Opcode::Sub => binary_opcode!(sub, self), - codegen::Opcode::Mul => binary_opcode!(mul, self), - codegen::Opcode::Div => binary_opcode!(div, self), - codegen::Opcode::ExtraDiv => binary_opcode!(extra_div, self), - codegen::Opcode::Mod => binary_opcode!(modd, self), - codegen::Opcode::Gt => binary_opcode!(gt, self), - codegen::Opcode::Lt => binary_opcode!(lt, self), - codegen::Opcode::Ge => binary_opcode!(ge, self), - codegen::Opcode::Le => binary_opcode!(le, self), - codegen::Opcode::Eq => binary_opcode!(eq, self), - codegen::Opcode::Ne => binary_opcode!(ne, self), - codegen::Opcode::And => binary_opcode!(and, self), - codegen::Opcode::Or => binary_opcode!(or, self), - codegen::Opcode::Power => binary_opcode!(power, self), - codegen::Opcode::Not => unary_opcode!(not, self), - codegen::Opcode::Xor => binary_opcode!(xor, self), + 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 => { let ret = self.dynadata.frames_stack.pop(); @@ -175,11 +141,11 @@ impl<'a> Vm<'a> { self.static_data.constpool.intpool[self.static_data.inst[self.pc].operand], ))); } - codegen::Opcode::BitAnd => binary_opcode!(bit_and, self), - codegen::Opcode::BitOr => binary_opcode!(bit_or, self), - codegen::Opcode::BitNot => unary_opcode!(bit_not, self), - codegen::Opcode::BitLeftShift => binary_opcode!(bit_left_shift, self), - codegen::Opcode::BitRightShift => binary_opcode!(bit_right_shift, self), + 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 => { @@ -198,11 +164,18 @@ impl<'a> Vm<'a> { codegen::Opcode::LoadBigInt => {} codegen::Opcode::Empty => {} codegen::Opcode::SelfNegative => { - unary_opcode!(self_negative, self); + operator_opcode!(self_negative, self); + } + codegen::Opcode::CallNative => { + match STD_FUNC_TABLE.with(|std| -> RuntimeResult<()> { + std.borrow()[self.static_data.inst[self.pc].operand](&mut self.dynadata) + }) { + Ok(_) => {} + Err(e) => { + return Err(RuntimeError::new(Box::new(self.run_contnet.clone()), e)); + } + } } - codegen::Opcode::CallNative => unsafe { - STD_FUNC_TABLE[self.static_data.inst[self.pc].operand](&mut self.dynadata)?; - }, } self.pc += 1; } diff --git a/rust/src/tvm/stdlib.rs b/rust/src/tvm/stdlib.rs index b9d72093..ee6086c5 100644 --- a/rust/src/tvm/stdlib.rs +++ b/rust/src/tvm/stdlib.rs @@ -1 +1,6 @@ +use crate::base::stdlib::Stdlib; +use derive::def_module; + pub mod prelude; + +def_module!(module_name = std, submodules = [prelude]); diff --git a/rust/src/tvm/stdlib/prelude.rs b/rust/src/tvm/stdlib/prelude.rs index b7179e75..8c28c1b5 100644 --- a/rust/src/tvm/stdlib/prelude.rs +++ b/rust/src/tvm/stdlib/prelude.rs @@ -1,7 +1,17 @@ -use crate::{base::error::RunResult, tvm::DynaData}; +use crate::base::stdlib::*; +use crate::{base::error::*, tvm::DynaData}; +use derive::{def_module, trc_function}; -pub fn tvm_print(dydata: &mut DynaData) -> RunResult<()> { - let obj = dydata.obj_stack.pop(); - print!("{}", obj.unwrap()); - Ok(()) +#[trc_function] +pub fn print(obj: any) -> void { + print!("{}", obj); } + +#[trc_function] +pub fn println(obj: any) -> void { + println!("{}", obj); +} + +def_module!(module_name = prelude, functions = [print => print, println => print], classes = [ + Trcint => int +]); diff --git a/rust/src/tvm/types.rs b/rust/src/tvm/types.rs index 4c965ad7..312a2cf3 100644 --- a/rust/src/tvm/types.rs +++ b/rust/src/tvm/types.rs @@ -1,4 +1,5 @@ -use crate::base::error; +use crate::base::error::*; +use crate::tvm::DynaData; use downcast_rs::{impl_downcast, Downcast}; use gettextrs::gettext; @@ -9,24 +10,19 @@ pub mod trcfloat; pub mod trcint; pub mod trcstr; -macro_rules! unsupported_operator { - ($operator_name:expr, $sself:expr) => { - Err(error::ErrorInfo::new( - gettext!( - error::OPERATOR_IS_NOT_SUPPORT, - $operator_name, - $sself.get_type_name() - ), - gettext(error::SYNTAX_ERROR), - )) - }; -} - /// help to generate the same error reporter functions macro_rules! batch_unsupported_operators { ($($traie_name:ident => $oper_name:expr),*) => { - $(fn $traie_name(&self, _ :Box) -> TypeError { - unsupported_operator!($oper_name, self) + $( + fn $traie_name(&self, _:Box) -> RuntimeResult> { + return Err(ErrorInfo::new( + gettext!( + OPERATOR_IS_NOT_SUPPORT, + $oper_name, + self.get_type_name() + ), + gettext(SYNTAX_ERROR), + )); })* }; } @@ -35,26 +31,26 @@ macro_rules! batch_unsupported_operators { macro_rules! impl_oper { // for unsupported operator in rust ($trait_oper_fn_name:ident, $oper:ident, $error_oper_name:expr, $self_type:ident, $newtype:ident, $whether_throw_error:tt) => { - fn $trait_oper_fn_name(&self, other:Box) -> TypeError { + fn $trait_oper_fn_name(&self, other:Box) -> RuntimeResult> { match other.downcast_ref::<$self_type>() { Some(v) => { - Ok(Box::new($newtype::new($oper(self.value.clone(), v.value.clone())$whether_throw_error))) + return Ok(Box::new($newtype::new($oper(self._value.clone(), v._value.clone())$whether_throw_error))); }, None => { - Err(ErrorInfo::new(gettext!(OPERATOR_IS_NOT_SUPPORT, $error_oper_name, other.get_type_name()), gettext(OPERATOR_ERROR))) + return Err(ErrorInfo::new(gettext!(OPERATOR_IS_NOT_SUPPORT, $error_oper_name, other.get_type_name()), gettext(OPERATOR_ERROR))) } } } }; // for supported operator in rust ($trait_oper_fn_name:ident, $oper:tt, $error_oper_name:expr, $self_type:ident, $newtype:ident) => { - fn $trait_oper_fn_name(&self, other:Box) -> TypeError { + fn $trait_oper_fn_name(&self, other:Box) -> RuntimeResult> { match other.downcast_ref::<$self_type>() { Some(v) => { - Ok(Box::new($newtype::new(self.value $oper v.value))) + return Ok(Box::new($newtype::new(self._value $oper v._value))); }, None => { - Err(ErrorInfo::new(gettext!(OPERATOR_IS_NOT_SUPPORT, $error_oper_name, other.get_type_name()), gettext(OPERATOR_ERROR))) + return Err(ErrorInfo::new(gettext!(OPERATOR_IS_NOT_SUPPORT, $error_oper_name, other.get_type_name()), gettext(OPERATOR_ERROR))) } } } @@ -62,12 +58,6 @@ macro_rules! impl_oper { } #[macro_export] -/// use tvm::types::batch_impl_opers; -/// batch_impl_opers!( -/// add => +, "+", TrcInt, TrcInt, -/// sub => -, "-", TrcInt, TrcInt, -/// mul => *, "*", TrcInt, TrcInt -/// ); macro_rules! batch_impl_opers { ($($trait_oper_fn_name:ident => $oper:tt, $error_oper_name:expr, $self_type:ident, $newtype:ident),*) => { $( @@ -79,13 +69,41 @@ macro_rules! batch_impl_opers { #[macro_export] macro_rules! impl_single_oper { ($trait_oper_fn_name:ident, $oper:tt, $error_oper_name:expr, $self_type:ident, $newtype:ident) => { - fn $trait_oper_fn_name(&self) -> TypeError { - Ok(Box::new($newtype::new($oper self.value))) + fn $trait_oper_fn_name(&self) -> RuntimeResult> { + return Ok(Box::new($newtype::new($oper self._value))); } }; } -type TypeError = Result, error::ErrorInfo>; +macro_rules! gen_interface { + ($funcname:ident, 2) => { + pub fn $funcname(dydata: &mut DynaData) -> RuntimeResult<()> { + let t2 = dydata.obj_stack.pop(); + let t1 = dydata.obj_stack.pop(); + if t2.is_none() || t1.is_none() { + return Err(ErrorInfo::new( + gettext!(VM_DATA_NUMBER, 2), + gettext(VM_ERROR), + )); + } + dydata.obj_stack.push(t1.unwrap().$funcname(t2.unwrap())?); + Ok(()) + } + }; + ($funcname:ident, 1) => { + pub fn $funcname(dydata: &mut DynaData) -> RuntimeResult<()> { + let t1 = dydata.obj_stack.pop(); + if t1.is_none() { + return Err(ErrorInfo::new( + gettext!(VM_DATA_NUMBER, 1), + gettext(VM_ERROR), + )); + } + dydata.obj_stack.push(t1.unwrap().$funcname()?); + Ok(()) + } + }; +} pub trait TrcObj: Downcast + std::fmt::Display { batch_unsupported_operators!( @@ -111,19 +129,52 @@ pub trait TrcObj: Downcast + std::fmt::Display { bit_right_shift => ">>" ); - fn not(&self) -> TypeError { - unsupported_operator!("!", self) + fn not(&self) -> RuntimeResult> { + return Err(ErrorInfo::new( + gettext!(OPERATOR_IS_NOT_SUPPORT, "!", self.get_type_name()), + gettext(SYNTAX_ERROR), + )); } - fn bit_not(&self) -> TypeError { - unsupported_operator!("~", self) + fn bit_not(&self) -> RuntimeResult> { + return Err(ErrorInfo::new( + gettext!(OPERATOR_IS_NOT_SUPPORT, "~", self.get_type_name()), + gettext(SYNTAX_ERROR), + )); } - fn self_negative(&self) -> TypeError { - unsupported_operator!("-", self) + fn self_negative(&self) -> RuntimeResult> { + return Err(ErrorInfo::new( + gettext!(OPERATOR_IS_NOT_SUPPORT, "-", self.get_type_name()), + gettext(SYNTAX_ERROR), + )); } fn get_type_name(&self) -> &str; } impl_downcast!(TrcObj); + +gen_interface!(add, 2); +gen_interface!(sub, 2); +gen_interface!(mul, 2); +gen_interface!(div, 2); +gen_interface!(extra_div, 2); +gen_interface!(modd, 2); +gen_interface!(power, 2); +gen_interface!(gt, 2); +gen_interface!(lt, 2); +gen_interface!(eq, 2); +gen_interface!(ne, 2); +gen_interface!(ge, 2); +gen_interface!(le, 2); +gen_interface!(and, 2); +gen_interface!(or, 2); +gen_interface!(bit_and, 2); +gen_interface!(bit_or, 2); +gen_interface!(xor, 2); +gen_interface!(bit_left_shift, 2); +gen_interface!(bit_right_shift, 2); +gen_interface!(self_negative, 1); +gen_interface!(not, 1); +gen_interface!(bit_not, 1); diff --git a/rust/src/tvm/types/trcbool.rs b/rust/src/tvm/types/trcbool.rs index 11aac55e..d38e4495 100644 --- a/rust/src/tvm/types/trcbool.rs +++ b/rust/src/tvm/types/trcbool.rs @@ -1,13 +1,20 @@ -use super::{TrcObj, TypeError}; +use super::TrcObj; +use crate::base::error::*; use crate::base::error::{ErrorInfo, OPERATOR_ERROR, OPERATOR_IS_NOT_SUPPORT}; -use crate::{batch_impl_opers, impl_oper, impl_single_oper}; +use crate::base::stdlib::*; +use crate::compiler::token::TokenType; +use crate::{batch_impl_opers, hash_map, impl_oper, impl_single_oper}; +use derive::{trc_class, trc_method}; use gettextrs::gettext; +use std::collections::hash_map::HashMap; use std::fmt::Display; +#[trc_class] pub struct TrcBool { - pub value: bool, + _value: bool, } +#[trc_method] impl TrcObj for TrcBool { fn get_type_name(&self) -> &str { "bool" @@ -22,7 +29,7 @@ impl TrcObj for TrcBool { impl Display for TrcBool { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if self.value { + if self._value { write!(f, "True") } else { write!(f, "False") @@ -32,6 +39,10 @@ impl Display for TrcBool { impl TrcBool { pub fn new(value: bool) -> TrcBool { - Self { value } + Self { _value: value } + } + + fn override_export() -> HashMap { + hash_map![] } } diff --git a/rust/src/tvm/types/trcfloat.rs b/rust/src/tvm/types/trcfloat.rs index e96b148d..e439113e 100644 --- a/rust/src/tvm/types/trcfloat.rs +++ b/rust/src/tvm/types/trcfloat.rs @@ -1,17 +1,28 @@ use super::TrcObj; +use crate::base::error::*; +use crate::base::stdlib::*; +use crate::compiler::token::TokenType; +use crate::hash_map; use crate::impl_single_oper; -use crate::tvm::types::TypeError; -use crate::{base::error::*, batch_impl_opers, impl_oper}; +use crate::{batch_impl_opers, impl_oper}; +use derive::trc_class; +use derive::trc_method; use gettextrs::gettext; +use std::collections::hash_map::HashMap; use std::fmt::Display; +#[trc_class] pub struct TrcFloat { - pub value: f64, + _value: f64, } impl TrcFloat { pub fn new(value: f64) -> TrcFloat { - Self { value } + Self { _value: value } + } + + fn override_export() -> HashMap { + hash_map![] } } @@ -25,6 +36,7 @@ fn div_float(a: f64, b: f64) -> Result { Ok(a / b) } +#[trc_method] impl TrcObj for TrcFloat { fn get_type_name(&self) -> &str { "float" @@ -40,6 +52,6 @@ impl TrcObj for TrcFloat { impl Display for TrcFloat { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.value) + write!(f, "{}", self._value) } } diff --git a/rust/src/tvm/types/trcint.rs b/rust/src/tvm/types/trcint.rs index b0a2cd7e..62ae946b 100644 --- a/rust/src/tvm/types/trcint.rs +++ b/rust/src/tvm/types/trcint.rs @@ -1,23 +1,28 @@ -use std::fmt::Display; - use super::trcfloat::TrcFloat; -use super::{TrcObj, TypeError}; +use super::TrcObj; +use crate::base::stdlib::*; +use crate::compiler::token::TokenType; +use crate::hash_map; use crate::impl_single_oper; -use crate::{ - base::error::{ - ErrorInfo, OPERATOR_ERROR, OPERATOR_IS_NOT_SUPPORT, ZERO_DIV, ZERO_DIVSION_ERROR, - }, - batch_impl_opers, impl_oper, -}; +use crate::{base::error::*, batch_impl_opers, impl_oper}; +use derive::trc_class; +use derive::trc_method; use gettextrs::gettext; +use std::collections::hash_map::HashMap; +use std::fmt::Display; +#[trc_class] pub struct TrcInt { - pub value: i64, + _value: i64, } impl TrcInt { pub fn new(value: i64) -> TrcInt { - TrcInt { value } + TrcInt { _value: value } + } + + fn override_export() -> HashMap { + hash_map![] } } @@ -66,10 +71,11 @@ fn power_int(a: i64, b: i64) -> i64 { impl Display for TrcInt { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.value) + write!(f, "{}", self._value) } } +#[trc_method] impl TrcObj for TrcInt { fn get_type_name(&self) -> &str { "int" diff --git a/rust/src/tvm/types/trcstr.rs b/rust/src/tvm/types/trcstr.rs index 6db0e3f5..4ee78804 100644 --- a/rust/src/tvm/types/trcstr.rs +++ b/rust/src/tvm/types/trcstr.rs @@ -1,16 +1,24 @@ use super::TrcObj; -use crate::{base::error::*, batch_impl_opers, impl_oper, tvm::types::TypeError}; +use crate::base::stdlib::*; +use crate::compiler::token::TokenType; +use crate::hash_map; +use crate::tvm::DynaData; +use crate::{base::error::*, batch_impl_opers, impl_oper}; +use derive::{trc_class, trc_function, trc_method}; use gettextrs::gettext; +use std::collections::hash_map::HashMap; use std::fmt::Display; +#[trc_class] pub struct TrcStr { - value: String, + _value: String, } fn cat_string(a: String, b: String) -> String { format!("{}{}", a, b) } +#[trc_method] impl TrcObj for TrcStr { fn get_type_name(&self) -> &str { "str" @@ -22,12 +30,16 @@ impl TrcObj for TrcStr { impl Display for TrcStr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.value) + write!(f, "{}", self._value) } } impl TrcStr { pub fn new(value: String) -> Self { - Self { value } + Self { _value: value } + } + + fn override_export() -> HashMap { + hash_map![] } }