Skip to content

Commit ffff92a

Browse files
committed
fix possible memory leak
1 parent cc22988 commit ffff92a

5 files changed

Lines changed: 73 additions & 8 deletions

File tree

lang/src/cli/repl.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ pub fn repl() {
127127
let ast = parse(&buffer, "<repl>");
128128

129129
if let Err(_) = ast {
130+
buffer.clear();
130131
continue;
131132
}
132133

@@ -135,6 +136,7 @@ pub fn repl() {
135136

136137
if let Err(e) = compiler.compile_program(ast.clone().unwrap()) {
137138
println!("{}: {}", "Compilation error".red(), e);
139+
buffer.clear();
138140
continue;
139141
}
140142

lang/src/compiler/compiler.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ impl Compiler {
3838
)
3939
}
4040

41+
fn block_is_void(expr: &Expr) -> bool {
42+
match expr {
43+
Expr::Block(exprs) => exprs.last().map(|e| Self::is_void(&e.node)).unwrap_or(true),
44+
_ => false,
45+
}
46+
}
47+
4148
// chunk shit
4249

4350
fn emit(&mut self, instruction: Instruction, span: SimpleSpan) {
@@ -348,8 +355,12 @@ impl Compiler {
348355

349356
Expr::And(a, b) => {
350357
self.compile_expr(*a.clone())?;
358+
359+
let skip = self.emit_jump(Instruction::JumpIfFalse(0), span);
360+
self.emit(Instruction::Pop, span);
361+
351362
self.compile_expr(*b.clone())?;
352-
self.emit(Instruction::And, span);
363+
self.patch_jump(skip);
353364
}
354365

355366
Expr::Or(a, b) => {
@@ -396,6 +407,11 @@ impl Compiler {
396407
self.continue_targets.push(start);
397408

398409
self.compile_expr(*body.clone())?;
410+
411+
if !Self::block_is_void(&body.node) {
412+
self.emit(Instruction::Pop, span);
413+
}
414+
399415
self.emit(Instruction::Jump(start), span);
400416

401417
let breaks = self.break_patches.pop().unwrap();
@@ -415,6 +431,11 @@ impl Compiler {
415431
let exit = self.emit_jump(Instruction::JumpIfFalse(0), span);
416432

417433
self.compile_expr(*body.clone())?;
434+
435+
if !Self::block_is_void(&body.node) {
436+
self.emit(Instruction::Pop, span);
437+
}
438+
418439
self.emit(Instruction::Jump(start), span);
419440

420441
let breaks = self.break_patches.pop().unwrap();
@@ -469,6 +490,11 @@ impl Compiler {
469490

470491
// body
471492
self.compile_expr(*body.clone())?;
493+
494+
if !Self::block_is_void(&body.node) {
495+
self.emit(Instruction::Pop, span);
496+
}
497+
472498
self.emit(Instruction::Jump(start), span);
473499

474500
self.patch_jump(exit);

lang/src/functions.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ fn int(args: Vec<Value>) -> Result<Value, String> {
8787
}
8888

8989
match &args[0] {
90+
Value::Int(i) => Ok(Value::Int(*i)),
9091
Value::Float(f) => Ok(Value::Int(*f as i64)),
9192
Value::Bool(b) => Ok(Value::Int(if *b { 1 } else { 0 })),
9293
Value::String(s) => s.parse::<i64>()
@@ -103,6 +104,7 @@ fn float(args: Vec<Value>) -> Result<Value, String> {
103104
}
104105

105106
match &args[0] {
107+
Value::Float(f) => Ok(Value::Float(*f)),
106108
Value::Int(i) => Ok(Value::Float(*i as f64)),
107109
Value::Bool(b) => Ok(Value::Float(if *b { 1.0 } else { 0.0 })),
108110
Value::String(s) => s.parse::<f64>()

lang/src/natives/array.rs

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,16 @@ pub fn get_fn(name: String) -> Option<NativeFn> {
1515
}
1616

1717
pub fn list_fns() -> Vec<String> {
18-
vec!["len".to_string(), "push".to_string(), "pop".to_string(), "join".to_string()]
18+
vec![
19+
"len".to_string(),
20+
"push".to_string(),
21+
"pop".to_string(),
22+
"join".to_string(),
23+
"min".to_string(),
24+
"max".to_string(),
25+
"reverse".to_string(),
26+
"sort".to_string()
27+
]
1928
}
2029

2130
pub fn len(this: Value, args: Vec<Value>) -> Result<(Value, Option<Value>), String> {
@@ -86,8 +95,21 @@ pub fn min(this: Value, args: Vec<Value>) -> Result<(Value, Option<Value>), Stri
8695

8796
match this {
8897
Value::Array(arr) => {
89-
let min_value = arr.iter().min_by(|a, b| a.partial_cmp(b).unwrap()).cloned().unwrap_or(Value::Null);
90-
Ok((min_value, None))
98+
if arr.is_empty() {
99+
return Ok((Value::Null, None));
100+
}
101+
102+
let mut min_value = &arr[0];
103+
104+
for v in &arr[1..] {
105+
match v.partial_cmp(min_value) {
106+
Some(std::cmp::Ordering::Less) => min_value = v,
107+
None => return Err(format!("cannot compare '{}' and '{}'", v.type_name(), min_value.type_name())),
108+
_ => {}
109+
}
110+
}
111+
112+
Ok((min_value.clone(), None))
91113
}
92114

93115
_ => unreachable!(),
@@ -101,8 +123,21 @@ pub fn max(this: Value, args: Vec<Value>) -> Result<(Value, Option<Value>), Stri
101123

102124
match this {
103125
Value::Array(arr) => {
104-
let max_value = arr.iter().max_by(|a, b| a.partial_cmp(b).unwrap()).cloned().unwrap_or(Value::Null);
105-
Ok((max_value, None))
126+
if arr.is_empty() {
127+
return Ok((Value::Null, None));
128+
}
129+
130+
let mut max_value = &arr[0];
131+
132+
for v in &arr[1..] {
133+
match v.partial_cmp(max_value) {
134+
Some(std::cmp::Ordering::Greater) => max_value = v,
135+
None => return Err(format!("cannot compare '{}' and '{}'", v.type_name(), max_value.type_name())),
136+
_ => {}
137+
}
138+
}
139+
140+
Ok((max_value.clone(), None))
106141
}
107142

108143
_ => unreachable!(),

lang/src/validator.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ fn validate_expr(expr: &SpannedExpr, ctx: &mut ValidationContext) -> Result<(),
5858
}
5959

6060
Expr::Function { body, .. } => {
61+
ctx.inside_function += 1;
6162
validate_expr(&body, ctx)?;
63+
ctx.inside_function -= 1;
6264
}
6365

6466
Expr::WhileLoop { body, .. } | Expr::ForLoop { body, .. } | Expr::InfiniteLoop { body, .. } => {
@@ -78,11 +80,9 @@ fn validate_expr(expr: &SpannedExpr, ctx: &mut ValidationContext) -> Result<(),
7880
}
7981

8082
Expr::Block(body) => {
81-
ctx.inside_function += 1;
8283
for expr in body {
8384
validate_expr(&expr, ctx)?;
8485
}
85-
ctx.inside_function -= 1;
8686
}
8787

8888
_ => {}

0 commit comments

Comments
 (0)