From a1ffcf0a3534182fbac4eedacdc10abfd3069f68 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 21 Sep 2024 13:37:53 +0900 Subject: [PATCH] feat: support f-string --- crates/py2erg/convert.rs | 41 ++++++++++++++++++++++++++++++++++++++++ tests/literal.py | 5 +++++ tests/test.rs | 5 +++++ 3 files changed, 51 insertions(+) create mode 100644 tests/literal.py diff --git a/crates/py2erg/convert.rs b/crates/py2erg/convert.rs index e1e6bfc..46b7804 100644 --- a/crates/py2erg/convert.rs +++ b/crates/py2erg/convert.rs @@ -1406,6 +1406,46 @@ impl ASTConverter { let slice = self.convert_ident("slice".to_string(), loc); slice.call(args).into() } + py_ast::Expr::JoinedStr(string) => { + if string.values.is_empty() { + let loc = string.location(); + let stringify = self.convert_ident("str".to_string(), loc); + return stringify.call(Args::empty()).into(); + } else if string.values.len() == 1 { + let loc = string.location(); + let mut values = string.values; + let expr = self.convert_expr(values.remove(0)); + let stringify = self.convert_ident("str".to_string(), loc); + return stringify.call1(expr).into(); + } + let mut values = vec![]; + for value in string.values { + match value { + py_ast::Expr::Constant(cons) => { + let cons = self.convert_const(cons); + values.push(cons); + } + py_ast::Expr::FormattedValue(form) => { + let loc = form.location(); + let expr = self.convert_expr(*form.value); + let stringify = self.convert_ident("str".to_string(), loc); + values.push(stringify.call1(expr).into()); + } + _ => {} + } + } + let fst = values.remove(0); + values.into_iter().fold(fst, |acc, expr| { + let plus = Token::dummy(TokenKind::Plus, "+"); + Expr::BinOp(BinOp::new(plus, acc, expr)) + }) + } + py_ast::Expr::FormattedValue(form) => { + let loc = form.location(); + let expr = self.convert_expr(*form.value); + let stringify = self.convert_ident("str".to_string(), loc); + stringify.call1(expr).into() + } _other => { log!(err "unimplemented: {:?}", _other); Expr::Dummy(Dummy::new(None, vec![])) @@ -1890,6 +1930,7 @@ impl ASTConverter { fn convert_statement(&mut self, stmt: Stmt, dont_call_return: bool) -> Expr { match stmt { py_ast::Stmt::Expr(stmt) => self.convert_expr(*stmt.value), + // type-annotated assignment py_ast::Stmt::AnnAssign(ann_assign) => { let anot = self.convert_expr(*ann_assign.annotation.clone()); let t_spec = self.convert_type_spec(*ann_assign.annotation); diff --git a/tests/literal.py b/tests/literal.py new file mode 100644 index 0000000..54ed126 --- /dev/null +++ b/tests/literal.py @@ -0,0 +1,5 @@ +name = "John" + +print(f"Hello, {name}!") +print(f"Hello, {nome}!") # ERR +print(f"Hello, {name + 1}!") # ERR diff --git a/tests/test.rs b/tests/test.rs index b6ee1e4..8a9e5c8 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -112,6 +112,11 @@ fn exec_list() -> Result<(), String> { expect("tests/list.py", 0, 2) } +#[test] +fn exec_literal() -> Result<(), String> { + expect("tests/literal.py", 0, 2) +} + #[test] fn exec_narrowing() -> Result<(), String> { expect("tests/narrowing.py", 0, 1)