Skip to content

Commit

Permalink
Support asg::Expr::UnaryExpr(UnaryExpr) for UnaryOp::Minus
Browse files Browse the repository at this point in the history
This supports in the ASG unary expressions with UnaryOp::Minus

The struct `UnaryExpr` and accessors was already present. Now we
construct these from the AST.
  • Loading branch information
jlapeyre committed Feb 1, 2024
1 parent 92915ef commit 99104a2
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 17 deletions.
10 changes: 10 additions & 0 deletions crates/oq3_semantics/src/asg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,16 @@ impl UnaryExpr {
pub fn op(&self) -> &UnaryOp {
&self.op
}

pub fn to_texpr(self) -> TExpr {
match self.op() {
UnaryOp::Not => TExpr::new(Expr::UnaryExpr(self), Type::Bool(IsConst::False)),
_ => {
let ty = self.operand.get_type().clone();
TExpr::new(Expr::UnaryExpr(self), ty)
}
}
}
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
Expand Down
45 changes: 28 additions & 17 deletions crates/oq3_semantics/src/syntax_to_semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ fn from_expr_stmt(expr_stmt: synast::ExprStmt, context: &mut Context) -> Option<
_ => {
let expr = from_expr(syn_expr, context);
expr.map_or_else(
|| panic!("expr::ExprStmt is None"),
|| panic!("expr::ExprStmt is None. Expression not implemented in the ASG."),
|ex| Some(asg::Stmt::ExprStmt(ex)),
)
}
Expand All @@ -248,26 +248,37 @@ fn from_expr(expr: synast::Expr, context: &mut Context) -> Option<asg::TExpr> {
match expr {
// FIXME: Ugh. could clean up logic here
synast::Expr::PrefixExpr(prefix_expr) => {
match prefix_expr.op_kind()? {
synast::UnaryOp::Neg => {
if let synast::Expr::Literal(ref literal) = prefix_expr.expr()? {
match literal.kind() {
synast::LiteralKind::FloatNumber(float_num) => {
let num = float_num.value().unwrap();
let float = format!("-{num}");
return Some(asg::FloatLiteral::new(float).to_texpr());
match prefix_expr.op_kind() {
Some(synast::UnaryOp::Neg) => {
match prefix_expr.expr() {
Some(synast::Expr::Literal(ref literal)) => {
match literal.kind() {
synast::LiteralKind::FloatNumber(float_num) => {
let num = float_num.value().unwrap();
let float = format!("-{num}");
Some(asg::FloatLiteral::new(float).to_texpr())
}
synast::LiteralKind::IntNumber(int_num) => {
let num = int_num.value_u128().unwrap(); // fn value_u128 is kind of a hack
Some(asg::IntLiteral::new(num, false).to_texpr())
// `false` means negative
}
_ => todo!(),
}
synast::LiteralKind::IntNumber(int_num) => {
let num = int_num.value_u128().unwrap(); // fn value_u128 is kind of a hack
return Some(asg::IntLiteral::new(num, false).to_texpr());
// `false` means negative
}
_ => todo!(),
}

Some(synexpr) => Some(
asg::UnaryExpr::new(
asg::UnaryOp::Minus,
from_expr(synexpr, context).unwrap(),
)
.to_texpr(),
),

_ => todo!(),
}
None
}
_ => None,
_ => todo!(),
}
}

Expand Down
11 changes: 11 additions & 0 deletions crates/oq3_semantics/tests/from_string_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,17 @@ fn literal_value(stmt: &asg::Stmt) -> Option<String> {
}
}

#[test]
fn test_from_string_unary_minus() {
let code = r##"
- a;
"##;
let (program, errors, _symbol_table) = parse_string(code);
assert_eq!(errors.len(), 1);
let expr = expr_from_expr_stmt(&program[0]);
assert!(matches!(&expr, asg::Expr::UnaryExpr(_)));
}

#[test]
fn test_from_string_pos_lit_float() {
let code = r##"
Expand Down

0 comments on commit 99104a2

Please sign in to comment.