Skip to content

Commit

Permalink
增加模块系统
Browse files Browse the repository at this point in the history
  • Loading branch information
limuy2022 committed Feb 1, 2024
1 parent 8debe05 commit 15dd4e8
Show file tree
Hide file tree
Showing 10 changed files with 293 additions and 56 deletions.
Binary file modified rust/locales/zh_CN/LC_MESSAGES/trans.mo
Binary file not shown.
9 changes: 9 additions & 0 deletions rust/locales/zh_CN/LC_MESSAGES/trans.po
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,12 @@ msgstr "类型错误"
msgid "Type {} and {} are not the same"
msgstr "类型{}和{}不同"

msgid "ArgumentError"
msgstr "参数错误"

msgid "expect {}.But given {}"
msgstr "期望{}.但是输入{}"

msgid "Expect type {}.But given type {}"
msgstr "期望类型{}.但是传入类型是{}"

3 changes: 3 additions & 0 deletions rust/src/base/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub const ZERO_DIVSION_ERROR: &str = "ZeroDivisionError";
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 STRING_WITHOUT_END: &str = "this string should be ended with {}";
pub const UNMATCHED_BRACE: &str = "{} is unmatched";
Expand All @@ -25,6 +26,8 @@ pub const IN_MODULE: &str = "In module {}";
pub const SYMBOL_NOT_FOUND: &str = "Symbol {} not found";
pub const SYMBOL_REDEFINED: &str = "Symbol {} redefined";
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 {}";

#[derive(Debug)]
pub struct ErrorInfo {
Expand Down
139 changes: 138 additions & 1 deletion rust/src/base/stdlib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,138 @@
pub const STDLIB_LIST: Vec<String> = vec![];
use crate::{
base::error::{ARGUMENT_ERROR, ARGU_NUMBER, EXPECT_TYPE},
compiler::scope::{Type, TypeAllowNull},
tvm::{stdlib::prelude::*, DynaData},
};
use lazy_static::lazy_static;
use std::{
collections::{HashMap, HashSet},
sync::Mutex,
};

use super::{
codegen::{Inst, Opcode},
error::{ErrorInfo, RunResult},
};

type StdlibFunc = fn(DynaData) -> RunResult<()>;

#[derive(Hash, PartialEq, Eq, Clone, Debug)]
pub struct RustFunction {
pub name: String,
pub buildin_id: usize,
pub ptr: StdlibFunc,
pub argvs_type: Vec<Type>,
pub return_type: TypeAllowNull,
}

pub trait FunctionInterface {
fn check_argvs(&self, argvs: Vec<Type>) -> Result<(), ErrorInfo>;
fn get_return_type(&self) -> &TypeAllowNull;
}

impl FunctionInterface for RustFunction {
fn check_argvs(&self, argvs: Vec<Type>) -> 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 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),
));
}
}
Ok(())
}

fn get_return_type(&self) -> &TypeAllowNull {
&self.return_type
}
}

pub struct RustClass {
pub name: String,
pub members: HashMap<String, String>,
pub functions: HashSet<RustFunction>,
}

lazy_static! {
static ref STD_FUNC_ID: Mutex<usize> = Mutex::new(0);
}

impl RustFunction {
pub fn new(
name: String,
ptr: StdlibFunc,
argvs_type: Vec<Type>,
return_type: TypeAllowNull,
) -> RustFunction {
let mut lock = STD_FUNC_ID.lock().unwrap();
let tmp = *lock;
*lock += 1;
RustFunction {
name,
buildin_id: tmp,
ptr,
return_type,
argvs_type,
}
}
}

#[derive(Debug, Clone)]
pub struct StdlibNode {
pub name: String,
pub sons: HashMap<String, StdlibNode>,
pub functions: HashSet<RustFunction>,
}

impl StdlibNode {
pub fn new(name: String) -> StdlibNode {
StdlibNode {
name,
sons: HashMap::new(),
functions: HashSet::new(),
}
}

pub fn add_module(&mut self, name: String) -> StdlibNode {
let ret = StdlibNode::new(name.clone());
self.sons.insert(name, ret.clone());
ret
}

pub fn add_function(&mut self, name: RustFunction) {
self.functions.insert(name);
}

pub fn get_module<T: Iterator<Item = String>>(&self, mut path: T) -> Option<&StdlibNode> {
let item = path.next();
if item.is_none() {
return Some(self);
}
let item = item.unwrap();
return self.sons.get(&item).unwrap().get_module(path);
}
}

