Skip to content

Commit cb7ff3d

Browse files
committed
fix(semantic): 修复变量错误的作用域处理导致函数定义异常问题.
1 parent af83a36 commit cb7ff3d

11 files changed

Lines changed: 138 additions & 41 deletions

File tree

lib/math.exf

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,81 @@ function sqrt(n) {
3434
}
3535

3636
return x;
37-
}
37+
}
38+
39+
function cbrt(n) {
40+
if (n == 0) { return 0; }
41+
42+
var is_negative = 0;
43+
if (n < 0) {
44+
is_negative = 1;
45+
n = 0 - n;
46+
}
47+
48+
var x = n;
49+
var last = 0;
50+
var precision = 0.000001;
51+
52+
while {
53+
last = x;
54+
x = (2 * x + n / (x * x)) / 3;
55+
56+
var diff = x - last;
57+
if (diff < 0) { diff = 0 - diff; }
58+
if (diff < precision) { break; }
59+
}
60+
61+
if (is_negative == 1) {
62+
return 0 - x;
63+
}
64+
return x;
65+
}
66+
67+
function log(n) {
68+
if (n <= 0) { return 0.0; }
69+
70+
var x = 1.0;
71+
if (n > 100.0) { x = 5.0; }
72+
73+
var last = 0.0;
74+
var precision = 0.000001;
75+
76+
while {
77+
last = x;
78+
var ex = exp(x);
79+
x = x + (n / ex) - 1.0;
80+
81+
var diff = x - last;
82+
if (diff < 0) { diff = 0.0 - diff; }
83+
if (diff < precision) { break; }
84+
}
85+
return x;
86+
}
87+
88+
function exp(x) {
89+
var sum = 1.0;
90+
var term = 1.0;
91+
var i = 1.0;
92+
var precision = 0.000001;
93+
94+
while {
95+
term = term * x / i;
96+
sum = sum + term;
97+
98+
var abs_term = term;
99+
if (abs_term < 0) { abs_term = 0.0 - abs_term; }
100+
if (abs_term < precision) { break; }
101+
102+
i = i + 1.0;
103+
if (i > 100.0) { break; }
104+
}
105+
return sum;
106+
}
107+
108+
function pow(base, exp_val) {
109+
if (base == 0.0) { return 0.0; }
110+
if (exp_val == 0.0) { return 1.0; }
111+
112+
var res = exp(exp_val * log(base));
113+
return res;
114+
}

src/compiler/ast/ssa_ir.rs

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -250,28 +250,17 @@ pub struct Function {
250250
}
251251

