Skip to content

Commit e3fd4e4

Browse files
committed
feat(warn): 添加与补充部分警告.
对标准库不规范写法纠正
1 parent 1eb33e9 commit e3fd4e4

6 files changed

Lines changed: 76 additions & 4 deletions

File tree

lib/system.exf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ function println(output) {
77
print(output + "\n");
88
}
99

10-
function readline() {
10+
function readline {
1111
var line = "";
1212
var c = "";
1313
var newline = "\n";

src/compiler/lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,5 @@ declare_lint! {
3636
UnusedValue "unused-value",
3737
UnusedLibrary "unused-library",
3838
UnusedExpression "unused-expression",
39+
SyncRecursion "sync-recursion",
3940
}

src/compiler/parser/function.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
use crate::compiler::Compiler;
12
use crate::compiler::ast::{ASTExprTree, ASTStmtTree};
23
use crate::compiler::lexer::TokenType;
34
use crate::compiler::lexer::TokenType::{LP, LR};
5+
use crate::compiler::lints::Lint::FuncNoArg;
46
use crate::compiler::parser::ParserError::{Expected, IdentifierExpected, IllegalArgument};
57
use crate::compiler::parser::block::blk_eval;
68
use crate::compiler::parser::{Parser, ParserError, check_char};
9+
use smol_str::format_smolstr;
710

811
fn parser_argument(parser: &mut Parser) -> Result<Vec<ASTExprTree>, ParserError> {
912
let mut token = parser.next_parser_token()?;
@@ -82,8 +85,22 @@ pub fn func_eval(parser: &mut Parser) -> Result<ASTStmtTree, ParserError> {
8285
parser.cache = Some(token);
8386
args = vec![];
8487
} else {
88+
let pt = token.clone();
8589
parser.cache = Some(token);
8690
args = parser_argument(parser)?;
91+
if args.is_empty() && !is_native {
92+
Compiler::warning_info_expr(
93+
parser.file,
94+
format_smolstr!(
95+
"'function {}()' can be written as 'function {}'",
96+
name.text(),
97+
name.text()
98+
)
99+
.as_str(),
100+
&ASTExprTree::Literal(pt),
101+
FuncNoArg,
102+
);
103+
}
87104
}
88105
}
89106
TokenType::End => {
@@ -108,6 +125,11 @@ pub fn func_eval(parser: &mut Parser) -> Result<ASTStmtTree, ParserError> {
108125
} else {
109126
parser.cache = Some(token);
110127
let body = blk_eval(parser)?;
111-
Ok(ASTStmtTree::Function { name, sync: is_sync, args, body })
128+
Ok(ASTStmtTree::Function {
129+
name,
130+
sync: is_sync,
131+
args,
132+
body,
133+
})
112134
}
113135
}

src/compiler/parser/symbol_table.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ pub struct Element {
2929
pub struct Context {
3030
elements: Vec<Element>,
3131
ctxt_type: ContextType,
32+
pub func_sync: bool, // 仅当上下文类型为 func 时有意义
33+
pub func_name: SmolStr, // 同上
3234
}
3335

3436
#[derive(Debug, Clone)]
@@ -42,6 +44,8 @@ impl SymbolTable {
4244
table.contexts.push(Context {
4345
elements: vec![],
4446
ctxt_type: ContextType::Root,
47+
func_sync: false,
48+
func_name: SmolStr::new(""),
4549
});
4650
table
4751
}
@@ -73,6 +77,8 @@ impl SymbolTable {
7377
self.contexts.push(Context {
7478
elements: vec![],
7579
ctxt_type,
80+
func_name: SmolStr::new(""),
81+
func_sync: false,
7682
});
7783
}
7884

src/compiler/semantic/expression.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::compiler::Compiler;
12
use crate::compiler::ast::ssa_ir::OpCode::Push;
23
use crate::compiler::ast::ssa_ir::Operand::ImmNumFlot;
34
use crate::compiler::ast::ssa_ir::ValueGuessType::{
@@ -6,8 +7,9 @@ use crate::compiler::ast::ssa_ir::ValueGuessType::{
67
use crate::compiler::ast::ssa_ir::{OpCode, OpCodeTable, Operand, ValueAlloc, ValueGuessType};
78
use crate::compiler::ast::{ASTExprTree, ExprOp};
89
use crate::compiler::lexer::{Token, TokenType};
10+
use crate::compiler::lints::Lint::SyncRecursion;
911
use crate::compiler::parser::ParserError;
10-
use crate::compiler::parser::symbol_table::ElementType;
12+
use crate::compiler::parser::symbol_table::{ContextType, ElementType};
1113
use crate::compiler::semantic::Semantic;
1214
use crate::compiler::semantic::optimizer::{expr_optimizer, unary_optimizer};
1315
use slotmap::DefaultKey;
@@ -352,7 +354,23 @@ fn lower_ref(
352354
};
353355

354356
if let Some(base) = base {
355-
let full_path = format_smolstr!("{}/{}", base, token.text());
357+
let full_path = format_smolstr!("{base}/{}", token.text());
358+
359+
if file_base == base && let Some(context) = semantic
360+
.compiler_data()
361+
.symbol_table
362+
.get_context(&ContextType::Func)
363+
&& context.func_sync
364+
&& context.func_name.as_str() == token.text()
365+
{
366+
Compiler::warning_info_expr(
367+
semantic.file,
368+
"unsafe recursion in synchronized function.",
369+
right_tree,
370+
SyncRecursion,
371+
);
372+
}
373+
356374
opcode_table.add_opcode(Push(None, Operand::Reference(full_path)));
357375
return Ok((token.text().to_smolstr(), opcode_table));
358376
}
@@ -578,6 +596,23 @@ fn expr_call(
578596
.next()
579597
.unwrap_or(semantic.file.name.as_str());
580598
let full_path = format_smolstr!("{file_base}/{path}");
599+
600+
// 检查同步函数递归调用
601+
if let Some(context) = semantic
602+
.compiler_data()
603+
.symbol_table
604+
.get_context(&ContextType::Func)
605+
&& context.func_name == path
606+
&& context.func_sync
607+
{
608+
Compiler::warning_info_expr(
609+
semantic.file,
610+
"unsafe recursion in synchronized function.",
611+
name,
612+
SyncRecursion,
613+
);
614+
}
615+
581616
opcode_table.add_opcode(Push(None, Operand::Reference(full_path)));
582617
opcode_table.add_opcode(OpCode::Call(None, path.clone()));
583618
Ok((Operand::Call(path), Unknown, opcode_table))

src/compiler/semantic/function.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ pub fn function_semantic(
6969
.compiler_data()
7070
.symbol_table
7171
.add_context(ContextType::Func);
72+
let context = semantic
73+
.compiler_data()
74+
.symbol_table
75+
.get_context(&ContextType::Func)
76+
.unwrap();
77+
context.func_sync = sync;
78+
context.func_name = name.text().to_smolstr();
79+
7280
let mut tables = OpCodeTable::new();
7381
let mut locals = LocalMap::new();
7482
let mut value_alloc = ValueAlloc::new();

0 commit comments

Comments
 (0)