pub fn init() -> StdlibNode {
// init stdlib
let mut stdlib = StdlibNode::new("std".to_string());
let mut prelude = stdlib.add_module("prelude".to_string());
prelude.add_function(RustFunction::new(
"print".to_string(),
tvm_print,
vec![Type::Any],
TypeAllowNull::No,
));
stdlib
}

lazy_static! {
pub static ref STDLIB_LIST: StdlibNode = init();
}
59 changes: 30 additions & 29 deletions rust/src/compiler/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +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::STDLIB_LIST;
use crate::base::{codegen::StaticData, error::*};
use gettextrs::gettext;
use std::cell::RefCell;
Expand Down Expand Up @@ -43,8 +44,8 @@ macro_rules! TmpExpeFunctionGen {
}
return TryErr!(istry,
Box::new(self.token_lexer.compiler_data.content.clone()),
ErrorInfo::new(gettext!(TYPE_NOT_THE_SAME, self.get_type_name(ty_now),
self.get_type_name(ty_after)), gettextrs::gettext(TYPE_ERROR)))
ErrorInfo::new(gettext!(TYPE_NOT_THE_SAME, ty_now,
ty_after), gettextrs::gettext(TYPE_ERROR)))
})*
_ => {
self.token_lexer.next_back(next_sym);
Expand All @@ -68,8 +69,8 @@ macro_rules! ExprGen {
if t1 != t2 {
return TryErr!(istry,
Box::new(self.token_lexer.compiler_data.content.clone()),
ErrorInfo::new(gettext!(TYPE_NOT_THE_SAME, self.get_type_name(t1),
self.get_type_name(t2)), gettextrs::gettext(TYPE_ERROR)))
ErrorInfo::new(gettext!(TYPE_NOT_THE_SAME, t1,
t2), gettextrs::gettext(TYPE_ERROR)))
}
Ok(t1)
}
Expand All @@ -79,20 +80,23 @@ macro_rules! ExprGen {
impl<'a> AstBuilder<'a> {
pub fn new(token_lexer: TokenLex<'a>) -> Self {
let root_scope = Rc::new(RefCell::new(SymScope::new(None)));
AstBuilder {
// 为root scope添加prelude
let mut ret = AstBuilder {
token_lexer,
staticdata: StaticData::new(),
self_scope: root_scope,
};
for i in &STDLIB_LIST.sons.get("prelude").unwrap().functions {
ret.token_lexer
.compiler_data
.const_pool
.add_id(i.name.clone());
}
}

fn get_type_name(&self, ty: TypeAllowNull) -> String {
match ty {
TypeAllowNull::Yes(ty) => {
self.token_lexer.compiler_data.const_pool.id_name[ty.name].clone()
}
TypeAllowNull::No => "null".to_string(),
}
ret.self_scope
.as_ref()
.borrow_mut()
.import_prelude(&ret.token_lexer.compiler_data.const_pool);
ret
}

ExprGen!(expr9, expr9_, factor, TokenType::Power => Opcode::Power);
Expand Down Expand Up @@ -165,7 +169,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(tt));
return Ok(TypeAllowNull::Yes(Type::Common(tt)));
} else {
self.token_lexer.next_back(t.clone());
return TryErr!(
Expand Down Expand Up @@ -281,14 +285,17 @@ impl<'a> AstBuilder<'a> {
.replace('.', "/"),
);
// the standard library first

if let InputSource::File(now_module_path) =
self.token_lexer.compiler_data.option.inputsource.clone()
{
let mut now_module_path = std::path::PathBuf::from(now_module_path);
now_module_path.pop();
now_module_path = now_module_path.join(path);
if now_module_path.exists() {}
let strpath = path.to_str().unwrap();
if strpath.get(0..3) == Some("std") {
} else {
if let InputSource::File(now_module_path) =
self.token_lexer.compiler_data.option.inputsource.clone()
{
let mut now_module_path = std::path::PathBuf::from(now_module_path);
now_module_path.pop();
now_module_path = now_module_path.join(path);
if now_module_path.exists() {}
}
}
Ok(())
}
Expand Down Expand Up @@ -372,12 +379,6 @@ impl<'a> AstBuilder<'a> {
if let Ok(_) = self.expr(true) {
return Ok(());
}
if let Ok(_) = self.val(false) {
let t = self.token_lexer.next_token()?;
if t.tp == TokenType::LeftSmallBrace {
// func call
}
}
return Err(RuntimeError::new(
Box::new(self.token_lexer.compiler_data.content.clone()),
ErrorInfo::new(
Expand Down
Loading

0 comments on commit 15dd4e8

Please sign in to comment.