252252
#[derive(Debug, Clone)]
253-
#[allow(dead_code)] //TODO
254-
pub struct Code {
255-
codes: OpCodeTable,
253+
pub struct ValueAlloc {
256254
values: SlotMap<DefaultKey, Value>,
257-
pub(crate) funcs: Vec<Function>,
258-
root: bool, // 是否是根脚本上下文 (true: 根上下文|false: 函数上下文)
259255
}
260256

261-
impl Code {
262-
pub fn new(root: bool) -> Self {
263-
Self {
264-
codes: OpCodeTable::new(),
257+
impl ValueAlloc {
258+
pub fn new() -> Self {
259+
Self{
265260
values: SlotMap::new(),
266-
funcs: Vec::new(),
267-
root,
268261
}
269262
}
270263

271-
pub const fn get_code_table(&mut self) -> &mut OpCodeTable {
272-
&mut self.codes
273-
}
274-
275264
pub fn find_value_key(&mut self, name: &SmolStr) -> Option<DefaultKey> {
276265
for (key, value) in &mut self.values {
277266
if value.token.text() == name {
@@ -293,6 +282,28 @@ impl Code {
293282
};
294283
self.values.insert(va)
295284
}
285+
}
286+
287+
#[derive(Debug, Clone)]
288+
#[allow(dead_code)] //TODO
289+
pub struct Code {
290+
codes: OpCodeTable,
291+
pub(crate) funcs: Vec<Function>,
292+
root: bool, // 是否是根脚本上下文 (true: 根上下文|false: 函数上下文)
293+
}
294+
295+
impl Code {
296+
pub fn new(root: bool) -> Self {
297+
Self {
298+
codes: OpCodeTable::new(),
299+
funcs: Vec::new(),
300+
root,
301+
}
302+
}
303+
304+
pub const fn get_code_table(&mut self) -> &mut OpCodeTable {
305+
&mut self.codes
306+
}
296307

297308
pub fn add_function(&mut self, func: Function) {
298309
self.funcs.push(func);

src/compiler/ast/vm_ir.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,13 @@ impl IrFunction {
193193
match code.1 {
194194
OpCode::Push(_, imm) => {
195195
if let Operand::Val(key) = imm {
196-
let index = locals.get_index(key).unwrap();
197-
codes_builder.push(ByteCode::StoreGlobal(*index));
196+
if let Some(index) = locals.get_index(key) {
197+
codes_builder.push(ByteCode::Store(*index));
198+
}else if let Some(index) = globals.get_index(key) {
199+
codes_builder.push(ByteCode::StoreGlobal(*index));
200+
}else {
201+
unreachable!()
202+
}
198203
} else {
199204
let index = constant_table.add_operand(imm, code0);
200205
codes_builder.push(ByteCode::Push(index));

src/compiler/parser/expression.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ fn expr_bp(
138138
let mut p_count: u64 = 0;
139139
let mut done: bool = false;
140140
loop {
141-
if token.t_type == TokenType::Operator && token.text() == "," {
141+
if token.t_type == TokenType::Operator && token.text() == "," && p_count == 0 {
142142
break;
143143
}
144144
if token.t_type == LP && token.text() == "(" {

src/compiler/semantic/block.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
use crate::compiler::ast::ssa_ir::OpCode::Push;
2-
use crate::compiler::ast::ssa_ir::{Code, LocalMap, OpCode, OpCodeTable, Operand};
2+
use crate::compiler::ast::ssa_ir::{LocalMap, OpCode, OpCodeTable, Operand, ValueAlloc};
33
use crate::compiler::ast::ASTStmtTree;
44
use crate::compiler::lints::Lint::UnusedExpression;
55
use crate::compiler::parser::ParserError;
66
use crate::compiler::semantic::expression::{check_expr_operand, expr_semantic, lower_expr};
77
use crate::compiler::semantic::judgment::judgment_semantic;
8+
use crate::compiler::semantic::loop_back::loop_back_semantic;
89
use crate::compiler::semantic::r#while::while_semantic;
910
use crate::compiler::semantic::var::var_semantic;
1011
use crate::compiler::semantic::Semantic;
1112
use crate::compiler::Compiler;
12-
use crate::compiler::semantic::loop_back::loop_back_semantic;
1313

1414
pub fn block_semantic(
1515
semantic: &mut Semantic,
1616
stmt_tree: Vec<ASTStmtTree>,
17-
code: &mut Code,
17+
code: &mut ValueAlloc,
1818
locals: &mut LocalMap,
1919
) -> Result<OpCodeTable, ParserError> {
2020
let mut opcodes = OpCodeTable::new();

src/compiler/semantic/expression.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::compiler::ast::ssa_ir::Operand::ImmNumFlot;
33
use crate::compiler::ast::ssa_ir::ValueGuessType::{
44
Bool, Float, Null, Number, Ref, String, This, Unknown,
55
};
6-
use crate::compiler::ast::ssa_ir::{Code, OpCode, OpCodeTable, Operand, ValueGuessType};
6+
use crate::compiler::ast::ssa_ir::{OpCode, OpCodeTable, Operand, ValueAlloc, ValueGuessType};
77
use crate::compiler::ast::{ASTExprTree, ExprOp};
88
use crate::compiler::lexer::{Token, TokenType};
99
use crate::compiler::parser::ParserError;
@@ -266,7 +266,7 @@ fn guess_type(
266266
fn lower_ref(
267267
semantic: &mut Semantic,
268268
expr_tree: &ASTExprTree,
269-
code: &mut Code,
269+
code: &mut ValueAlloc,
270270
) -> Result<(SmolStr, OpCodeTable), ParserError> {
271271
let mut opcode_table = OpCodeTable::new();
272272
let mut path = SmolStrBuilder::new();
@@ -328,7 +328,7 @@ const fn operand_to_guess(operand: &Operand) -> ValueGuessType {
328328
pub fn lower_expr(
329329
semantic: &mut Semantic,
330330
expr_tree: &ASTExprTree,
331-
code: &mut Code,
331+
code: &mut ValueAlloc,
332332
store: Option<Operand>,
333333
) -> Result<(Operand, ValueGuessType, OpCodeTable), ParserError> {
334334
let mut opcode_table = OpCodeTable::new();
@@ -531,7 +531,7 @@ pub fn check_expr_operand(operand: &Operand, op_code: &OpCode, call_count: i32)
531531
pub fn expr_semantic(
532532
semantic: &mut Semantic,
533533
expr: Option<ASTExprTree>,
534-
code: &mut Code,
534+
code: &mut ValueAlloc,
535535
) -> Result<(Operand, ValueGuessType, OpCodeTable), ParserError> {
536536
let guess_type;
537537
let operand: Operand;

src/compiler/semantic/function.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::compiler::ast::ssa_ir::{Code, Function, LocalMap, OpCode, OpCodeTable, Operand, ValueGuessType};
1+
use crate::compiler::ast::ssa_ir::{Code, Function, LocalMap, OpCode, OpCodeTable, Operand, ValueAlloc, ValueGuessType};
22
use crate::compiler::ast::{ASTExprTree, ASTStmtTree};
33
use crate::compiler::lexer::Token;
44
use crate::compiler::parser::symbol_table::ElementType::Argument;
@@ -65,22 +65,25 @@ pub fn function_semantic(
6565
.add_context(ContextType::Func);
6666
let mut tables = OpCodeTable::new();
6767
let mut locals = LocalMap::new();
68+
let mut value_alloc = ValueAlloc::new();
6869

6970
let args_len = arguments.len();
7071
for i in arguments {
7172
if let ASTExprTree::Var(token) = i {
7273
let token_c = token.clone();
73-
let key = code.alloc_value(token, ValueGuessType::Unknown);
74+
let key = value_alloc.alloc_value(token, ValueGuessType::Unknown);
7475
locals.add_local(key);
7576
semantic
7677
.compiler_data()
7778
.symbol_table
7879
.add_element(token_c.value().unwrap(), Argument);
7980
tables.add_opcode(OpCode::LoadLocal(None, key, Operand::Val(key)));
81+
}else {
82+
unreachable!()
8083
}
8184
}
8285

83-
let blk = block_semantic(semantic, body, code, &mut locals)?;
86+
let blk = block_semantic(semantic, body, &mut value_alloc, &mut locals)?;
8487
tables.append_code(&blk);
8588

8689
semantic.compiler_data().symbol_table.exit_context();

src/compiler/semantic/judgment.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::compiler::ast::ssa_ir::{Code, LocalMap, OpCode, OpCodeTable, ValueGuessType};
1+
use crate::compiler::ast::ssa_ir::{LocalMap, OpCode, OpCodeTable, ValueAlloc, ValueGuessType};
22
use crate::compiler::ast::{ASTExprTree, ASTStmtTree};
33
use crate::compiler::parser::ParserError;
44
use crate::compiler::semantic::block::block_semantic;
@@ -10,7 +10,7 @@ pub fn judgment_semantic(
1010
expr: &ASTExprTree,
1111
then_body: Vec<ASTStmtTree>,
1212
else_body: Vec<ASTStmtTree>,
13-
code: &mut Code,
13+
code: &mut ValueAlloc,
1414
locals: &mut LocalMap,
1515
) -> Result<OpCodeTable, ParserError> {
1616
let exp = lower_expr(semantic, expr, code, None)?;

src/compiler/semantic/mod.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ mod r#while;
77
mod judgment;
88
mod loop_back;
99

10-
use crate::compiler::ast::ssa_ir::{Code, LocalMap, OpCode, ValueGuessType};
10+
use crate::compiler::ast::ssa_ir::{Code, LocalMap, OpCode, ValueAlloc, ValueGuessType};
1111
use crate::compiler::ast::ASTStmtTree;
1212
use crate::compiler::file::SourceFile;
1313
use crate::compiler::lints::Lint::UnusedExpression;
@@ -38,17 +38,18 @@ impl<'a> Semantic<'a> {
3838
pub fn semantic(&mut self, stmt_tree: ASTStmtTree) -> Result<(Code,LocalMap), ParserError> {
3939
let code = &mut Code::new(true);
4040
let mut global = LocalMap::new();
41+
let value_alloc = &mut ValueAlloc::new();
4142

4243
if let ASTStmtTree::Root(stmts) = stmt_tree {
4344
for stmt in stmts {
4445
match stmt {
4546
ASTStmtTree::Var { name, value } => {
46-
let opcode = var_semantic(self, name, value, code, true, &mut global)?;
47+
let opcode = var_semantic(self, name, value, value_alloc, true, &mut global)?;
4748
code.get_code_table().append_code(&opcode);
4849
}
4950
ASTStmtTree::Expr(expr) => {
5051
let ref_expr = expr.clone();
51-
let ret_m = expr_semantic(self, Some(expr), code)?;
52+
let ret_m = expr_semantic(self, Some(expr), value_alloc)?;
5253
code.get_code_table().append_code(&ret_m.2);
5354
if !check_expr_operand(&ret_m.0, &OpCode::Store(None), 0) {
5455
Compiler::warning_info_expr(
@@ -68,15 +69,15 @@ impl<'a> Semantic<'a> {
6869
self.compiler_data()
6970
.symbol_table
7071
.add_element(name, ElementType::Library);
71-
code.alloc_value(token, ValueGuessType::Ref);
72+
value_alloc.alloc_value(token, ValueGuessType::Ref);
7273
}
7374
ASTStmtTree::Loop {
7475
token: _token,
7576
cond,
7677
body,
7778
is_easy,
7879
} => {
79-
let ret_m = while_semantic(self, &cond, body, code, &mut global, is_easy)?;
80+
let ret_m = while_semantic(self, &cond, body, value_alloc, &mut global, is_easy)?;
8081
code.get_code_table().append_code(&ret_m);
8182
}
8283
ASTStmtTree::Function { name, args, body } => {
@@ -86,7 +87,7 @@ impl<'a> Semantic<'a> {
8687
native_function_semantic(self, name, &args, code)?;
8788
}
8889
ASTStmtTree::If {cond,then_body,else_body} => {
89-
let ret_m = judgment_semantic(self, &cond, then_body, else_body, code, &mut global)?;
90+
let ret_m = judgment_semantic(self, &cond, then_body, else_body, value_alloc, &mut global)?;
9091
code.get_code_table().append_code(&ret_m);
9192
}
9293
_ => todo!(),

src/compiler/semantic/var.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::compiler::ast::ssa_ir::OpCode::{LoadGlobal, LoadLocal};
2-
use crate::compiler::ast::ssa_ir::{Code, LocalMap, OpCodeTable};
2+
use crate::compiler::ast::ssa_ir::{LocalMap, OpCodeTable, ValueAlloc};
33
use crate::compiler::ast::ASTExprTree;
44
use crate::compiler::lexer::Token;
55
use crate::compiler::parser::symbol_table::ElementType::Value;
@@ -11,7 +11,7 @@ pub fn var_semantic(
1111
semantic: &mut Semantic,
1212
name: Token,
1313
init_var: Option<ASTExprTree>,
14-
code: &mut Code,
14+
code: &mut ValueAlloc,
1515
root: bool,
1616
locals:&mut LocalMap
1717
) -> Result<OpCodeTable, ParserError> {

0 commit comments

Comments
 (0)