From 7f9d095e518412af3a659bcf34dc68eac11480d6 Mon Sep 17 00:00:00 2001 From: limuy Date: Tue, 6 Feb 2024 16:21:29 +0800 Subject: [PATCH] add static type check --- rust/Cargo.lock | 1 - rust/Cargo.toml | 1 - rust/derive/src/lib.rs | 4 ++-- rust/examples/expr.trc | 4 ++-- rust/src/base/stdlib.rs | 19 +++++++++++++++++ rust/src/compiler/ast.rs | 42 +++++++++++++++++++++++++++----------- rust/src/compiler/scope.rs | 30 ++++++++++++++++++++++++++- rust/src/compiler/token.rs | 5 ++++- rust/src/tvm/types.rs | 6 +++--- 9 files changed, 89 insertions(+), 23 deletions(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 6f5a9143..96695eb1 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1293,7 +1293,6 @@ dependencies = [ "lazy_static", "llvm-sys", "num-bigint", - "once_cell", "rand", "reqwest", "tokio", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 1edba210..cdb2b282 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -20,7 +20,6 @@ num-bigint = "0.4.4" reqwest = { version = "0.11.24", features = ["json", "multipart"] } tokio = { version = "1.36.0", features = ["full"] } llvm-sys = "170.0.1" -once_cell = "1.19.0" derive = { path = "./derive" } [profile.release] diff --git a/rust/derive/src/lib.rs b/rust/derive/src/lib.rs index a2a6a8d5..3cd79609 100644 --- a/rust/derive/src/lib.rs +++ b/rust/derive/src/lib.rs @@ -112,7 +112,7 @@ pub fn trc_class(_: TokenStream, input: TokenStream) -> TokenStream { // 因为很可能某个函数的参数就是标准库中的某个类型,所以我们需要先将类型导入到class_table中 let ret = quote!(#input use crate::base::stdlib::{RustClass, new_class_id, STD_CLASS_TABLE}; - use once_cell::sync::OnceCell; + use std::sync::OnceLock; impl #name { pub fn init_info() -> usize { use std::collections::hash_map::HashMap; @@ -144,7 +144,7 @@ pub fn trc_class(_: TokenStream, input: TokenStream) -> TokenStream { } pub fn export_info() -> usize { - static ID: OnceCell = OnceCell::new(); + static ID: OnceLock = OnceLock::new(); *ID.get_or_init(|| { let id = Self::init_info(); id diff --git a/rust/examples/expr.trc b/rust/examples/expr.trc index cbba7316..83e973ee 100644 --- a/rust/examples/expr.trc +++ b/rust/examples/expr.trc @@ -1,6 +1,6 @@ /* test expr */ -print(1+1) +print(1.0+9.0) print("hello") -#print("ppp"+1) +#print(1+"ppp") diff --git a/rust/src/base/stdlib.rs b/rust/src/base/stdlib.rs index 79eb6c5d..cac9630f 100644 --- a/rust/src/base/stdlib.rs +++ b/rust/src/base/stdlib.rs @@ -9,6 +9,7 @@ use crate::{ }; use downcast_rs::{impl_downcast, Downcast}; use lazy_static::lazy_static; +use std::sync::OnceLock; use std::{ cell::RefCell, collections::HashMap, @@ -103,6 +104,8 @@ pub trait ClassInterface: Downcast + Sync + Send + ClassClone + Debug + Display fn is_any(&self) -> bool { self.get_id() == 0 } + + fn get_override_func(&self, oper_token: TokenType) -> Option<&IOType>; } impl ClassClone for T @@ -197,6 +200,13 @@ impl ClassInterface for RustClass { fn get_id(&self) -> usize { self.id } + + fn get_override_func(&self, oper_token: TokenType) -> Option<&IOType> { + match self.overrides.get(&oper_token) { + Some(i) => Some(i), + None => None, + } + } } impl Display for RustClass { @@ -276,3 +286,12 @@ lazy_static! { RustClass::new("any", HashMap::new(), None, HashMap::new(), new_class_id()); pub static ref STDLIB_ROOT: Stdlib = crate::tvm::stdlib::init(); } + +/// 获取到标准库的类的个数,从而区分标准库和用户自定义的类 +pub fn get_stdclass_end() -> usize { + static STD_NUM: OnceLock = OnceLock::new(); + *STD_NUM.get_or_init(|| { + let mut num = STD_CLASS_TABLE.with(|std| std.borrow().len()); + num + }) +} diff --git a/rust/src/compiler/ast.rs b/rust/src/compiler/ast.rs index c9041c33..cd836ee4 100644 --- a/rust/src/compiler/ast.rs +++ b/rust/src/compiler/ast.rs @@ -33,22 +33,40 @@ macro_rules! tmp_expe_function_gen { let next_sym = self.token_lexer.next_token()?; match next_sym.tp { $($accepted_token => { - let ty_now = self.$next_item_func(istry)?; + let tya = self.$next_item_func(istry)?; self.add_bycode($add_opcode, NO_ARG); - let ty_after = self.$tmpfuncname(istry)?; - if let TypeAllowNull::No = ty_after { - return Ok(ty_now); + let tyb = self.$tmpfuncname(istry)?; + if let TypeAllowNull::No = tyb { + return Ok(tya); } - if let TypeAllowNull::No = ty_now { - return Ok(ty_now) + if let TypeAllowNull::No = tya { + return Ok(tya) } - if(ty_now.unwrap() == ty_after.unwrap()) { - return Ok(ty_now); - } - return try_err!(istry, + // 读取IOType检查 + let tya = tya.unwrap(); + let tyb = tyb.unwrap(); + let func_obj = self.self_scope.as_ref().borrow().get_class(tya).unwrap(); + let io_check = func_obj.get_override_func($accepted_token); + match io_check { + None => return try_err!(istry, Box::new(self.token_lexer.compiler_data.content.clone()), - ErrorInfo::new(gettext!(TYPE_NOT_THE_SAME, ty_now, - ty_after), gettextrs::gettext(TYPE_ERROR))) + ErrorInfo::new( + gettext!(OPERATOR_IS_NOT_SUPPORT, $accepted_token, func_obj.get_name()), + gettext(OPERATOR_ERROR), + ) + ), + Some(v) => { + if let Ok(_) = v.check_argvs(vec![tyb]) { + return Ok(v.return_type.clone()); + } + let func_objb = self.self_scope.as_ref().borrow().get_class(tyb).unwrap(); + return try_err!(istry, + Box::new(self.token_lexer.compiler_data.content.clone()), + ErrorInfo::new(gettext!(TYPE_NOT_THE_SAME, func_obj.get_name(), + func_objb.get_name()), gettextrs::gettext(TYPE_ERROR))) + + } + } })* _ => { self.token_lexer.next_back(next_sym); diff --git a/rust/src/compiler/scope.rs b/rust/src/compiler/scope.rs index 4e0b024f..0d189feb 100644 --- a/rust/src/compiler/scope.rs +++ b/rust/src/compiler/scope.rs @@ -1,6 +1,7 @@ use super::ValuePool; use crate::base::stdlib::{ - ClassInterface, FunctionInterface, IOType, Stdlib, STDLIB_ROOT, STD_CLASS_TABLE, + get_stdclass_end, ClassInterface, FunctionInterface, IOType, Stdlib, STDLIB_ROOT, + STD_CLASS_TABLE, }; use lazy_static::lazy_static; use std::{borrow::Borrow, cell::RefCell, collections::HashMap, fmt::Display, rc::Rc}; @@ -143,6 +144,10 @@ impl ClassInterface for CommonType { fn get_id(&self) -> usize { self.name } + + fn get_override_func(&self, oper_token: super::token::TokenType) -> Option<&IOType> { + None + } } pub struct SymScope { @@ -154,6 +159,7 @@ pub struct SymScope { vars: HashMap, modules: HashMap, types_id: usize, + types_custom_store: HashMap, } impl SymScope { @@ -166,6 +172,7 @@ impl SymScope { funcs: HashMap::new(), vars: HashMap::new(), modules: HashMap::new(), + types_custom_store: HashMap::new(), types_id: 0, }; match prev_scope { @@ -262,6 +269,27 @@ impl SymScope { pub fn get_scope_last_idx(&self) -> usize { self.scope_sym_id } + + pub fn get_class(&self, classid: usize) -> Option { + // 在标准库界限内 + if classid < get_stdclass_end() { + return Some(Box::new( + STD_CLASS_TABLE.with(|std| std.borrow()[classid].clone()), + )); + } + // 不存在的类 + if classid >= self.types_id { + return None; + } + let t = self.types.get(&classid); + return match t { + Some(t) => Some(Box::new(self.types_custom_store.get(t).unwrap().clone())), + None => match self.prev_scope { + Some(ref prev_scope) => prev_scope.as_ref().borrow().get_class(classid), + None => None, + }, + }; + } } #[cfg(test)] diff --git a/rust/src/compiler/token.rs b/rust/src/compiler/token.rs index e4959f29..298043c7 100644 --- a/rust/src/compiler/token.rs +++ b/rust/src/compiler/token.rs @@ -11,7 +11,7 @@ use gettextrs::gettext; use lazy_static::lazy_static; use std::{collections::HashMap, fmt::Display, process::exit}; -#[derive(PartialEq, Debug, Clone)] +#[derive(PartialEq, Debug, Clone, Hash, Eq)] pub enum TokenType { // -> Arrow, @@ -424,11 +424,14 @@ impl TokenLex<'_> { if c == '/' { return self.next_token(); } + self.compiler_data.input.unread(c); } else if c == '\0' { return Err(RuntimeError::new( Box::new(self.compiler_data.content.clone()), ErrorInfo::new(gettext(UNCLODED_COMMENT), gettext(SYNTAX_ERROR)), )); + } else if c == '\n' { + self.compiler_data.content.add_line(); } } } diff --git a/rust/src/tvm/types.rs b/rust/src/tvm/types.rs index fda2be7a..d41ad726 100644 --- a/rust/src/tvm/types.rs +++ b/rust/src/tvm/types.rs @@ -141,21 +141,21 @@ pub trait TrcObj: Downcast + std::fmt::Display + Debug { fn not(&self) -> RuntimeResult> { return Err(ErrorInfo::new( gettext!(OPERATOR_IS_NOT_SUPPORT, "!", self.get_type_name()), - gettext(SYNTAX_ERROR), + gettext(OPERATOR_ERROR), )); } fn bit_not(&self) -> RuntimeResult> { return Err(ErrorInfo::new( gettext!(OPERATOR_IS_NOT_SUPPORT, "~", self.get_type_name()), - gettext(SYNTAX_ERROR), + gettext(OPERATOR_ERROR), )); } fn self_negative(&self) -> RuntimeResult> { return Err(ErrorInfo::new( gettext!(OPERATOR_IS_NOT_SUPPORT, "-", self.get_type_name()), - gettext(SYNTAX_ERROR), + gettext(OPERATOR_ERROR), )); }