Skip to content

Commit

Permalink
fix scope bug
Browse files Browse the repository at this point in the history
  • Loading branch information
limuy2022 committed Mar 1, 2024
1 parent 826520b commit 88ef2e7
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 40 deletions.
16 changes: 11 additions & 5 deletions rust/src/base/stdlib.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -97,7 +97,7 @@ pub trait ClassClone {
pub trait ClassInterface: Downcast + Sync + Send + ClassClone + Debug + Display {
fn has_func(&self, funcname: &str) -> Option<Box<dyn FunctionInterface>>;

fn has_attr(&self, attrname: &str) -> Option<Type>;
fn has_attr(&self, attrname: &str) -> Option<ScopeAllocClassId>;

fn get_id(&self) -> usize;

Expand Down Expand Up @@ -195,10 +195,10 @@ impl ClassInterface for RustClass {
None
}

fn has_attr(&self, attrname: &str) -> Option<Type> {
fn has_attr(&self, attrname: &str) -> Option<ScopeAllocClassId> {
let ret = &self.members.get(attrname);
match ret {
Some(i) => Some(i.ty.clone()),
Some(i) => Some(i.ty),
None => None,
}
}
Expand Down Expand Up @@ -308,8 +308,14 @@ impl AnyType {
}
}

/// 获取到标准库的类的个数,从而区分标准库和用户自定义的类
/// 获取到标准库的类的个数,从而区分标准库和用户自定义的类,其实也相当于获取第一个用户可以定义的类的ID
pub fn get_stdclass_end() -> usize {
static STD_NUM: OnceLock<usize> = 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";
55 changes: 38 additions & 17 deletions rust/src/compiler/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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<usize> {
self.self_scope.as_ref().borrow().get_type(
*self
.token_lexer
Expand All @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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 {
Expand All @@ -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());
Expand Down Expand Up @@ -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()),
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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]
Expand Down
34 changes: 24 additions & 10 deletions rust/src/compiler/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ impl FunctionInterface for Function {

#[derive(Clone, Debug)]
pub struct Var {
pub ty: Box<dyn ClassInterface>,
pub ty: ScopeAllocClassId,
pub name: String,
}

impl Var {
pub fn new(ty: Box<dyn ClassInterface>, name: String) -> Self {
pub fn new(ty: ScopeAllocClassId, name: String) -> Self {
Self { ty, name }
}
}
Expand Down Expand Up @@ -118,10 +118,10 @@ impl ClassInterface for CommonType {
None
}

fn has_attr(&self, attrname: &str) -> Option<Type> {
fn has_attr(&self, attrname: &str) -> Option<ScopeAllocClassId> {
for i in &self.attr {
if i.name == attrname {
return Some(i.ty.clone());
return Some(i.ty);
}
}
None
Expand Down Expand Up @@ -150,13 +150,17 @@ pub struct SymScope {
sym_map: HashMap<ConstPoolIndexTy, ScopeAllocIdTy>,
// 当前作用域要分配的下一个ID,也就是当前作用域的最大id+1
scope_sym_id: ScopeAllocIdTy,
// ID到class id的映射
types: HashMap<ScopeAllocIdTy, ScopeAllocClassId>,
// ID到函数的映射
funcs: HashMap<ScopeAllocIdTy, Box<dyn FunctionInterface>>,
// token id
vars: HashMap<ScopeAllocIdTy, Var>,
// 由token id到模块的映射
modules: HashMap<ScopeAllocIdTy, &'static Stdlib>,
// 当前作用域可以分配的下一个class id
types_id: ScopeAllocClassId,
// 用户自定义的类型储存位置
types_custom_store: HashMap<ScopeAllocClassId, CommonType>,
}

Expand Down Expand Up @@ -230,11 +234,21 @@ impl SymScope {
*t
}

pub fn get_sym_idx(&self, id: usize) -> Option<usize> {
pub fn get_var(&self, id: ScopeAllocIdTy) -> Option<Var> {
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<usize> {
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),
Expand All @@ -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<usize> {
self.types.get(&id).copied()
}

pub fn get_scope_last_idx(&self) -> usize {
Expand Down Expand Up @@ -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));
}
}
18 changes: 10 additions & 8 deletions rust/src/tvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
}
}

0 comments on commit 88ef2e7

Please sign in to comment.