Skip to content

Commit c370d1b

Browse files
authored
Merge pull request #335 from CohenArthur/187-mutate-var-in-block
Fix variable mutation in block
2 parents 1babd52 + be6af25 commit c370d1b

File tree

6 files changed

+83
-4
lines changed

6 files changed

+83
-4
lines changed

src/context.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,12 @@ impl Context {
198198

199199
/// Replace a variable or create it if it does not exist
200200
pub fn replace_variable(&mut self, var: Var) -> Result<(), Error> {
201-
// Remove the variable if it exists
202-
let _ = self.remove_variable(&var);
201+
match self.scope_map.get_variable_mut(var.name()) {
202+
None => self.add_variable(var)?,
203+
Some(var_ref) => var_ref.set_instance(var.instance()),
204+
}
203205

204-
self.add_variable(var)
206+
Ok(())
205207
}
206208

207209
/// Get a mutable reference on an existing function

src/context/scope_map.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ impl<V, F, T> Scope<V, F, T> {
2222
self.variables.get(name)
2323
}
2424

25+
/// Get a mutable reference on a variable from the scope map if it has been inserted already
26+
pub fn get_variable_mut(&mut self, name: &str) -> Option<&mut V> {
27+
self.variables.get_mut(name)
28+
}
29+
2530
/// Get a reference on a function from the scope map if is has been inserted already
2631
pub fn get_function(&self, name: &str) -> Option<&F> {
2732
self.functions.get(name)
@@ -144,6 +149,17 @@ impl<V, F, T> ScopeMap<V, F, T> {
144149
None
145150
}
146151

152+
pub fn get_variable_mut(&mut self, name: &str) -> Option<&mut V> {
153+
for scope in self.scopes.iter_mut() {
154+
match scope.get_variable_mut(name) {
155+
Some(v) => return Some(v),
156+
None => continue,
157+
};
158+
}
159+
160+
None
161+
}
162+
147163
/// Maybe get a function in any available scopes
148164
pub fn get_function(&self, name: &str) -> Option<&F> {
149165
// FIXME: Use find for code quality?

src/instruction/var_assignment.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,10 @@ impl TypeCheck for VarAssign {
157157
#[cfg(test)]
158158
mod tests {
159159
use super::*;
160-
use crate::jinko_fail;
161160
use crate::parser::{Construct, Token};
162161
use crate::value::{JkInt, JkString};
163162
use crate::ToObjectInstance;
163+
use crate::{jinko, jinko_fail};
164164

165165
#[test]
166166
fn non_mutable() {
@@ -223,4 +223,36 @@ mod tests {
223223
mut a0 = 14;
224224
};
225225
}
226+
227+
#[test]
228+
fn assign_mutable_in_block_187() {
229+
let ctx = jinko! {
230+
mut x = 1;
231+
{
232+
x = 0;
233+
}
234+
};
235+
236+
assert_eq!(
237+
ctx.get_variable("x").unwrap().instance(),
238+
JkInt::from(0).to_instance()
239+
);
240+
}
241+
242+
#[test]
243+
fn assign_mutable_in_function_187() {
244+
let ctx = jinko! {
245+
mut x = 1;
246+
func change_global() {
247+
x = 0;
248+
}
249+
250+
change_global()
251+
};
252+
253+
assert_eq!(
254+
ctx.get_variable("x").unwrap().instance(),
255+
JkInt::from(0).to_instance()
256+
);
257+
}
226258
}

tests/ft/regression/187.jk

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
mut x = 1;
2+
{
3+
x = 0;
4+
}
5+
6+
x

tests/ft/regression/187_fn.jk

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
mut global_x = 1;
2+
3+
func mutate_global() {
4+
func inner() {
5+
global_x = 0;
6+
}
7+
8+
inner()
9+
}
10+
11+
mutate_global();
12+
13+
x

tests/ft/regression/regression.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,13 @@ tests:
44
args:
55
- "tests/ft/regression/string_double_free.jk"
66
exit_code: 0
7+
- name: "Variable mutation in block #187"
8+
binary: "target/debug/jinko"
9+
args:
10+
- "tests/ft/regression/187.jk"
11+
exit_code: 0
12+
- name: "Variable mutation in function #187"
13+
binary: "target/debug/jinko"
14+
args:
15+
- "tests/ft/regression/187_fn.jk"
16+
exit_code: 0

0 commit comments

Comments
 (0)