From 872b3103e8aa87cb9911f96fe0c151c1743d0f91 Mon Sep 17 00:00:00 2001 From: Aaron Councilman <aaronjc4@illinois.edu> Date: Mon, 17 Feb 2025 19:24:42 -0600 Subject: [PATCH] Allow more rust-like for loops --- juno_frontend/src/lang.l | 1 + juno_frontend/src/lang.y | 20 +++++++++++++------- juno_frontend/src/semant.rs | 16 +++++++++++++--- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/juno_frontend/src/lang.l b/juno_frontend/src/lang.l index 4039ef0a..6399e5f2 100644 --- a/juno_frontend/src/lang.l +++ b/juno_frontend/src/lang.l @@ -28,6 +28,7 @@ for "for" if "if" inout "inout" integer "integer" +in "in" let "let" match "match" mod "mod" diff --git a/juno_frontend/src/lang.y b/juno_frontend/src/lang.y index 7efc0125..a5b82452 100644 --- a/juno_frontend/src/lang.y +++ b/juno_frontend/src/lang.y @@ -292,11 +292,17 @@ Stmt -> Result<Stmt, ()> | 'match' NonStructExpr Cases { Ok(Stmt::MatchStmt{ span : $span, expr : $2?, body : $3? }) } | 'for' VarBind '=' NonStructExpr 'to' NonStructExpr Stmts - { Ok(Stmt::ForStmt{ span : $span, var : $2?, init : $4?, bound : $6?, step : None, - body : Box::new($7?) }) } + { Ok(Stmt::ForStmt{ span : $span, var : $2?, init : $4?, bound : $6?, + inclusive: false, step : None, body : Box::new($7?) }) } | 'for' VarBind '=' NonStructExpr 'to' NonStructExpr 'by' SignedIntLit Stmts - { Ok(Stmt::ForStmt{ span : $span, var : $2?, init : $4?, bound : $6?, step : Some($8?), - body : Box::new($9?) }) } + { Ok(Stmt::ForStmt{ span : $span, var : $2?, init : $4?, bound : $6?, + inclusive: false, step : Some($8?), body : Box::new($9?) }) } + | 'for' VarBind 'in' NonStructExpr '..' NonStructExpr Stmts + { Ok(Stmt::ForStmt{ span: $span, var: $2?, init: $4?, bound: $6?, + inclusive: false, step: None, body: Box::new($7?) }) } + | 'for' VarBind 'in' NonStructExpr '..' '=' NonStructExpr Stmts + { Ok(Stmt::ForStmt{ span: $span, var: $2?, init: $4?, bound: $7?, + inclusive: false, step: None, body: Box::new($8?) }) } | 'while' NonStructExpr Stmts { Ok(Stmt::WhileStmt{ span : $span, cond : $2?, body : Box::new($3?) }) } | 'return' ';' @@ -687,9 +693,9 @@ pub enum Stmt { AssignStmt { span : Span, lhs : LExpr, assign : AssignOp, assign_span : Span, rhs : Expr }, IfStmt { span : Span, cond : Expr, thn : Box<Stmt>, els : Option<Box<Stmt>> }, MatchStmt { span : Span, expr : Expr, body : Vec<Case> }, - // The step records: negative, number, base - ForStmt { span : Span, var : VarBind, init : Expr, bound : Expr, step : Option<(bool, Span, IntBase)>, - body : Box<Stmt> }, + // The step records: negative, number, base, inclusive records whether the bound is included in the range + ForStmt { span : Span, var : VarBind, init : Expr, bound : Expr, + inclusive: bool, step : Option<(bool, Span, IntBase)>, body : Box<Stmt> }, WhileStmt { span : Span, cond : Expr, body : Box<Stmt> }, ReturnStmt { span : Span, expr : Option<Expr> }, BreakStmt { span : Span }, diff --git a/juno_frontend/src/semant.rs b/juno_frontend/src/semant.rs index 1059229a..bfd4cf7f 100644 --- a/juno_frontend/src/semant.rs +++ b/juno_frontend/src/semant.rs @@ -1999,6 +1999,7 @@ fn process_stmt( }, init, bound, + inclusive, step, body, } => { @@ -2130,10 +2131,19 @@ fn process_stmt( val: bound_val, }; - // The condition of the loop is var < bound, unless the step is negative in which case - // it is var > bound + // There are four cases for the condition that we generate, though it always takes the + // form var OP bound: + // 1. The step is positive and the range is exclusive of the bound, OP = < + // 2. The step is positive and the range is inclusive of the bound, OP = <= + // 3. The step is negative and the range is exclusive of the bound, OP = > + // 4. The step is negative and the range is inclusive of the bound, OP = >= let condition = Expr::BinaryExp { - op: if step_pos { BinaryOp::Lt } else { BinaryOp::Gt }, + op: match (step_pos, inclusive) { + (true, false) => BinaryOp::Lt, + (true, true) => BinaryOp::Le, + (false, false) => BinaryOp::Gt, + (false, true) => BinaryOp::Ge, + }, lhs: Box::new(Expr::Variable { var: var, typ: var_type, -- GitLab