Skip to content

Commit 8816e5d

Browse files
committed
Implement more complete version of str_repr.
1 parent 9936342 commit 8816e5d

File tree

3 files changed

+37
-11
lines changed

3 files changed

+37
-11
lines changed

tests/snippets/strings.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,9 @@
1616
assert str() == ""
1717
assert str("abc") == "abc"
1818

19-
assert str(["a", "b", "can't"]) == "['a', 'b', 'can\\'t']"
19+
assert repr("a") == "'a'"
20+
assert repr("can't") == '"can\'t"'
21+
assert repr('"won\'t"') == "'\"won\\'t\"'"
22+
assert repr('\n\t') == "'\\n\\t'"
23+
24+
assert str(["a", "b", "can't"]) == "['a', 'b', \"can't\"]"

vm/src/builtins.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,10 @@ fn builtin_range(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
288288
}
289289

290290
// builtin_repr
291+
fn builtin_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
292+
arg_check!(vm, args, required = [(obj, None)]);
293+
vm.to_repr(obj.clone())
294+
}
291295
// builtin_reversed
292296
// builtin_round
293297
// builtin_set
@@ -346,6 +350,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
346350
dict.insert(String::from("locals"), ctx.new_rustfunc(builtin_locals));
347351
dict.insert(String::from("print"), ctx.new_rustfunc(builtin_print));
348352
dict.insert(String::from("range"), ctx.new_rustfunc(builtin_range));
353+
dict.insert(String::from("repr"), ctx.new_rustfunc(builtin_repr));
349354
dict.insert(String::from("setattr"), ctx.new_rustfunc(builtin_setattr));
350355
dict.insert(String::from("str"), ctx.str_type()); // new_rustfunc(builtin_str));
351356
dict.insert(String::from("tuple"), ctx.tuple_type());

vm/src/obj/objstr.rs

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,38 @@ fn str_str(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
4545
Ok(s.clone())
4646
}
4747

48+
fn count_char(s: &str, c: char) -> usize {
49+
s.chars().filter(|x| *x == c).count()
50+
}
51+
4852
fn str_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
4953
arg_check!(vm, args, required = [(s, Some(vm.ctx.str_type()))]);
5054
let value = get_value(s);
51-
let mut formatted = String::from("'");
55+
let quote_char = if count_char(&value, '\'') > count_char(&value, '"') {
56+
'"'
57+
} else {
58+
'\''
59+
};
60+
let mut formatted = String::new();
61+
formatted.push(quote_char);
5262
for c in value.chars() {
53-
match c {
54-
'\'' | '\\' => {
55-
formatted.push('\\');
56-
formatted.push(c);
57-
}
58-
_ => {
59-
formatted.push(c);
60-
}
63+
if c == quote_char || c == '\\' {
64+
formatted.push('\\');
65+
formatted.push(c);
66+
} else if c == '\n' {
67+
formatted.push('\\');
68+
formatted.push('n');
69+
} else if c == '\t' {
70+
formatted.push('\\');
71+
formatted.push('t');
72+
} else if c == '\r' {
73+
formatted.push('\\');
74+
formatted.push('r');
75+
} else {
76+
formatted.push(c);
6177
}
6278
}
63-
formatted.push('\'');
79+
formatted.push(quote_char);
6480
Ok(vm.ctx.new_str(formatted))
6581
}
6682

0 commit comments

Comments
 (0)