Skip to content

Commit e6f67c1

Browse files
committed
fix(executor): 修复赋值运算符的行为, 修复类型检查器的错误判断问题.
补充常量折叠优化器的计算.
1 parent 9b04ff3 commit e6f67c1

16 files changed

Lines changed: 225 additions & 69 deletions

File tree

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ expect-test = "1.5.1"
1111
linked-hash-map = "0.5.6"
1212
crossbeam-channel = "0.5.15"
1313

14+
[lib]
15+
name = "openex"
16+
path = "src/lib.rs"
17+
1418
[profile.release]
1519
debug = false
1620
strip = true

src/compiler/ast/ssa_ir.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub struct Value {
4848
pub enum OpCode {
4949
// Option<LocalAddr> 为各 IR 的逻辑地址
5050
LoadGlobal(Option<LocalAddr>, DefaultKey, Operand), // 栈顶元素加载到全局变量
51+
StoreGlobal(Option<LocalAddr>, DefaultKey, Operand), // 将一个全局变量加载到栈顶
5152
LoadLocal(Option<LocalAddr>, DefaultKey, Operand), // 栈顶元素加载到局部变量
5253
StoreLocal(Option<LocalAddr>, DefaultKey, Operand), // 将一个变量加载到栈顶
5354
Push(Option<LocalAddr>, Operand), // 将值压入操作栈
@@ -214,14 +215,14 @@ pub struct LocalMap {
214215

215216
impl LocalMap {
216217
pub fn new() -> LocalMap {
217-
Self {
218+
Self {
218219
locals: BTreeMap::new(),
219220
now_index: 0,
220221
}
221222
}
222223

223224
pub fn add_local(&mut self, local: DefaultKey) -> usize {
224-
self.locals.insert(local,self.now_index);
225+
self.locals.insert(local, self.now_index);
225226
let ret_m = self.now_index;
226227
self.now_index += 1;
227228
ret_m
@@ -237,7 +238,7 @@ pub struct Function {
237238
pub(crate) name: SmolStr,
238239
pub(crate) args: usize,
239240
pub(crate) codes: Option<OpCodeTable>, // 为 None 代表本地方法实现
240-
pub(crate) locals: LocalMap, // 局部变量表映射
241+
pub(crate) locals: LocalMap, // 局部变量表映射
241242
}
242243

243244
#[derive(Debug, Clone)]
@@ -305,6 +306,7 @@ macro_rules! mathch_opcodes {
305306
($expr: expr,$slot:ident,$stmt: expr) => {
306307
match $expr {
307308
OpCode::LoadGlobal($slot, ..)
309+
| OpCode::StoreGlobal($slot, ..)
308310
| OpCode::LoadLocal($slot, ..)
309311
| OpCode::StoreLocal($slot, ..)
310312
| OpCode::Push($slot, ..)

src/compiler/ast/vm_ir.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ fn opcode_to_vmir(code: OpCode) -> ByteCode {
108108
OpCode::Equ(_) => ByteCode::Equ,
109109
OpCode::Call(_, _imm) => ByteCode::Call,
110110
OpCode::Ref(_) => ByteCode::GetRef,
111+
111112
c => {
112113
dbg!(c);
113114
todo!()
@@ -154,6 +155,14 @@ impl IrFunction {
154155
let index = locals.get_index(&key).unwrap();
155156
self.codes.push(ByteCode::Store(*index));
156157
}
158+
OpCode::LoadGlobal(_, key, _) => {
159+
let index = locals.get_index(&key).unwrap();
160+
self.codes.push(ByteCode::LoadGlobal(*index));
161+
}
162+
OpCode::StoreGlobal(_, key, _) => {
163+
let index = locals.get_index(&key).unwrap();
164+
self.codes.push(ByteCode::StoreGlobal(*index));
165+
}
157166
c => {
158167
self.codes.push(opcode_to_vmir(c));
159168
}
@@ -227,6 +236,14 @@ impl VMIRTable {
227236
let index = locals.get_index(&key).unwrap();
228237
self.codes.push(ByteCode::StoreGlobal(*index));
229238
}
239+
OpCode::LoadGlobal(_, key, _) => {
240+
let index = locals.get_index(&key).unwrap();
241+
self.codes.push(ByteCode::LoadGlobal(*index));
242+
}
243+
OpCode::StoreGlobal(_, key, _) => {
244+
let index = locals.get_index(&key).unwrap();
245+
self.codes.push(ByteCode::StoreGlobal(*index));
246+
}
230247
c => {
231248
self.codes.push(opcode_to_vmir(c));
232249
}

src/compiler/lexer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ impl Token {
9898
}
9999

100100
pub fn value_float(&mut self) -> f64 {
101-
self.data.parse::<f64>().unwrap()
101+
f64::from_str(&self.data).unwrap_or(0.0)
102102
}
103103

104104
pub fn value_number(&mut self) -> i64 {

src/compiler/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::compiler::lints::Lint;
55
use crate::compiler::parser::symbol_table::SymbolTable;
66
use crate::compiler::parser::ParserError;
77
use std::collections::HashSet;
8-
use crate::compiler::ast::vm_ir::VMIRTable;
8+
use std::process::exit;
99

1010
pub(crate) mod ast;
1111
pub mod file;
@@ -239,7 +239,7 @@ impl Compiler {
239239
let vm_ir = file.compiler(&mut compiler).unwrap_or_else(|error| {
240240
Self::dump_parser_error(error, file);
241241
failed = true;
242-
VMIRTable::new()
242+
exit(-1);
243243
});
244244
if failed {
245245
continue;

src/compiler/semantic/expression.rs

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use crate::compiler::ast::ssa_ir::OpCode::Push;
2-
use crate::compiler::ast::ssa_ir::ValueGuessType::{
3-
Bool, Float, Null, Number, String, This, Unknown,
4-
};
2+
use crate::compiler::ast::ssa_ir::ValueGuessType::{Bool, Float, Null, Number, Ref, String, This, Unknown};
53
use crate::compiler::ast::ssa_ir::{Code, OpCode, OpCodeTable, Operand, ValueGuessType};
64
use crate::compiler::ast::{ASTExprTree, ExprOp};
75
use crate::compiler::lexer::{Token, TokenType};
@@ -72,6 +70,9 @@ fn guess_check_type(src: ValueGuessType, args: &[ValueGuessType]) -> bool {
7270
}
7371

7472
fn check_opts(op: &ExprOp, args: &[ExprOp]) -> bool {
73+
if matches!(op, ExprOp::Store | ExprOp::Equ | ExprOp::NotEqu) {
74+
return true;
75+
}
7576
for ty in args {
7677
if op == ty {
7778
return true;
@@ -115,6 +116,10 @@ fn guess_type(
115116
return Ok(Unknown);
116117
}
117118

119+
if matches!(op, ExprOp::Store) {
120+
return Ok(second);
121+
}
122+
118123
match first {
119124
Bool => {
120125
if guess_check_type(second, &[Bool])
@@ -136,9 +141,9 @@ fn guess_type(
136141
}
137142
String => {
138143
if guess_check_type(second, &[String, Float, Number, Null])
139-
&& check_opts(op, &[ExprOp::Add, ExprOp::Equ, ExprOp::NotEqu])
144+
&& check_opts(op, &[ExprOp::Add])
140145
{
141-
if check_opts(op, &[ExprOp::Equ, ExprOp::NotEqu]) {
146+
if check_opts(op, &[]) {
142147
Ok(Bool)
143148
} else {
144149
Ok(String)
@@ -248,7 +253,7 @@ fn lower_ref(
248253

249254
if matches!(left_tree, ASTExprTree::Call { .. }) || matches!(left_tree, ASTExprTree::This(_token)) ||
250255
matches!(left_tree, ASTExprTree::Var(_token)) {
251-
let mut table = lower_expr(semantic, left_tree, code)?.2;
256+
let mut table = lower_expr(semantic, left_tree, code, None)?.2;
252257
opcode_table.append_code(&mut table);
253258
}else {
254259
unreachable!()
@@ -279,10 +284,24 @@ fn lower_ref(
279284
Ok((path.finish(), opcode_table))
280285
}
281286

287+
fn operand_to_guess(operand: Operand) -> ValueGuessType {
288+
match operand {
289+
Operand::ImmBool(_) => Bool,
290+
Operand::Null => Null,
291+
Operand::This => This,
292+
Operand::ImmNum(_) => Number,
293+
Operand::ImmFlot(_) => Float,
294+
Operand::ImmStr(_) => String,
295+
Operand::Reference(_) => Ref,
296+
_=> Unknown,
297+
}
298+
}
299+
282300
pub(crate) fn lower_expr(
283301
semantic: &mut Semantic,
284302
expr_tree: &ASTExprTree,
285303
code: &mut Code,
304+
store: Option<Operand>,
286305
) -> Result<(Operand, ValueGuessType, OpCodeTable), ParserError> {
287306
let mut opcode_table = OpCodeTable::new();
288307
match expr_tree {
@@ -314,13 +333,13 @@ pub(crate) fn lower_expr(
314333
Ok((Operand::Null, Null, opcode_table))
315334
}
316335
_ => {
317-
todo!()
336+
unreachable!()
318337
}
319338
}
320339
}
321340
ASTExprTree::Ref(token) => {
322341
opcode_table.add_opcode(Push(None, Operand::Reference(token.text().to_smolstr())));
323-
Ok((Operand::Reference(token.text().to_smolstr()), ValueGuessType::Ref, opcode_table))
342+
Ok((Operand::Reference(token.text().to_smolstr()), Ref, opcode_table))
324343
}
325344
ASTExprTree::This(_token) => {
326345
opcode_table.add_opcode(Push(None, Operand::This));
@@ -331,7 +350,7 @@ pub(crate) fn lower_expr(
331350
op: u_op,
332351
code: u_code,
333352
} => {
334-
let mut a = lower_expr(semantic, u_code.as_ref(), code)?;
353+
let mut a = lower_expr(semantic, u_code.as_ref(), code,None)?;
335354
let g_type = guess_type_unary(u_token, a.1, u_op)?;
336355
if let Some(operand) = unary_optimizer(u_op, &a.0) {
337356
opcode_table.add_opcode(Push(None, operand));
@@ -347,24 +366,33 @@ pub(crate) fn lower_expr(
347366
left: e_left,
348367
right: e_right,
349368
} => {
350-
let mut left = lower_expr(semantic, e_left.as_ref(), code)?;
351-
let mut right = lower_expr(semantic, e_right.as_ref(), code)?;
352-
let left_opd = Box::new(left.0.clone());
369+
let mut right = lower_expr(semantic, e_right.as_ref(), code, None)?;
353370
let right_opd = Box::new(right.0.clone());
371+
let stores = if matches!(e_op,ExprOp::Store) {
372+
Some(right.0.clone())
373+
}else {
374+
None
375+
};
376+
let mut left = lower_expr(semantic, e_left.as_ref(), code, stores)?;
377+
378+
let left_opd = Box::new(left.0.clone());
354379
let guess_type = guess_type(e_token, left.1, right.1, e_op)?;
355380
let n_operand;
356381

357382
if let Some(operand) = expr_optimizer(&left.0, &right.0, e_op) {
358383
n_operand = operand.clone();
359384
opcode_table.add_opcode(Push(None, operand));
360385
} else {
361-
opcode_table.append_code(&mut left.2);
362-
opcode_table.append_code(&mut right.2);
363-
364386
let opcode = astop_to_opcode(e_op);
365-
n_operand = Operand::Expression(left_opd, right_opd, Box::from(opcode.clone()));
366-
367-
opcode_table.add_opcode(opcode);
387+
if matches!(e_op,ExprOp::Store) {
388+
opcode_table.append_code(&mut right.2);
389+
opcode_table.append_code(&mut left.2);
390+
}else {
391+
opcode_table.append_code(&mut left.2);
392+
opcode_table.append_code(&mut right.2);
393+
opcode_table.add_opcode(opcode.clone());
394+
}
395+
n_operand = Operand::Expression(left_opd, right_opd, Box::from(opcode));
368396
}
369397
Ok((n_operand, guess_type, opcode_table))
370398
}
@@ -380,22 +408,28 @@ pub(crate) fn lower_expr(
380408
if let Some(key) = code.find_value_key(var_name.clone()) {
381409
let value = code.find_value(key).unwrap();
382410
value.variable = true;
411+
let type_ = value.type_.clone();
383412
match value.type_ {
384-
ValueGuessType::Ref => {
413+
Ref => {
385414
opcode_table.add_opcode(Push(None, Operand::Library(var_name)));
386415
}
387416
_ => {
388-
opcode_table.add_opcode(OpCode::StoreLocal(None, key, Operand::Val(key)));
417+
if let Some(operand) = store{
418+
value.type_ = operand_to_guess(operand);
419+
opcode_table.add_opcode(OpCode::LoadLocal(None, key, Operand::Val(key)));
420+
}else {
421+
opcode_table.add_opcode(OpCode::StoreLocal(None, key, Operand::Val(key)));
422+
}
389423
}
390424
};
391-
Ok((Operand::Val(key), value.type_.clone(), opcode_table))
425+
Ok((Operand::Val(key), type_, opcode_table))
392426
} else {
393427
unreachable!()
394428
}
395429
}
396430
ASTExprTree::Call { name, args } => {
397431
for arg in args {
398-
let mut expr = lower_expr(semantic, arg, code)?;
432+
let mut expr = lower_expr(semantic, arg, code, None)?;
399433
opcode_table.append_code(&mut expr.2);
400434
}
401435

@@ -458,7 +492,7 @@ pub fn expr_semantic(
458492
let mut opcode_vec = OpCodeTable::new();
459493

460494
if let Some(expr) = expr {
461-
let mut exp = lower_expr(semantic, &expr, code)?;
495+
let mut exp = lower_expr(semantic, &expr, code, None)?;
462496
opcode_vec.append_code(&mut exp.2);
463497
operand = exp.0;
464498
guess_type = exp.1;

src/compiler/semantic/optimizer.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,18 @@ pub fn expr_optimizer(left: &Operand, right: &Operand, op: &ExprOp) -> Option<Op
4141
(ImmNum(a), ImmNum(b), ExprOp::Div) => Some(ImmNum(a / b)),
4242
(ImmNum(a), ImmNum(b), ExprOp::Rmd) => Some(ImmNum(a % b)),
4343

44+
(ImmNum(a), ImmFlot(b), ExprOp::Add) => Some(ImmFlot(*a as f64 + b)),
45+
(ImmNum(a), ImmFlot(b), ExprOp::Sub) => Some(ImmFlot(*a as f64 - b)),
46+
(ImmNum(a), ImmFlot(b), ExprOp::Mul) => Some(ImmFlot(*a as f64 * b)),
47+
(ImmNum(a), ImmFlot(b), ExprOp::Div) => Some(ImmFlot(*a as f64 / b)),
48+
(ImmNum(a), ImmFlot(b), ExprOp::Rmd) => Some(ImmFlot(*a as f64 % b)),
49+
50+
(ImmFlot(a), ImmNum(b), ExprOp::Add) => Some(ImmFlot(a + *b as f64)),
51+
(ImmFlot(a), ImmNum(b), ExprOp::Sub) => Some(ImmFlot(a - *b as f64)),
52+
(ImmFlot(a), ImmNum(b), ExprOp::Mul) => Some(ImmFlot(a * *b as f64)),
53+
(ImmFlot(a), ImmNum(b), ExprOp::Div) => Some(ImmFlot(a / *b as f64)),
54+
(ImmFlot(a), ImmNum(b), ExprOp::Rmd) => Some(ImmFlot(a % *b as f64)),
55+
4456
// 位运算
4557
(ImmNum(a), ImmNum(b), ExprOp::BitAnd) => Some(ImmNum(a & b)),
4658
(ImmNum(a), ImmNum(b), ExprOp::BitOr) => Some(ImmNum(a | b)),

src/compiler/semantic/while.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub fn while_semantic(
1414
code: &mut Code,
1515
locals:&mut LocalMap
1616
) -> Result<OpCodeTable, ParserError> {
17-
let mut exp = lower_expr(semantic, &expr, code)?;
17+
let mut exp = lower_expr(semantic, &expr, code, None)?;
1818
let mut code_table = OpCodeTable::new();
1919

2020
if exp.1 == ValueGuessType::Bool && !semantic.file.has_warnings(LoopNoExpr) {

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub mod compiler;
2+
pub mod library;
3+
pub mod runtime;

src/library/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ fn register_library(library: LibModule) {
5050
.insert(library.name.clone(), library);
5151
}
5252

53-
pub(crate) fn find_library(
53+
pub fn find_library(
5454
name: &str,
5555
f: impl FnOnce(Option<&mut LibModule>) -> Result<(), ParserError>,
5656
) -> Result<(), ParserError> {

0 commit comments

Comments
 (0)