Skip to content
This repository was archived by the owner on Jan 21, 2025. It is now read-only.

Commit da445b3

Browse files
jasontattonfacebook-github-bot
authored andcommitted
Add support for complex numbers
Summary: Here we improve the following: * The test case for complex numbers * Errpy will now throw a recoverable error when a invalid number is attempted to be parsed (rather than panic crashing) * "integer style" and "float style" complex numbers are both handled. * The pretty printers are improved to handle complex numbers * `ast.rs` and `ast.ml` are both enhanced to support complex numbers Reviewed By: stroxler Differential Revision: D42407324 Privacy Context Container: L1152058 fbshipit-source-id: 5a34ccd8919abf9d01af2c63d46149e93a04efe6
1 parent 2c9d437 commit da445b3

File tree

7 files changed

+75
-16
lines changed

7 files changed

+75
-16
lines changed

src/ast.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
type num =
99
| Int of int
1010
| Float of float
11+
| Complex of float
1112
| Big_int of string
1213
(** pyast uses Py.Object.t for Big_int, but this is presumably not what we
1314
* want (if it's an opaque wrapper for a CPython object). Just have the

src/ast.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use serde::Serialize;
1717
pub enum Num {
1818
Int(isize),
1919
Float(f64),
20+
Complex(f64),
2021
/// pyast uses Py.Object.t for Big_int, but this is presumably not what we
2122
/// want (if it's an opaque wrapper for a CPython object). Just have the
2223
/// source text representing the integer digits for now instead.

src/cst_to_ast.rs

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2064,8 +2064,8 @@ impl Parser {
20642064
KEYWORD_IDENTIFIER => self.name(self.get_text(rule.node)),
20652065
STRING => self.raw_string(rule.node, rule.node)?,
20662066
CONCATENATED_STRING => self.concatenated_string(rule.node)?,
2067-
INTEGER => self.integer(self.get_text(rule.node)),
2068-
FLOAT => self.float(self.get_text(rule.node)),
2067+
INTEGER => self.integer(rule.node)?,
2068+
FLOAT => self.float(rule.node)?,
20692069
TRUE => self.constant(ConstantDesc::Bool(true)),
20702070
FALSE => self.constant(ConstantDesc::Bool(false)),
20712071
NONE => self.none(),
@@ -3426,22 +3426,66 @@ impl Parser {
34263426
}
34273427
}
34283428

3429-
fn integer(&mut self, const_value: String) -> ExprDesc {
3430-
ExprDesc::Constant {
3431-
value: Some(ConstantDesc::Num(Num::Int(
3432-
const_value.parse::<isize>().unwrap(),
3433-
))),
3434-
kind: None,
3429+
fn integer(&mut self, node: &Node) -> ErrorableResult<ExprDesc> {
3430+
let mut const_value = self.get_text(node);
3431+
3432+
let is_complex = const_value.ends_with('j') || const_value.ends_with('J');
3433+
if is_complex {
3434+
const_value = const_value[0..const_value.len() - 1].to_string();
34353435
}
3436-
}
34373436

3438-
fn float(&mut self, const_value: String) -> ExprDesc {
3439-
ExprDesc::Constant {
3440-
value: Some(ConstantDesc::Num(Num::Float(
3441-
const_value.parse::<f64>().unwrap(),
3442-
))),
3437+
let integer_value = match const_value.parse::<isize>() {
3438+
Ok(value) => value,
3439+
Err(error_msg) => {
3440+
return Err(self.record_recoverable_error(
3441+
RecoverableError::UnexpectedExpression(format!(
3442+
"cannot parse integer: {:?} as {:?}",
3443+
const_value, error_msg
3444+
)),
3445+
node,
3446+
));
3447+
}
3448+
};
3449+
3450+
Ok(ExprDesc::Constant {
3451+
value: Some(ConstantDesc::Num(if is_complex {
3452+
Num::Complex(integer_value as f64)
3453+
} else {
3454+
Num::Int(integer_value)
3455+
})),
34433456
kind: None,
3457+
})
3458+
}
3459+
3460+
fn float(&mut self, node: &Node) -> ErrorableResult<ExprDesc> {
3461+
let mut const_value = self.get_text(node);
3462+
3463+
let is_complex = const_value.ends_with('j') || const_value.ends_with('J');
3464+
if is_complex {
3465+
const_value = const_value[0..const_value.len() - 1].to_string();
34443466
}
3467+
3468+
let float_value = match const_value.parse::<f64>() {
3469+
Ok(value) => value,
3470+
Err(error_msg) => {
3471+
return Err(self.record_recoverable_error(
3472+
RecoverableError::UnexpectedExpression(format!(
3473+
"cannot parse float: {:?} as {:?}",
3474+
const_value, error_msg
3475+
)),
3476+
node,
3477+
));
3478+
}
3479+
};
3480+
3481+
Ok(ExprDesc::Constant {
3482+
value: Some(ConstantDesc::Num(if is_complex {
3483+
Num::Complex(float_value)
3484+
} else {
3485+
Num::Float(float_value)
3486+
})),
3487+
kind: None,
3488+
})
34453489
}
34463490

34473491
fn name(&mut self, identifier: String) -> ExprDesc {

src/printers/ast_pretty_print.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,10 @@ impl ConstantDesc {
12601260
ConstantDesc::Num(Num::Float(vala)) => {
12611261
pprint_output.push_str(&vala.to_string());
12621262
}
1263+
ConstantDesc::Num(Num::Complex(vala)) => {
1264+
pprint_output.push_str(&vala.to_string());
1265+
pprint_output.push_str("j");
1266+
}
12631267
rest => {
12641268
let res = match rest {
12651269
ConstantDesc::Str(vala) => vala,

src/printers/ast_print.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,9 @@ impl fmt::Display for ConstantDesc {
749749
ConstantDesc::Num(Num::Float(vala)) => {
750750
write!(f, "{}", vala)
751751
}
752+
ConstantDesc::Num(Num::Complex(vala)) => {
753+
write!(f, "{}j", vala)
754+
}
752755
rest => {
753756
let res = match rest {
754757
ConstantDesc::Str(vala) => vala,

tests/test_resources/unit_tests/ast_literals.pytest

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,14 @@ f"{{{{70 + 4}}}}"
234234
timestamp = 9223372036854775810
235235

236236
## complex numbers
237-
complex = 0.0302988j
237+
complex_half = 0.0302988j
238+
239+
c = 1 + 2.j
240+
c = 1 + 2j
241+
c = 1 + 2.J
242+
c = 1 + 2J
243+
real = c.real
244+
imag = c.imag
238245

239246
## very long floats
240247
timestamp = 0.33333333333333334444444444444444356456456456456456457457456456456456456456
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
long integers
2-
complex numbers

0 commit comments

Comments
 (0)