diff --git a/rust/src/base/stdlib.rs b/rust/src/base/stdlib.rs index 864ab5c4..344211a0 100644 --- a/rust/src/base/stdlib.rs +++ b/rust/src/base/stdlib.rs @@ -1,7 +1,7 @@ use super::{codegen::Opcode, error::*}; use crate::{ compiler::{ - scope::{Type, TypeAllowNull, Var}, + scope::{ScopeAllocClassId, Type, TypeAllowNull, Var}, token::TokenType, }, tvm::DynaData, @@ -97,7 +97,7 @@ pub trait ClassClone { pub trait ClassInterface: Downcast + Sync + Send + ClassClone + Debug + Display { fn has_func(&self, funcname: &str) -> Option>; - fn has_attr(&self, attrname: &str) -> Option; + fn has_attr(&self, attrname: &str) -> Option; fn get_id(&self) -> usize; @@ -195,10 +195,10 @@ impl ClassInterface for RustClass { None } - fn has_attr(&self, attrname: &str) -> Option { + fn has_attr(&self, attrname: &str) -> Option { let ret = &self.members.get(attrname); match ret { - Some(i) => Some(i.ty.clone()), + Some(i) => Some(i.ty), None => None, } } @@ -308,8 +308,14 @@ impl AnyType { } } -/// 获取到标准库的类的个数,从而区分标准库和用户自定义的类 +/// 获取到标准库的类的个数,从而区分标准库和用户自定义的类,其实也相当于获取第一个用户可以定义的类的ID pub fn get_stdclass_end() -> usize { static STD_NUM: OnceLock = OnceLock::new(); *STD_NUM.get_or_init(|| unsafe { STD_CLASS_TABLE.len() }) } + +pub const INT: &str = "int"; +pub const FLOAT: &str = "float"; +pub const BOOL: &str = "bool"; +pub const CHAR: &str = "char"; +pub const STR: &str = "str"; diff --git a/rust/src/compiler/ast.rs b/rust/src/compiler/ast.rs index 76487643..42c76311 100644 --- a/rust/src/compiler/ast.rs +++ b/rust/src/compiler/ast.rs @@ -6,7 +6,7 @@ use super::{ use crate::base::{ codegen::{Inst, Opcode, StaticData, VmStackType, NO_ARG}, error::*, - stdlib::{get_stdlib, RustFunction}, + stdlib::{get_stdlib, RustFunction, BOOL, CHAR, FLOAT, INT, STR}, }; use rust_i18n::t; use std::{cell::RefCell, rc::Rc}; @@ -268,7 +268,7 @@ impl<'a> AstBuilder<'a> { } } - fn get_type_id(&self, ty_name: &str) -> usize { + fn get_type_id(&self, ty_name: &str) -> Option { self.self_scope.as_ref().borrow().get_type( *self .token_lexer @@ -281,15 +281,15 @@ impl<'a> AstBuilder<'a> { } fn convert_to_vm_type(&self, ty: usize) -> VmStackType { - if ty == self.get_type_id("int") { + if ty == self.get_type_id(INT).unwrap() { VmStackType::Int - } else if ty == self.get_type_id("float") { + } else if ty == self.get_type_id(FLOAT).unwrap() { VmStackType::Float - } else if ty == self.get_type_id("str") { + } else if ty == self.get_type_id(STR).unwrap() { VmStackType::Str - } else if ty == self.get_type_id("char") { + } else if ty == self.get_type_id(CHAR).unwrap() { VmStackType::Char - } else if ty == self.get_type_id("bool") { + } else if ty == self.get_type_id(BOOL).unwrap() { VmStackType::Bool } else { VmStackType::Object @@ -313,7 +313,7 @@ impl<'a> AstBuilder<'a> { let t = self.token_lexer.next_token()?; if t.tp == TokenType::ID { let token_data = t.data.unwrap(); - let idx = self.self_scope.as_ref().borrow().get_sym_idx(token_data); + let idx = self.self_scope.as_ref().borrow().get_sym(token_data); if idx.is_none() { self.try_err( istry, @@ -353,9 +353,20 @@ impl<'a> AstBuilder<'a> { 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); - self.add_bycode(Opcode::LoadLocal, varidx); - let tt = self.self_scope.as_ref().borrow().get_type(varidx); + self.add_bycode(Opcode::LoadLocal, idx); + let tt = match self.self_scope.as_ref().borrow().get_var(idx) { + Some(v) => v.ty, + None => self.try_err( + istry, + ErrorInfo::new( + t!( + SYMBOL_NOT_FOUND, + "0" = self.token_lexer.compiler_data.const_pool.id_name[token_data] + ), + t!(SYMBOL_ERROR), + ), + )?, + }; Ok(TypeAllowNull::Yes(tt)) } } else { @@ -376,27 +387,27 @@ impl<'a> AstBuilder<'a> { TokenType::IntValue => { self.add_bycode(Opcode::LoadInt, t.data.unwrap()); self.process_info.new_type(VmStackType::Int); - Ok(TypeAllowNull::Yes(self.get_type_id("int"))) + Ok(TypeAllowNull::Yes(self.get_type_id(INT).unwrap())) } TokenType::FloatValue => { self.add_bycode(Opcode::LoadFloat, t.data.unwrap()); self.process_info.new_type(VmStackType::Float); - Ok(TypeAllowNull::Yes(self.get_type_id("float"))) + Ok(TypeAllowNull::Yes(self.get_type_id(FLOAT).unwrap())) } TokenType::StringValue => { self.add_bycode(Opcode::LoadString, t.data.unwrap()); self.process_info.new_type(VmStackType::Str); - Ok(TypeAllowNull::Yes(self.get_type_id("str"))) + Ok(TypeAllowNull::Yes(self.get_type_id(STR).unwrap())) } 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"))) + Ok(TypeAllowNull::Yes(self.get_type_id(CHAR).unwrap())) } 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"))) + Ok(TypeAllowNull::Yes(self.get_type_id(BOOL).unwrap())) } _ => { self.token_lexer.next_back(t.clone()); @@ -533,7 +544,7 @@ impl<'a> AstBuilder<'a> { let tt = self.token_lexer.next_token()?; match tt.tp { TokenType::Assign => { - let var = self.self_scope.as_ref().borrow().get_sym_idx(name); + let var = self.self_scope.as_ref().borrow().get_sym(name); if var.is_none() { return Err(RuntimeError::new( Box::new(self.token_lexer.compiler_data.context.clone()), @@ -628,6 +639,15 @@ mod tests { #[test] fn test_assign() { gen_test_env!(r#"a:=10"#, t); + t.generate_code().unwrap(); + assert_eq!( + t.staticdata.inst, + vec![ + Inst::new(Opcode::LoadInt, INT_VAL_POOL_ONE), + Inst::new(Opcode::MoveInt, NO_ARG), + Inst::new(Opcode::StoreLocal, 0) + ], + ) } #[test] @@ -767,6 +787,7 @@ mod tests { fn test_wrong_type() { gen_test_env!(r#"1.0+9"#, t); t.generate_code().unwrap(); + println!("{:?}", t.staticdata.inst); } #[test] diff --git a/rust/src/compiler/scope.rs b/rust/src/compiler/scope.rs index 042886c5..b5784dfc 100644 --- a/rust/src/compiler/scope.rs +++ b/rust/src/compiler/scope.rs @@ -62,12 +62,12 @@ impl FunctionInterface for Function { #[derive(Clone, Debug)] pub struct Var { - pub ty: Box, + pub ty: ScopeAllocClassId, pub name: String, } impl Var { - pub fn new(ty: Box, name: String) -> Self { + pub fn new(ty: ScopeAllocClassId, name: String) -> Self { Self { ty, name } } } @@ -118,10 +118,10 @@ impl ClassInterface for CommonType { None } - fn has_attr(&self, attrname: &str) -> Option { + fn has_attr(&self, attrname: &str) -> Option { for i in &self.attr { if i.name == attrname { - return Some(i.ty.clone()); + return Some(i.ty); } } None @@ -150,13 +150,17 @@ pub struct SymScope { sym_map: HashMap, // 当前作用域要分配的下一个ID,也就是当前作用域的最大id+1 scope_sym_id: ScopeAllocIdTy, + // ID到class id的映射 types: HashMap, + // ID到函数的映射 funcs: HashMap>, // token id vars: HashMap, // 由token id到模块的映射 modules: HashMap, + // 当前作用域可以分配的下一个class id types_id: ScopeAllocClassId, + // 用户自定义的类型储存位置 types_custom_store: HashMap, } @@ -230,11 +234,21 @@ impl SymScope { *t } - pub fn get_sym_idx(&self, id: usize) -> Option { + pub fn get_var(&self, id: ScopeAllocIdTy) -> Option { + match self.vars.get(&id) { + Some(v) => Some(v.clone()), + None => match self.prev_scope { + Some(ref prev_scope) => prev_scope.as_ref().borrow().get_var(id), + None => None, + }, + } + } + + pub fn get_sym(&self, id: usize) -> Option { let t = self.sym_map.get(&id); match t { None => match self.prev_scope { - Some(ref prev_scope) => prev_scope.as_ref().borrow().get_sym_idx(id), + Some(ref prev_scope) => prev_scope.as_ref().borrow().get_sym(id), None => None, }, Some(t) => Some(*t), @@ -253,8 +267,8 @@ impl SymScope { self.types.insert(id, t); } - pub fn get_type(&self, id: usize) -> usize { - *self.types.get(&id).unwrap() + pub fn get_type(&self, id: usize) -> Option { + self.types.get(&id).copied() } pub fn get_scope_last_idx(&self) -> usize { @@ -293,8 +307,8 @@ mod tests { root_scope.as_ref().borrow_mut().insert_sym(1); let mut son_scope = SymScope::new(Some(root_scope.clone())); son_scope.insert_sym(2); - assert_eq!(son_scope.get_sym_idx(2), Some(1)); + assert_eq!(son_scope.get_sym(2), Some(1)); drop(son_scope); - assert_eq!(root_scope.as_ref().borrow().get_sym_idx(1), Some(0)); + assert_eq!(root_scope.as_ref().borrow().get_sym(1), Some(0)); } } diff --git a/rust/src/tvm.rs b/rust/src/tvm.rs index 3954d9a7..b7076b15 100644 --- a/rust/src/tvm.rs +++ b/rust/src/tvm.rs @@ -256,11 +256,14 @@ impl<'a> Vm<'a> { Opcode::BitLeftShift => operator_opcode!(bit_left_shift, self), Opcode::BitRightShift => operator_opcode!(bit_right_shift, self), Opcode::LoadLocal => { - // self.dynadata.obj_stack.push( - // self.dynadata.var_store[self.static_data.inst[self.pc].operand].clone(), - // ); + self.dynadata + .obj_stack + .push(self.dynadata.var_store[self.static_data.inst[self.pc].operand]); + } + Opcode::StoreLocal => { + self.dynadata.var_store[self.static_data.inst[self.pc].operand] = + self.dynadata.obj_stack.pop().unwrap(); } - Opcode::StoreLocal => {} Opcode::LoadString => { self.dynadata.str_stack.push( self.static_data.constpool.stringpool @@ -530,16 +533,15 @@ mod tests { use crate::compiler::InputSource; use crate::compiler::Option; - fn gen_test_env(code: &str) -> StaticData { + fn gen_test_env(code: &str) -> Vm { let mut compiler = Compiler::new_string_compiler(Option::new(false, InputSource::StringInternal), code); - compiler.lex().unwrap() + Vm::new_init(compiler.lex().unwrap()) } #[test] fn test_vm() { - let staticdata = gen_test_env(r#"print("{},{},{},{}", 1, "h", 'p', true)"#); - let mut vm = Vm::new_init(staticdata); + let mut vm = gen_test_env(r#"print("{},{},{},{}", 1, "h", 'p', true)"#); vm.run().unwrap() } }