Ver código fonte

Use named enum for more fields of ast::Expression (#1121)

Signed-off-by: Sean Young <sean@mess.org>
Sean Young 2 anos atrás
pai
commit
15f36f2012

+ 76 - 60
src/bin/languageserver/mod.rs

@@ -273,12 +273,11 @@ impl SolangServer {
                 }
             }
             ast::Statement::For {
-                loc: _,
-                reachable: _,
                 init,
                 cond,
                 next,
                 body,
+                ..
             } => {
                 if let Some(exp) = cond {
                     SolangServer::construct_expr(exp, lookup_tbl, symtab, ns);
@@ -443,7 +442,13 @@ impl SolangServer {
             }
 
             // Arithmetic expression
-            ast::Expression::Add(locs, ty, unchecked, expr1, expr2) => {
+            ast::Expression::Add {
+                loc: locs,
+                ty,
+                unchecked,
+                left,
+                right,
+            } => {
                 lookup_tbl.push(HoverEntry {
                     start: locs.start(),
                     stop: locs.end(),
@@ -454,10 +459,16 @@ impl SolangServer {
                     ),
                 });
 
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
-                SolangServer::construct_expr(expr2, lookup_tbl, symtab, ns);
+                SolangServer::construct_expr(left, lookup_tbl, symtab, ns);
+                SolangServer::construct_expr(right, lookup_tbl, symtab, ns);
             }
-            ast::Expression::Subtract(locs, ty, unchecked, expr1, expr2) => {
+            ast::Expression::Subtract {
+                loc: locs,
+                ty,
+                unchecked,
+                left,
+                right,
+            } => {
                 lookup_tbl.push(HoverEntry {
                     start: locs.start(),
                     stop: locs.end(),
@@ -468,10 +479,16 @@ impl SolangServer {
                     ),
                 });
 
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
-                SolangServer::construct_expr(expr2, lookup_tbl, symtab, ns);
+                SolangServer::construct_expr(left, lookup_tbl, symtab, ns);
+                SolangServer::construct_expr(right, lookup_tbl, symtab, ns);
             }
-            ast::Expression::Multiply(locs, ty, unchecked, expr1, expr2) => {
+            ast::Expression::Multiply {
+                loc: locs,
+                ty,
+                unchecked,
+                left,
+                right,
+            } => {
                 lookup_tbl.push(HoverEntry {
                     start: locs.start(),
                     stop: locs.end(),
@@ -482,30 +499,46 @@ impl SolangServer {
                     ),
                 });
 
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
-                SolangServer::construct_expr(expr2, lookup_tbl, symtab, ns);
+                SolangServer::construct_expr(left, lookup_tbl, symtab, ns);
+                SolangServer::construct_expr(right, lookup_tbl, symtab, ns);
             }
-            ast::Expression::Divide(locs, ty, expr1, expr2) => {
+            ast::Expression::Divide {
+                loc: locs,
+                ty,
+                left,
+                right,
+            } => {
                 lookup_tbl.push(HoverEntry {
                     start: locs.start(),
                     stop: locs.end(),
                     val: format!("{} divide", ty.to_string(ns)),
                 });
 
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
-                SolangServer::construct_expr(expr2, lookup_tbl, symtab, ns);
+                SolangServer::construct_expr(left, lookup_tbl, symtab, ns);
+                SolangServer::construct_expr(right, lookup_tbl, symtab, ns);
             }
-            ast::Expression::Modulo(locs, ty, expr1, expr2) => {
+            ast::Expression::Modulo {
+                loc: locs,
+                ty,
+                left,
+                right,
+            } => {
                 lookup_tbl.push(HoverEntry {
                     start: locs.start(),
                     stop: locs.end(),
                     val: format!("{} modulo", ty.to_string(ns)),
                 });
 
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
-                SolangServer::construct_expr(expr2, lookup_tbl, symtab, ns);
+                SolangServer::construct_expr(left, lookup_tbl, symtab, ns);
+                SolangServer::construct_expr(right, lookup_tbl, symtab, ns);
             }
-            ast::Expression::Power(locs, ty, unchecked, expr1, expr2) => {
+            ast::Expression::Power {
+                loc: locs,
+                ty,
+                unchecked,
+                left,
+                right,
+            } => {
                 lookup_tbl.push(HoverEntry {
                     start: locs.start(),
                     stop: locs.end(),
@@ -516,30 +549,18 @@ impl SolangServer {
                     ),
                 });
 
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
-                SolangServer::construct_expr(expr2, lookup_tbl, symtab, ns);
+                SolangServer::construct_expr(left, lookup_tbl, symtab, ns);
+                SolangServer::construct_expr(right, lookup_tbl, symtab, ns);
             }
 
             // Bitwise expresion
-            ast::Expression::BitwiseOr(_locs, _typ, expr1, expr2) => {
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
-                SolangServer::construct_expr(expr2, lookup_tbl, symtab, ns);
-            }
-            ast::Expression::BitwiseAnd(_locs, _typ, expr1, expr2) => {
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
-                SolangServer::construct_expr(expr2, lookup_tbl, symtab, ns);
-            }
-            ast::Expression::BitwiseXor(_locs, _typ, expr1, expr2) => {
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
-                SolangServer::construct_expr(expr2, lookup_tbl, symtab, ns);
-            }
-            ast::Expression::ShiftLeft(_locs, _typ, expr1, expr2) => {
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
-                SolangServer::construct_expr(expr2, lookup_tbl, symtab, ns);
-            }
-            ast::Expression::ShiftRight(_locs, _typ, expr1, expr2, _bl) => {
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
-                SolangServer::construct_expr(expr2, lookup_tbl, symtab, ns);
+            ast::Expression::BitwiseOr { left, right, .. }
+            | ast::Expression::BitwiseAnd { left, right, .. }
+            | ast::Expression::BitwiseXor { left, right, .. }
+            | ast::Expression::ShiftLeft { left, right, .. }
+            | ast::Expression::ShiftRight { left, right, .. } => {
+                SolangServer::construct_expr(left, lookup_tbl, symtab, ns);
+                SolangServer::construct_expr(right, lookup_tbl, symtab, ns);
             }
 
             // Variable expression
@@ -615,18 +636,12 @@ impl SolangServer {
                 SolangServer::construct_expr(expr, lookup_tbl, symtab, ns);
             }
 
-            //Increment-Decrement expression
-            ast::Expression::PreIncrement(_locs, _typ, _, expr1) => {
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
-            }
-            ast::Expression::PreDecrement(_locs, _typ, _, expr1) => {
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
-            }
-            ast::Expression::PostIncrement(_locs, _typ, _, expr1) => {
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
-            }
-            ast::Expression::PostDecrement(_locs, _typ, _, expr1) => {
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
+            // Increment-Decrement expression
+            ast::Expression::PreIncrement { expr, .. }
+            | ast::Expression::PreDecrement { expr, .. }
+            | ast::Expression::PostIncrement { expr, .. }
+            | ast::Expression::PostDecrement { expr, .. } => {
+                SolangServer::construct_expr(expr, lookup_tbl, symtab, ns);
             }
             ast::Expression::Assign(_locs, _typ, expr1, expr2) => {
                 SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
@@ -669,10 +684,15 @@ impl SolangServer {
                 SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
             }
 
-            ast::Expression::ConditionalOperator(_locs, _typ, expr1, expr2, expr3) => {
-                SolangServer::construct_expr(expr1, lookup_tbl, symtab, ns);
-                SolangServer::construct_expr(expr2, lookup_tbl, symtab, ns);
-                SolangServer::construct_expr(expr3, lookup_tbl, symtab, ns);
+            ast::Expression::ConditionalOperator {
+                cond,
+                true_option: left,
+                false_option: right,
+                ..
+            } => {
+                SolangServer::construct_expr(cond, lookup_tbl, symtab, ns);
+                SolangServer::construct_expr(left, lookup_tbl, symtab, ns);
+                SolangServer::construct_expr(right, lookup_tbl, symtab, ns);
             }
 
             ast::Expression::Subscript(_locs, _, _, expr1, expr2) => {
@@ -837,11 +857,7 @@ impl SolangServer {
                 }
             }
             ast::Expression::Constructor {
-                loc: _,
-                contract_no: _,
-                constructor_no: _,
-                args,
-                call_args,
+                args, call_args, ..
             } => {
                 if let Some(gas) = &call_args.gas {
                     SolangServer::construct_expr(gas, lookup_tbl, symtab, ns);

+ 106 - 20
src/codegen/expression.rs

@@ -49,7 +49,13 @@ pub fn expression(
 
             load_storage(loc, ty, storage, cfg, vartab)
         }
-        ast::Expression::Add(loc, ty, unchecked, left, right) => add(
+        ast::Expression::Add {
+            loc,
+            ty,
+            unchecked,
+            left,
+            right,
+        } => add(
             loc,
             ty,
             unchecked,
@@ -62,7 +68,13 @@ pub fn expression(
             right,
             opt,
         ),
-        ast::Expression::Subtract(loc, ty, unchecked, left, right) => substract(
+        ast::Expression::Subtract {
+            loc,
+            ty,
+            unchecked,
+            left,
+            right,
+        } => substract(
             loc,
             ty,
             unchecked,
@@ -75,7 +87,13 @@ pub fn expression(
             right,
             opt,
         ),
-        ast::Expression::Multiply(loc, ty, unchecked, left, right) => {
+        ast::Expression::Multiply {
+            loc,
+            ty,
+            unchecked,
+            left,
+            right,
+        } => {
             if ty.is_rational() {
                 let (_, r) = eval_const_rational(expr, ns).unwrap();
 
@@ -90,7 +108,12 @@ pub fn expression(
                 )
             }
         }
-        ast::Expression::Divide(loc, ty, left, right) => {
+        ast::Expression::Divide {
+            loc,
+            ty,
+            left,
+            right,
+        } => {
             let l = expression(left, cfg, contract_no, func, ns, vartab, opt);
             let r = expression(right, cfg, contract_no, func, ns, vartab, opt);
             if ty.is_signed_int() {
@@ -99,7 +122,12 @@ pub fn expression(
                 Expression::UnsignedDivide(*loc, ty.clone(), Box::new(l), Box::new(r))
             }
         }
-        ast::Expression::Modulo(loc, ty, left, right) => {
+        ast::Expression::Modulo {
+            loc,
+            ty,
+            left,
+            right,
+        } => {
             let l = expression(left, cfg, contract_no, func, ns, vartab, opt);
             let r = expression(right, cfg, contract_no, func, ns, vartab, opt);
             if ty.is_signed_int() {
@@ -108,38 +136,70 @@ pub fn expression(
                 Expression::UnsignedModulo(*loc, ty.clone(), Box::new(l), Box::new(r))
             }
         }
-        ast::Expression::Power(loc, ty, unchecked, left, right) => Expression::Power(
+        ast::Expression::Power {
+            loc,
+            ty,
+            unchecked,
+            left,
+            right,
+        } => Expression::Power(
             *loc,
             ty.clone(),
             *unchecked,
             Box::new(expression(left, cfg, contract_no, func, ns, vartab, opt)),
             Box::new(expression(right, cfg, contract_no, func, ns, vartab, opt)),
         ),
-        ast::Expression::BitwiseOr(loc, ty, left, right) => Expression::BitwiseOr(
+        ast::Expression::BitwiseOr {
+            loc,
+            ty,
+            left,
+            right,
+        } => Expression::BitwiseOr(
             *loc,
             ty.clone(),
             Box::new(expression(left, cfg, contract_no, func, ns, vartab, opt)),
             Box::new(expression(right, cfg, contract_no, func, ns, vartab, opt)),
         ),
-        ast::Expression::BitwiseAnd(loc, ty, left, right) => Expression::BitwiseAnd(
+        ast::Expression::BitwiseAnd {
+            loc,
+            ty,
+            left,
+            right,
+        } => Expression::BitwiseAnd(
             *loc,
             ty.clone(),
             Box::new(expression(left, cfg, contract_no, func, ns, vartab, opt)),
             Box::new(expression(right, cfg, contract_no, func, ns, vartab, opt)),
         ),
-        ast::Expression::BitwiseXor(loc, ty, left, right) => Expression::BitwiseXor(
+        ast::Expression::BitwiseXor {
+            loc,
+            ty,
+            left,
+            right,
+        } => Expression::BitwiseXor(
             *loc,
             ty.clone(),
             Box::new(expression(left, cfg, contract_no, func, ns, vartab, opt)),
             Box::new(expression(right, cfg, contract_no, func, ns, vartab, opt)),
         ),
-        ast::Expression::ShiftLeft(loc, ty, left, right) => Expression::ShiftLeft(
+        ast::Expression::ShiftLeft {
+            loc,
+            ty,
+            left,
+            right,
+        } => Expression::ShiftLeft(
             *loc,
             ty.clone(),
             Box::new(expression(left, cfg, contract_no, func, ns, vartab, opt)),
             Box::new(expression(right, cfg, contract_no, func, ns, vartab, opt)),
         ),
-        ast::Expression::ShiftRight(loc, ty, left, right, sign) => Expression::ShiftRight(
+        ast::Expression::ShiftRight {
+            loc,
+            ty,
+            left,
+            right,
+            sign,
+        } => Expression::ShiftRight(
             *loc,
             ty.clone(),
             Box::new(expression(left, cfg, contract_no, func, ns, vartab, opt)),
@@ -264,8 +324,18 @@ pub fn expression(
 
             assign_single(left, cfg_right, cfg, contract_no, func, ns, vartab, opt)
         }
-        ast::Expression::PreDecrement(loc, ty, unchecked, var)
-        | ast::Expression::PreIncrement(loc, ty, unchecked, var) => pre_incdec(
+        ast::Expression::PreDecrement {
+            loc,
+            ty,
+            unchecked,
+            expr: var,
+        }
+        | ast::Expression::PreIncrement {
+            loc,
+            ty,
+            unchecked,
+            expr: var,
+        } => pre_incdec(
             vartab,
             ty,
             var,
@@ -278,8 +348,18 @@ pub fn expression(
             unchecked,
             opt,
         ),
-        ast::Expression::PostDecrement(loc, ty, unchecked, var)
-        | ast::Expression::PostIncrement(loc, ty, unchecked, var) => post_incdec(
+        ast::Expression::PostDecrement {
+            loc,
+            ty,
+            unchecked,
+            expr: var,
+        }
+        | ast::Expression::PostIncrement {
+            loc,
+            ty,
+            unchecked,
+            expr: var,
+        } => post_incdec(
             vartab,
             ty,
             var,
@@ -704,7 +784,13 @@ pub fn expression(
         ast::Expression::AllocDynamicBytes(loc, ty, size, init) => {
             alloc_dynamic_array(size, cfg, contract_no, func, ns, vartab, loc, ty, init, opt)
         }
-        ast::Expression::ConditionalOperator(loc, ty, cond, left, right) => conditional_operator(
+        ast::Expression::ConditionalOperator {
+            loc,
+            ty,
+            cond,
+            true_option: left,
+            false_option: right,
+        } => conditional_operator(
             loc,
             ty,
             cond,
@@ -812,14 +898,14 @@ fn post_incdec(
     );
     let one = Box::new(Expression::NumberLiteral(*loc, ty.clone(), BigInt::one()));
     let expr = match expr {
-        ast::Expression::PostDecrement(..) => Expression::Subtract(
+        ast::Expression::PostDecrement { .. } => Expression::Subtract(
             *loc,
             ty.clone(),
             *unchecked,
             Box::new(Expression::Variable(*loc, ty.clone(), res)),
             one,
         ),
-        ast::Expression::PostIncrement(..) => Expression::Add(
+        ast::Expression::PostIncrement { .. } => Expression::Add(
             *loc,
             ty.clone(),
             *unchecked,
@@ -900,10 +986,10 @@ fn pre_incdec(
     };
     let one = Box::new(Expression::NumberLiteral(*loc, ty.clone(), BigInt::one()));
     let expr = match expr {
-        ast::Expression::PreDecrement(..) => {
+        ast::Expression::PreDecrement { .. } => {
             Expression::Subtract(*loc, ty.clone(), *unchecked, Box::new(v), one)
         }
-        ast::Expression::PreIncrement(..) => {
+        ast::Expression::PreIncrement { .. } => {
             Expression::Add(*loc, ty.clone(), *unchecked, Box::new(v), one)
         }
         _ => unreachable!(),

+ 13 - 2
src/codegen/statements.rs

@@ -764,7 +764,12 @@ fn returns(
     let uncast_values = match expr {
         // Explicitly recurse for conditinal operator expressions.
         // `return a ? b : c` is transformed into pseudo code `a ? return b : return c`
-        ast::Expression::ConditionalOperator(_, _, cond, left, right) => {
+        ast::Expression::ConditionalOperator {
+            cond,
+            true_option: left,
+            false_option: right,
+            ..
+        } => {
             let cond = expression(cond, cfg, contract_no, Some(func), ns, vartab, opt);
 
             let left_block = cfg.new_basic_block("left".to_string());
@@ -836,7 +841,13 @@ fn destructure(
     vartab: &mut Vartable,
     opt: &Options,
 ) {
-    if let ast::Expression::ConditionalOperator(_, _, cond, left, right) = expr {
+    if let ast::Expression::ConditionalOperator {
+        cond,
+        true_option: left,
+        false_option: right,
+        ..
+    } = expr
+    {
         let cond = expression(cond, cfg, contract_no, Some(func), ns, vartab, opt);
 
         let left_block = cfg.new_basic_block("left".to_string());

+ 147 - 54
src/sema/ast.rs

@@ -711,17 +711,81 @@ pub enum Expression {
     StructLiteral(pt::Loc, Type, Vec<Expression>),
     ArrayLiteral(pt::Loc, Type, Vec<u32>, Vec<Expression>),
     ConstArrayLiteral(pt::Loc, Type, Vec<u32>, Vec<Expression>),
-    Add(pt::Loc, Type, bool, Box<Expression>, Box<Expression>),
-    Subtract(pt::Loc, Type, bool, Box<Expression>, Box<Expression>),
-    Multiply(pt::Loc, Type, bool, Box<Expression>, Box<Expression>),
-    Divide(pt::Loc, Type, Box<Expression>, Box<Expression>),
-    Modulo(pt::Loc, Type, Box<Expression>, Box<Expression>),
-    Power(pt::Loc, Type, bool, Box<Expression>, Box<Expression>),
-    BitwiseOr(pt::Loc, Type, Box<Expression>, Box<Expression>),
-    BitwiseAnd(pt::Loc, Type, Box<Expression>, Box<Expression>),
-    BitwiseXor(pt::Loc, Type, Box<Expression>, Box<Expression>),
-    ShiftLeft(pt::Loc, Type, Box<Expression>, Box<Expression>),
-    ShiftRight(pt::Loc, Type, Box<Expression>, Box<Expression>, bool),
+    Add {
+        loc: pt::Loc,
+        ty: Type,
+        /// Do not check for overflow, i.e. in `unchecked {}` block
+        unchecked: bool,
+        left: Box<Expression>,
+        right: Box<Expression>,
+    },
+    Subtract {
+        loc: pt::Loc,
+        ty: Type,
+        /// Do not check for overflow, i.e. in `unchecked {}` block
+        unchecked: bool,
+        left: Box<Expression>,
+        right: Box<Expression>,
+    },
+    Multiply {
+        loc: pt::Loc,
+        ty: Type,
+        /// Do not check for overflow, i.e. in `unchecked {}` block
+        unchecked: bool,
+        left: Box<Expression>,
+        right: Box<Expression>,
+    },
+    Divide {
+        loc: pt::Loc,
+        ty: Type,
+        left: Box<Expression>,
+        right: Box<Expression>,
+    },
+    Modulo {
+        loc: pt::Loc,
+        ty: Type,
+        left: Box<Expression>,
+        right: Box<Expression>,
+    },
+    Power {
+        loc: pt::Loc,
+        ty: Type,
+        /// Do not check for overflow, i.e. in `unchecked {}` block
+        unchecked: bool,
+        left: Box<Expression>,
+        right: Box<Expression>,
+    },
+    BitwiseOr {
+        loc: pt::Loc,
+        ty: Type,
+        left: Box<Expression>,
+        right: Box<Expression>,
+    },
+    BitwiseAnd {
+        loc: pt::Loc,
+        ty: Type,
+        left: Box<Expression>,
+        right: Box<Expression>,
+    },
+    BitwiseXor {
+        loc: pt::Loc,
+        ty: Type,
+        left: Box<Expression>,
+        right: Box<Expression>,
+    },
+    ShiftLeft {
+        loc: pt::Loc,
+        ty: Type,
+        left: Box<Expression>,
+        right: Box<Expression>,
+    },
+    ShiftRight {
+        loc: pt::Loc,
+        ty: Type,
+        left: Box<Expression>,
+        right: Box<Expression>,
+        sign: bool,
+    },
     Variable(pt::Loc, Type, usize),
     ConstantVariable(pt::Loc, Type, Option<usize>, usize),
     StorageVariable(pt::Loc, Type, usize, usize),
@@ -759,10 +823,34 @@ pub enum Expression {
         to: Type,
         expr: Box<Expression>,
     },
-    PreIncrement(pt::Loc, Type, bool, Box<Expression>),
-    PreDecrement(pt::Loc, Type, bool, Box<Expression>),
-    PostIncrement(pt::Loc, Type, bool, Box<Expression>),
-    PostDecrement(pt::Loc, Type, bool, Box<Expression>),
+    PreIncrement {
+        loc: pt::Loc,
+        ty: Type,
+        /// Do not check for overflow, i.e. in `unchecked {}` block
+        unchecked: bool,
+        expr: Box<Expression>,
+    },
+    PreDecrement {
+        loc: pt::Loc,
+        ty: Type,
+        /// Do not check for overflow, i.e. in `unchecked {}` block
+        unchecked: bool,
+        expr: Box<Expression>,
+    },
+    PostIncrement {
+        loc: pt::Loc,
+        ty: Type,
+        /// Do not check for overflow, i.e. in `unchecked {}` block
+        unchecked: bool,
+        expr: Box<Expression>,
+    },
+    PostDecrement {
+        loc: pt::Loc,
+        ty: Type,
+        /// Do not check for overflow, i.e. in `unchecked {}` block
+        unchecked: bool,
+        expr: Box<Expression>,
+    },
     Assign(pt::Loc, Type, Box<Expression>, Box<Expression>),
 
     More(pt::Loc, Box<Expression>, Box<Expression>),
@@ -776,13 +864,13 @@ pub enum Expression {
     Complement(pt::Loc, Type, Box<Expression>),
     UnaryMinus(pt::Loc, Type, Box<Expression>),
 
-    ConditionalOperator(
-        pt::Loc,
-        Type,
-        Box<Expression>,
-        Box<Expression>,
-        Box<Expression>,
-    ),
+    ConditionalOperator {
+        loc: pt::Loc,
+        ty: Type,
+        cond: Box<Expression>,
+        true_option: Box<Expression>,
+        false_option: Box<Expression>,
+    },
     Subscript(pt::Loc, Type, Type, Box<Expression>, Box<Expression>),
     StructMember(pt::Loc, Type, Box<Expression>, usize),
 
@@ -892,17 +980,17 @@ impl Recurse for Expression {
                         e.recurse(cx, f);
                     }
                 }
-                Expression::Add(_, _, _, left, right)
-                | Expression::Subtract(_, _, _, left, right)
-                | Expression::Multiply(_, _, _, left, right)
-                | Expression::Divide(_, _, left, right)
-                | Expression::Modulo(_, _, left, right)
-                | Expression::Power(_, _, _, left, right)
-                | Expression::BitwiseOr(_, _, left, right)
-                | Expression::BitwiseAnd(_, _, left, right)
-                | Expression::BitwiseXor(_, _, left, right)
-                | Expression::ShiftLeft(_, _, left, right)
-                | Expression::ShiftRight(_, _, left, right, _) => {
+                Expression::Add { left, right, .. }
+                | Expression::Subtract { left, right, .. }
+                | Expression::Multiply { left, right, .. }
+                | Expression::Divide { left, right, .. }
+                | Expression::Modulo { left, right, .. }
+                | Expression::Power { left, right, .. }
+                | Expression::BitwiseOr { left, right, .. }
+                | Expression::BitwiseAnd { left, right, .. }
+                | Expression::BitwiseXor { left, right, .. }
+                | Expression::ShiftLeft { left, right, .. }
+                | Expression::ShiftRight { left, right, .. } => {
                     left.recurse(cx, f);
                     right.recurse(cx, f);
                 }
@@ -914,10 +1002,10 @@ impl Recurse for Expression {
                 | Expression::CheckingTrunc { expr, .. }
                 | Expression::Cast { expr, .. }
                 | Expression::BytesCast { expr, .. }
-                | Expression::PreIncrement(_, _, _, expr)
-                | Expression::PreDecrement(_, _, _, expr)
-                | Expression::PostIncrement(_, _, _, expr)
-                | Expression::PostDecrement(_, _, _, expr) => expr.recurse(cx, f),
+                | Expression::PreIncrement { expr, .. }
+                | Expression::PreDecrement { expr, .. }
+                | Expression::PostIncrement { expr, .. }
+                | Expression::PostDecrement { expr, .. } => expr.recurse(cx, f),
 
                 Expression::Assign(_, _, left, right)
                 | Expression::More(_, left, right)
@@ -933,7 +1021,12 @@ impl Recurse for Expression {
                 | Expression::Complement(_, _, expr)
                 | Expression::UnaryMinus(_, _, expr) => expr.recurse(cx, f),
 
-                Expression::ConditionalOperator(_, _, cond, left, right) => {
+                Expression::ConditionalOperator {
+                    cond,
+                    true_option: left,
+                    false_option: right,
+                    ..
+                } => {
                     cond.recurse(cx, f);
                     left.recurse(cx, f);
                     right.recurse(cx, f);
@@ -1021,17 +1114,17 @@ impl CodeLocation for Expression {
             | Expression::StructLiteral(loc, ..)
             | Expression::ArrayLiteral(loc, ..)
             | Expression::ConstArrayLiteral(loc, ..)
-            | Expression::Add(loc, ..)
-            | Expression::Subtract(loc, ..)
-            | Expression::Multiply(loc, ..)
-            | Expression::Divide(loc, ..)
-            | Expression::Modulo(loc, ..)
-            | Expression::Power(loc, ..)
-            | Expression::BitwiseOr(loc, ..)
-            | Expression::BitwiseAnd(loc, ..)
-            | Expression::BitwiseXor(loc, ..)
-            | Expression::ShiftLeft(loc, ..)
-            | Expression::ShiftRight(loc, ..)
+            | Expression::Add { loc, .. }
+            | Expression::Subtract { loc, .. }
+            | Expression::Multiply { loc, .. }
+            | Expression::Divide { loc, .. }
+            | Expression::Modulo { loc, .. }
+            | Expression::Power { loc, .. }
+            | Expression::BitwiseOr { loc, .. }
+            | Expression::BitwiseAnd { loc, .. }
+            | Expression::BitwiseXor { loc, .. }
+            | Expression::ShiftLeft { loc, .. }
+            | Expression::ShiftRight { loc, .. }
             | Expression::Variable(loc, ..)
             | Expression::ConstantVariable(loc, ..)
             | Expression::StorageVariable(loc, ..)
@@ -1053,7 +1146,7 @@ impl CodeLocation for Expression {
             | Expression::Not(loc, _)
             | Expression::Complement(loc, ..)
             | Expression::UnaryMinus(loc, ..)
-            | Expression::ConditionalOperator(loc, ..)
+            | Expression::ConditionalOperator { loc, .. }
             | Expression::Subscript(loc, ..)
             | Expression::StructMember(loc, ..)
             | Expression::Or(loc, ..)
@@ -1067,10 +1160,10 @@ impl CodeLocation for Expression {
             | Expression::ExternalFunctionCall { loc, .. }
             | Expression::ExternalFunctionCallRaw { loc, .. }
             | Expression::Constructor { loc, .. }
-            | Expression::PreIncrement(loc, ..)
-            | Expression::PreDecrement(loc, ..)
-            | Expression::PostIncrement(loc, ..)
-            | Expression::PostDecrement(loc, ..)
+            | Expression::PreIncrement { loc, .. }
+            | Expression::PreDecrement { loc, .. }
+            | Expression::PostIncrement { loc, .. }
+            | Expression::PostDecrement { loc, .. }
             | Expression::Builtin(loc, ..)
             | Expression::Assign(loc, ..)
             | Expression::List(loc, _)

+ 102 - 16
src/sema/dotgraphviz.rs

@@ -374,7 +374,13 @@ impl Dot {
                     self.add_expression(arg, func, ns, node, format!("arg #{}", no));
                 }
             }
-            Expression::Add(loc, ty, unchecked, left, right) => {
+            Expression::Add {
+                loc,
+                ty,
+                unchecked,
+                left,
+                right,
+            } => {
                 let mut labels = vec![String::from("add"), ty.to_string(ns), ns.loc_to_string(loc)];
                 if *unchecked {
                     labels.push(String::from("unchecked"));
@@ -384,7 +390,13 @@ impl Dot {
                 self.add_expression(left, func, ns, node, String::from("left"));
                 self.add_expression(right, func, ns, node, String::from("right"));
             }
-            Expression::Subtract(loc, ty, unchecked, left, right) => {
+            Expression::Subtract {
+                loc,
+                ty,
+                unchecked,
+                left,
+                right,
+            } => {
                 let mut labels = vec![
                     String::from("subtract"),
                     ty.to_string(ns),
@@ -402,7 +414,13 @@ impl Dot {
                 self.add_expression(left, func, ns, node, String::from("left"));
                 self.add_expression(right, func, ns, node, String::from("right"));
             }
-            Expression::Multiply(loc, ty, unchecked, left, right) => {
+            Expression::Multiply {
+                loc,
+                ty,
+                unchecked,
+                left,
+                right,
+            } => {
                 let mut labels = vec![
                     String::from("multiply"),
                     ty.to_string(ns),
@@ -420,7 +438,12 @@ impl Dot {
                 self.add_expression(left, func, ns, node, String::from("left"));
                 self.add_expression(right, func, ns, node, String::from("right"));
             }
-            Expression::Divide(loc, ty, left, right) => {
+            Expression::Divide {
+                loc,
+                ty,
+                left,
+                right,
+            } => {
                 let labels = vec![
                     String::from("divide"),
                     ty.to_string(ns),
@@ -432,7 +455,12 @@ impl Dot {
                 self.add_expression(left, func, ns, node, String::from("left"));
                 self.add_expression(right, func, ns, node, String::from("right"));
             }
-            Expression::Modulo(loc, ty, left, right) => {
+            Expression::Modulo {
+                loc,
+                ty,
+                left,
+                right,
+            } => {
                 let labels = vec![
                     String::from("modulo"),
                     ty.to_string(ns),
@@ -444,7 +472,13 @@ impl Dot {
                 self.add_expression(left, func, ns, node, String::from("left"));
                 self.add_expression(right, func, ns, node, String::from("right"));
             }
-            Expression::Power(loc, ty, unchecked, left, right) => {
+            Expression::Power {
+                loc,
+                ty,
+                unchecked,
+                left,
+                right,
+            } => {
                 let mut labels = vec![
                     String::from("power"),
                     ty.to_string(ns),
@@ -459,7 +493,12 @@ impl Dot {
                 self.add_expression(left, func, ns, node, String::from("left"));
                 self.add_expression(right, func, ns, node, String::from("right"));
             }
-            Expression::BitwiseOr(loc, ty, left, right) => {
+            Expression::BitwiseOr {
+                loc,
+                ty,
+                left,
+                right,
+            } => {
                 let labels = vec![
                     String::from("bitwise or"),
                     ty.to_string(ns),
@@ -474,7 +513,12 @@ impl Dot {
                 self.add_expression(left, func, ns, node, String::from("left"));
                 self.add_expression(right, func, ns, node, String::from("right"));
             }
-            Expression::BitwiseAnd(loc, ty, left, right) => {
+            Expression::BitwiseAnd {
+                loc,
+                ty,
+                left,
+                right,
+            } => {
                 let labels = vec![
                     String::from("bitwise and"),
                     ty.to_string(ns),
@@ -489,7 +533,12 @@ impl Dot {
                 self.add_expression(left, func, ns, node, String::from("left"));
                 self.add_expression(right, func, ns, node, String::from("right"));
             }
-            Expression::BitwiseXor(loc, ty, left, right) => {
+            Expression::BitwiseXor {
+                loc,
+                ty,
+                left,
+                right,
+            } => {
                 let labels = vec![
                     String::from("bitwise xor"),
                     ty.to_string(ns),
@@ -504,7 +553,12 @@ impl Dot {
                 self.add_expression(left, func, ns, node, String::from("left"));
                 self.add_expression(right, func, ns, node, String::from("right"));
             }
-            Expression::ShiftLeft(loc, ty, left, right) => {
+            Expression::ShiftLeft {
+                loc,
+                ty,
+                left,
+                right,
+            } => {
                 let labels = vec![
                     String::from("shift left"),
                     ty.to_string(ns),
@@ -519,7 +573,13 @@ impl Dot {
                 self.add_expression(left, func, ns, node, String::from("left"));
                 self.add_expression(right, func, ns, node, String::from("right"));
             }
-            Expression::ShiftRight(loc, ty, left, right, _) => {
+            Expression::ShiftRight {
+                loc,
+                ty,
+                left,
+                right,
+                sign: _,
+            } => {
                 let labels = vec![
                     String::from("shift right"),
                     ty.to_string(ns),
@@ -691,7 +751,12 @@ impl Dot {
 
                 self.add_expression(expr, func, ns, node, String::from("expr"));
             }
-            Expression::PreIncrement(loc, ty, unchecked, expr) => {
+            Expression::PreIncrement {
+                loc,
+                ty,
+                unchecked,
+                expr,
+            } => {
                 let mut labels = vec![
                     String::from("pre increment"),
                     ty.to_string(ns),
@@ -708,7 +773,12 @@ impl Dot {
 
                 self.add_expression(expr, func, ns, node, String::from("expr"));
             }
-            Expression::PreDecrement(loc, ty, unchecked, expr) => {
+            Expression::PreDecrement {
+                loc,
+                ty,
+                unchecked,
+                expr,
+            } => {
                 let mut labels = vec![
                     String::from("pre decrement"),
                     ty.to_string(ns),
@@ -725,7 +795,12 @@ impl Dot {
 
                 self.add_expression(expr, func, ns, node, String::from("expr"));
             }
-            Expression::PostIncrement(loc, ty, unchecked, expr) => {
+            Expression::PostIncrement {
+                loc,
+                ty,
+                unchecked,
+                expr,
+            } => {
                 let mut labels = vec![
                     String::from("post increment"),
                     ty.to_string(ns),
@@ -742,7 +817,12 @@ impl Dot {
 
                 self.add_expression(expr, func, ns, node, String::from("expr"));
             }
-            Expression::PostDecrement(loc, ty, unchecked, expr) => {
+            Expression::PostDecrement {
+                loc,
+                ty,
+                unchecked,
+                expr,
+            } => {
                 let mut labels = vec![
                     String::from("post decrement"),
                     ty.to_string(ns),
@@ -868,7 +948,13 @@ impl Dot {
                 self.add_expression(expr, func, ns, node, String::from("expr"));
             }
 
-            Expression::ConditionalOperator(loc, ty, cond, left, right) => {
+            Expression::ConditionalOperator {
+                loc,
+                ty,
+                cond,
+                true_option: left,
+                false_option: right,
+            } => {
                 let node = self.add_node(
                     Node::new(
                         "conditional",

+ 186 - 38
src/sema/eval.rs

@@ -17,19 +17,42 @@ pub fn eval_const_number(
     ns: &Namespace,
 ) -> Result<(pt::Loc, BigInt), Diagnostic> {
     match expr {
-        Expression::Add(loc, _, _, l, r) => Ok((
+        Expression::Add {
+            loc,
+            ty: _,
+            unchecked: _,
+            left: l,
+            right: r,
+        } => Ok((
             *loc,
             eval_const_number(l, ns)?.1 + eval_const_number(r, ns)?.1,
         )),
-        Expression::Subtract(loc, _, _, l, r) => Ok((
+        Expression::Subtract {
+            loc,
+            ty: _,
+            unchecked: _,
+            left: l,
+            right: r,
+        } => Ok((
             *loc,
             eval_const_number(l, ns)?.1 - eval_const_number(r, ns)?.1,
         )),
-        Expression::Multiply(loc, _, _, l, r) => Ok((
+        Expression::Multiply {
+            loc,
+            ty: _,
+            unchecked: _,
+            left: l,
+            right: r,
+        } => Ok((
             *loc,
             eval_const_number(l, ns)?.1 * eval_const_number(r, ns)?.1,
         )),
-        Expression::Divide(loc, _, l, r) => {
+        Expression::Divide {
+            loc,
+            ty: _,
+            left: l,
+            right: r,
+        } => {
             let divisor = eval_const_number(r, ns)?.1;
 
             if divisor.is_zero() {
@@ -38,7 +61,12 @@ pub fn eval_const_number(
                 Ok((*loc, eval_const_number(l, ns)?.1 / divisor))
             }
         }
-        Expression::Modulo(loc, _, l, r) => {
+        Expression::Modulo {
+            loc,
+            ty: _,
+            left: l,
+            right: r,
+        } => {
             let divisor = eval_const_number(r, ns)?.1;
 
             if divisor.is_zero() {
@@ -47,19 +75,40 @@ pub fn eval_const_number(
                 Ok((*loc, eval_const_number(l, ns)?.1 % divisor))
             }
         }
-        Expression::BitwiseAnd(loc, _, l, r) => Ok((
+        Expression::BitwiseAnd {
+            loc,
+            ty: _,
+            left: l,
+            right: r,
+        } => Ok((
             *loc,
             eval_const_number(l, ns)?.1 & eval_const_number(r, ns)?.1,
         )),
-        Expression::BitwiseOr(loc, _, l, r) => Ok((
+        Expression::BitwiseOr {
+            loc,
+            ty: _,
+            left: l,
+            right: r,
+        } => Ok((
             *loc,
             eval_const_number(l, ns)?.1 | eval_const_number(r, ns)?.1,
         )),
-        Expression::BitwiseXor(loc, _, l, r) => Ok((
+        Expression::BitwiseXor {
+            loc,
+            ty: _,
+            left: l,
+            right: r,
+        } => Ok((
             *loc,
             eval_const_number(l, ns)?.1 ^ eval_const_number(r, ns)?.1,
         )),
-        Expression::Power(loc, _, _, base, exp) => {
+        Expression::Power {
+            loc,
+            ty: _,
+            unchecked: _,
+            left: base,
+            right: exp,
+        } => {
             let b = eval_const_number(base, ns)?.1;
             let mut e = eval_const_number(exp, ns)?.1;
 
@@ -80,7 +129,12 @@ pub fn eval_const_number(
                 Ok((*loc, res))
             }
         }
-        Expression::ShiftLeft(loc, _, left, right) => {
+        Expression::ShiftLeft {
+            loc,
+            ty: _,
+            left,
+            right,
+        } => {
             let l = eval_const_number(left, ns)?.1;
             let r = eval_const_number(right, ns)?.1;
             let r = match r.to_usize() {
@@ -94,7 +148,13 @@ pub fn eval_const_number(
             };
             Ok((*loc, l << r))
         }
-        Expression::ShiftRight(loc, _, left, right, _) => {
+        Expression::ShiftRight {
+            loc,
+            ty: _,
+            left,
+            right,
+            sign: _,
+        } => {
             let l = eval_const_number(left, ns)?.1;
             let r = eval_const_number(right, ns)?.1;
             let r = match r.to_usize() {
@@ -142,19 +202,42 @@ pub fn eval_const_rational(
     ns: &Namespace,
 ) -> Result<(pt::Loc, BigRational), Diagnostic> {
     match expr {
-        Expression::Add(loc, _, _, l, r) => Ok((
+        Expression::Add {
+            loc,
+            ty: _,
+            unchecked: _,
+            left: l,
+            right: r,
+        } => Ok((
             *loc,
             eval_const_rational(l, ns)?.1 + eval_const_rational(r, ns)?.1,
         )),
-        Expression::Subtract(loc, _, _, l, r) => Ok((
+        Expression::Subtract {
+            loc,
+            ty: _,
+            unchecked: _,
+            left: l,
+            right: r,
+        } => Ok((
             *loc,
             eval_const_rational(l, ns)?.1 - eval_const_rational(r, ns)?.1,
         )),
-        Expression::Multiply(loc, _, _, l, r) => Ok((
+        Expression::Multiply {
+            loc,
+            ty: _,
+            unchecked: _,
+            left: l,
+            right: r,
+        } => Ok((
             *loc,
             eval_const_rational(l, ns)?.1 * eval_const_rational(r, ns)?.1,
         )),
-        Expression::Divide(loc, _, l, r) => {
+        Expression::Divide {
+            loc,
+            ty: _,
+            left: l,
+            right: r,
+        } => {
             let divisor = eval_const_rational(r, ns)?.1;
 
             if divisor.is_zero() {
@@ -163,7 +246,12 @@ pub fn eval_const_rational(
                 Ok((*loc, eval_const_rational(l, ns)?.1 / divisor))
             }
         }
-        Expression::Modulo(loc, _, l, r) => {
+        Expression::Modulo {
+            loc,
+            ty: _,
+            left: l,
+            right: r,
+        } => {
             let divisor = eval_const_rational(r, ns)?.1;
 
             if divisor.is_zero() {
@@ -201,17 +289,17 @@ pub fn eval_const_rational(
 /// If the expression is an arithmetic operation of two number literals, overflow_check() will be called on the result.
 pub(super) fn check_term_for_constant_overflow(expr: &Expression, ns: &mut Namespace) -> bool {
     match expr {
-        Expression::Add(..)
-        | Expression::Subtract(..)
-        | Expression::Multiply(..)
-        | Expression::Divide(..)
-        | Expression::Modulo(..)
-        | Expression::Power(..)
-        | Expression::ShiftLeft(..)
-        | Expression::ShiftRight(..)
-        | Expression::BitwiseAnd(..)
-        | Expression::BitwiseOr(..)
-        | Expression::BitwiseXor(..)
+        Expression::Add { .. }
+        | Expression::Subtract { .. }
+        | Expression::Multiply { .. }
+        | Expression::Divide { .. }
+        | Expression::Modulo { .. }
+        | Expression::Power { .. }
+        | Expression::ShiftLeft { .. }
+        | Expression::ShiftRight { .. }
+        | Expression::BitwiseAnd { .. }
+        | Expression::BitwiseOr { .. }
+        | Expression::BitwiseXor { .. }
         | Expression::NumberLiteral(..) => match eval_constants_in_expression(expr, ns) {
             (Some(Expression::NumberLiteral(loc, ty, result)), _) => {
                 if let Some(diagnostic) = overflow_check(&result, &ty, &loc) {
@@ -238,7 +326,13 @@ fn eval_constants_in_expression(
     ns: &mut Namespace,
 ) -> (Option<Expression>, bool) {
     match expr {
-        Expression::Add(loc, ty, _, left, right) => {
+        Expression::Add {
+            loc,
+            ty,
+            unchecked: _,
+            left,
+            right,
+        } => {
             let left = eval_constants_in_expression(left, ns).0;
             let right = eval_constants_in_expression(right, ns).0;
 
@@ -255,7 +349,13 @@ fn eval_constants_in_expression(
                 (None, true)
             }
         }
-        Expression::Subtract(loc, ty, _, left, right) => {
+        Expression::Subtract {
+            loc,
+            ty,
+            unchecked: _,
+            left,
+            right,
+        } => {
             let left = eval_constants_in_expression(left, ns).0;
             let right = eval_constants_in_expression(right, ns).0;
 
@@ -273,7 +373,13 @@ fn eval_constants_in_expression(
             }
         }
 
-        Expression::Multiply(loc, ty, _, left, right) => {
+        Expression::Multiply {
+            loc,
+            ty,
+            unchecked: _,
+            left,
+            right,
+        } => {
             let left = eval_constants_in_expression(left, ns).0;
             let right = eval_constants_in_expression(right, ns).0;
 
@@ -290,7 +396,12 @@ fn eval_constants_in_expression(
                 (None, true)
             }
         }
-        Expression::Divide(loc, ty, left, right) => {
+        Expression::Divide {
+            loc,
+            ty,
+            left,
+            right,
+        } => {
             let left = eval_constants_in_expression(left, ns).0;
             let right = eval_constants_in_expression(right, ns).0;
 
@@ -314,7 +425,12 @@ fn eval_constants_in_expression(
             }
         }
 
-        Expression::Modulo(loc, ty, left, right) => {
+        Expression::Modulo {
+            loc,
+            ty,
+            left,
+            right,
+        } => {
             let left = eval_constants_in_expression(left, ns).0;
             let right = eval_constants_in_expression(right, ns).0;
 
@@ -337,7 +453,13 @@ fn eval_constants_in_expression(
                 (None, true)
             }
         }
-        Expression::Power(loc, ty, _, left, right) => {
+        Expression::Power {
+            loc,
+            ty,
+            unchecked: _,
+            left,
+            right,
+        } => {
             let left = eval_constants_in_expression(left, ns).0;
             let right = eval_constants_in_expression(right, ns).0;
 
@@ -366,7 +488,12 @@ fn eval_constants_in_expression(
                 (None, true)
             }
         }
-        Expression::ShiftLeft(loc, ty, left, right) => {
+        Expression::ShiftLeft {
+            loc,
+            ty,
+            left,
+            right,
+        } => {
             let left = eval_constants_in_expression(left, ns).0;
             let right = eval_constants_in_expression(right, ns).0;
 
@@ -403,7 +530,13 @@ fn eval_constants_in_expression(
             }
         }
 
-        Expression::ShiftRight(loc, ty, left, right, _) => {
+        Expression::ShiftRight {
+            loc,
+            ty,
+            left,
+            right,
+            sign: _,
+        } => {
             let left = eval_constants_in_expression(left, ns).0;
             let right = eval_constants_in_expression(right, ns).0;
 
@@ -432,7 +565,12 @@ fn eval_constants_in_expression(
                 (None, true)
             }
         }
-        Expression::BitwiseAnd(loc, ty, left, right) => {
+        Expression::BitwiseAnd {
+            loc,
+            ty,
+            left,
+            right,
+        } => {
             let left = eval_constants_in_expression(left, ns).0;
             let right = eval_constants_in_expression(right, ns).0;
 
@@ -453,7 +591,12 @@ fn eval_constants_in_expression(
                 (None, true)
             }
         }
-        Expression::BitwiseOr(loc, ty, left, right) => {
+        Expression::BitwiseOr {
+            loc,
+            ty,
+            left,
+            right,
+        } => {
             let left = eval_constants_in_expression(left, ns).0;
             let right = eval_constants_in_expression(right, ns).0;
 
@@ -474,7 +617,12 @@ fn eval_constants_in_expression(
                 (None, true)
             }
         }
-        Expression::BitwiseXor(loc, ty, left, right) => {
+        Expression::BitwiseXor {
+            loc,
+            ty,
+            left,
+            right,
+        } => {
             let left = eval_constants_in_expression(left, ns).0;
             let right = eval_constants_in_expression(right, ns).0;
 

+ 215 - 167
src/sema/expression.rs

@@ -52,17 +52,17 @@ impl RetrieveType for Expression {
             | Expression::StructLiteral(_, ty, _)
             | Expression::ArrayLiteral(_, ty, ..)
             | Expression::ConstArrayLiteral(_, ty, ..)
-            | Expression::Add(_, ty, ..)
-            | Expression::Subtract(_, ty, ..)
-            | Expression::Multiply(_, ty, ..)
-            | Expression::Divide(_, ty, ..)
-            | Expression::Modulo(_, ty, ..)
-            | Expression::Power(_, ty, ..)
-            | Expression::BitwiseOr(_, ty, ..)
-            | Expression::BitwiseAnd(_, ty, ..)
-            | Expression::BitwiseXor(_, ty, ..)
-            | Expression::ShiftLeft(_, ty, ..)
-            | Expression::ShiftRight(_, ty, ..)
+            | Expression::Add { ty, .. }
+            | Expression::Subtract { ty, .. }
+            | Expression::Multiply { ty, .. }
+            | Expression::Divide { ty, .. }
+            | Expression::Modulo { ty, .. }
+            | Expression::Power { ty, .. }
+            | Expression::BitwiseOr { ty, .. }
+            | Expression::BitwiseAnd { ty, .. }
+            | Expression::BitwiseXor { ty, .. }
+            | Expression::ShiftLeft { ty, .. }
+            | Expression::ShiftRight { ty, .. }
             | Expression::Variable(_, ty, _)
             | Expression::ConstantVariable(_, ty, ..)
             | Expression::StorageVariable(_, ty, ..)
@@ -71,13 +71,13 @@ impl RetrieveType for Expression {
             | Expression::StorageLoad(_, ty, _)
             | Expression::Complement(_, ty, _)
             | Expression::UnaryMinus(_, ty, _)
-            | Expression::ConditionalOperator(_, ty, ..)
+            | Expression::ConditionalOperator { ty, .. }
             | Expression::StructMember(_, ty, ..)
             | Expression::AllocDynamicBytes(_, ty, ..)
-            | Expression::PreIncrement(_, ty, ..)
-            | Expression::PreDecrement(_, ty, ..)
-            | Expression::PostIncrement(_, ty, ..)
-            | Expression::PostDecrement(_, ty, ..)
+            | Expression::PreIncrement { ty, .. }
+            | Expression::PreDecrement { ty, .. }
+            | Expression::PostIncrement { ty, .. }
+            | Expression::PostDecrement { ty, .. }
             | Expression::Assign(_, ty, ..) => ty.clone(),
             Expression::Subscript(_, ty, ..) => ty.clone(),
             Expression::ZeroExt { to, .. }
@@ -880,37 +880,37 @@ impl Expression {
                 } else if to_len > from_len {
                     let shift = (to_len - from_len) * 8;
 
-                    Ok(Expression::ShiftLeft(
-                        *loc,
-                        to.clone(),
-                        Box::new(Expression::ZeroExt {
+                    Ok(Expression::ShiftLeft {
+                        loc: *loc,
+                        ty: to.clone(),
+                        left: Box::new(Expression::ZeroExt {
                             loc: self.loc(),
                             to: to.clone(),
                             expr: Box::new(self.clone()),
                         }),
-                        Box::new(Expression::NumberLiteral(
+                        right: Box::new(Expression::NumberLiteral(
                             *loc,
                             Type::Uint(*to_len as u16 * 8),
                             BigInt::from_u8(shift).unwrap(),
                         )),
-                    ))
+                    })
                 } else {
                     let shift = (from_len - to_len) * 8;
 
                     Ok(Expression::Trunc {
                         loc: *loc,
                         to: to.clone(),
-                        expr: Box::new(Expression::ShiftRight(
-                            self.loc(),
-                            from.clone(),
-                            Box::new(self.clone()),
-                            Box::new(Expression::NumberLiteral(
+                        expr: Box::new(Expression::ShiftRight {
+                            loc: self.loc(),
+                            ty: from.clone(),
+                            left: Box::new(self.clone()),
+                            right: Box::new(Expression::NumberLiteral(
                                 self.loc(),
                                 Type::Uint(*from_len as u16 * 8),
                                 BigInt::from_u8(shift).unwrap(),
                             )),
-                            false,
-                        )),
+                            sign: false,
+                        }),
                     })
                 }
             }
@@ -2117,13 +2117,13 @@ pub fn expression(
             let left = left.cast(&l.loc(), &ty, true, ns, diagnostics)?;
             let right = right.cast(&r.loc(), &ty, true, ns, diagnostics)?;
 
-            Ok(Expression::ConditionalOperator(
-                *loc,
+            Ok(Expression::ConditionalOperator {
+                loc: *loc,
                 ty,
-                Box::new(cond),
-                Box::new(left),
-                Box::new(right),
-            ))
+                cond: Box::new(cond),
+                true_option: Box::new(left),
+                false_option: Box::new(right),
+            })
         }
 
         // pre/post decrement/increment
@@ -2879,7 +2879,13 @@ fn subtract(
     )?;
 
     if ty.is_rational() {
-        let expr = Expression::Subtract(*loc, ty, false, Box::new(left), Box::new(right));
+        let expr = Expression::Subtract {
+            loc: *loc,
+            ty,
+            unchecked: false,
+            left: Box::new(left),
+            right: Box::new(right),
+        };
 
         return match eval_const_rational(&expr, ns) {
             Ok(_) => Ok(expr),
@@ -2890,13 +2896,13 @@ fn subtract(
         };
     }
 
-    Ok(Expression::Subtract(
-        *loc,
-        ty.clone(),
-        context.unchecked,
-        Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
-        Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
-    ))
+    Ok(Expression::Subtract {
+        loc: *loc,
+        ty: ty.clone(),
+        unchecked: context.unchecked,
+        left: Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
+        right: Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
+    })
 }
 
 fn bitwise_or(
@@ -2925,12 +2931,12 @@ fn bitwise_or(
         diagnostics,
     )?;
 
-    Ok(Expression::BitwiseOr(
-        *loc,
-        ty.clone(),
-        Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
-        Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
-    ))
+    Ok(Expression::BitwiseOr {
+        loc: *loc,
+        ty: ty.clone(),
+        left: Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
+        right: Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
+    })
 }
 
 fn bitwise_and(
@@ -2959,12 +2965,12 @@ fn bitwise_and(
         diagnostics,
     )?;
 
-    Ok(Expression::BitwiseAnd(
-        *loc,
-        ty.clone(),
-        Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
-        Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
-    ))
+    Ok(Expression::BitwiseAnd {
+        loc: *loc,
+        ty: ty.clone(),
+        left: Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
+        right: Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
+    })
 }
 
 fn bitwise_xor(
@@ -2993,12 +2999,12 @@ fn bitwise_xor(
         diagnostics,
     )?;
 
-    Ok(Expression::BitwiseXor(
-        *loc,
-        ty.clone(),
-        Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
-        Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
-    ))
+    Ok(Expression::BitwiseXor {
+        loc: *loc,
+        ty: ty.clone(),
+        left: Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
+        right: Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
+    })
 }
 
 fn shift_left(
@@ -3022,12 +3028,12 @@ fn shift_left(
 
     let left_type = left.ty();
 
-    Ok(Expression::ShiftLeft(
-        *loc,
-        left_type.clone(),
-        Box::new(left),
-        Box::new(cast_shift_arg(loc, right, right_length, &left_type, ns)),
-    ))
+    Ok(Expression::ShiftLeft {
+        loc: *loc,
+        ty: left_type.clone(),
+        left: Box::new(left),
+        right: Box::new(cast_shift_arg(loc, right, right_length, &left_type, ns)),
+    })
 }
 
 fn shift_right(
@@ -3051,13 +3057,13 @@ fn shift_right(
     let _ = get_int_length(&left_type, &l.loc(), true, ns, diagnostics)?;
     let (right_length, _) = get_int_length(&right.ty(), &r.loc(), false, ns, diagnostics)?;
 
-    Ok(Expression::ShiftRight(
-        *loc,
-        left_type.clone(),
-        Box::new(left),
-        Box::new(cast_shift_arg(loc, right, right_length, &left_type, ns)),
-        left_type.is_signed_int(),
-    ))
+    Ok(Expression::ShiftRight {
+        loc: *loc,
+        ty: left_type.clone(),
+        left: Box::new(left),
+        right: Box::new(cast_shift_arg(loc, right, right_length, &left_type, ns)),
+        sign: left_type.is_signed_int(),
+    })
 }
 
 fn multiply(
@@ -3087,7 +3093,13 @@ fn multiply(
     )?;
 
     if ty.is_rational() {
-        let expr = Expression::Multiply(*loc, ty, false, Box::new(left), Box::new(right));
+        let expr = Expression::Multiply {
+            loc: *loc,
+            ty,
+            unchecked: false,
+            left: Box::new(left),
+            right: Box::new(right),
+        };
 
         return match eval_const_rational(&expr, ns) {
             Ok(_) => Ok(expr),
@@ -3126,13 +3138,13 @@ fn multiply(
             )
         }
     } else {
-        Ok(Expression::Multiply(
-            *loc,
-            ty.clone(),
-            context.unchecked,
-            Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
-            Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
-        ))
+        Ok(Expression::Multiply {
+            loc: *loc,
+            ty: ty.clone(),
+            unchecked: context.unchecked,
+            left: Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
+            right: Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
+        })
     }
 }
 
@@ -3162,12 +3174,12 @@ fn divide(
         diagnostics,
     )?;
 
-    Ok(Expression::Divide(
-        *loc,
-        ty.clone(),
-        Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
-        Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
-    ))
+    Ok(Expression::Divide {
+        loc: *loc,
+        ty: ty.clone(),
+        left: Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
+        right: Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
+    })
 }
 
 fn modulo(
@@ -3196,12 +3208,12 @@ fn modulo(
         diagnostics,
     )?;
 
-    Ok(Expression::Modulo(
-        *loc,
-        ty.clone(),
-        Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
-        Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
-    ))
+    Ok(Expression::Modulo {
+        loc: *loc,
+        ty: ty.clone(),
+        left: Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
+        right: Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
+    })
 }
 
 fn power(
@@ -3267,13 +3279,13 @@ fn power(
         diagnostics,
     )?;
 
-    Ok(Expression::Power(
-        *loc,
-        ty.clone(),
-        context.unchecked,
-        Box::new(base.cast(&b.loc(), &ty, true, ns, diagnostics)?),
-        Box::new(exp.cast(&e.loc(), &ty, true, ns, diagnostics)?),
-    ))
+    Ok(Expression::Power {
+        loc: *loc,
+        ty: ty.clone(),
+        unchecked: context.unchecked,
+        left: Box::new(base.cast(&b.loc(), &ty, true, ns, diagnostics)?),
+        right: Box::new(exp.cast(&e.loc(), &ty, true, ns, diagnostics)?),
+    })
 }
 
 /// Resolve an new contract expression with positional arguments
@@ -4149,7 +4161,13 @@ fn addition(
     )?;
 
     if ty.is_rational() {
-        let expr = Expression::Add(*loc, ty, false, Box::new(left), Box::new(right));
+        let expr = Expression::Add {
+            loc: *loc,
+            ty,
+            unchecked: false,
+            left: Box::new(left),
+            right: Box::new(right),
+        };
 
         return match eval_const_rational(&expr, ns) {
             Ok(_) => Ok(expr),
@@ -4187,13 +4205,13 @@ fn addition(
         )?;
     }
 
-    Ok(Expression::Add(
-        *loc,
-        ty.clone(),
-        context.unchecked,
-        Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
-        Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
-    ))
+    Ok(Expression::Add {
+        loc: *loc,
+        ty: ty.clone(),
+        unchecked: context.unchecked,
+        left: Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
+        right: Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
+    })
 }
 
 /// Resolve an assignment
@@ -4396,52 +4414,70 @@ fn assign_expr(
         };
 
         Ok(match expr {
-            pt::Expression::AssignAdd(..) => Expression::Add(
-                *loc,
-                ty.clone(),
-                context.unchecked,
-                Box::new(assign),
-                Box::new(set),
-            ),
-            pt::Expression::AssignSubtract(..) => Expression::Subtract(
-                *loc,
-                ty.clone(),
-                context.unchecked,
-                Box::new(assign),
-                Box::new(set),
-            ),
-            pt::Expression::AssignMultiply(..) => Expression::Multiply(
-                *loc,
-                ty.clone(),
-                context.unchecked,
-                Box::new(assign),
-                Box::new(set),
-            ),
-            pt::Expression::AssignOr(..) => {
-                Expression::BitwiseOr(*loc, ty.clone(), Box::new(assign), Box::new(set))
-            }
-            pt::Expression::AssignAnd(..) => {
-                Expression::BitwiseAnd(*loc, ty.clone(), Box::new(assign), Box::new(set))
-            }
-            pt::Expression::AssignXor(..) => {
-                Expression::BitwiseXor(*loc, ty.clone(), Box::new(assign), Box::new(set))
-            }
-            pt::Expression::AssignShiftLeft(..) => {
-                Expression::ShiftLeft(*loc, ty.clone(), Box::new(assign), Box::new(set))
-            }
-            pt::Expression::AssignShiftRight(..) => Expression::ShiftRight(
-                *loc,
-                ty.clone(),
-                Box::new(assign),
-                Box::new(set),
-                ty.is_signed_int(),
-            ),
-            pt::Expression::AssignDivide(..) => {
-                Expression::Divide(*loc, ty.clone(), Box::new(assign), Box::new(set))
-            }
-            pt::Expression::AssignModulo(..) => {
-                Expression::Modulo(*loc, ty.clone(), Box::new(assign), Box::new(set))
-            }
+            pt::Expression::AssignAdd(..) => Expression::Add {
+                loc: *loc,
+                ty: ty.clone(),
+                unchecked: context.unchecked,
+                left: Box::new(assign),
+                right: Box::new(set),
+            },
+            pt::Expression::AssignSubtract(..) => Expression::Subtract {
+                loc: *loc,
+                ty: ty.clone(),
+                unchecked: context.unchecked,
+                left: Box::new(assign),
+                right: Box::new(set),
+            },
+            pt::Expression::AssignMultiply(..) => Expression::Multiply {
+                loc: *loc,
+                ty: ty.clone(),
+                unchecked: context.unchecked,
+                left: Box::new(assign),
+                right: Box::new(set),
+            },
+            pt::Expression::AssignOr(..) => Expression::BitwiseOr {
+                loc: *loc,
+                ty: ty.clone(),
+                left: Box::new(assign),
+                right: Box::new(set),
+            },
+            pt::Expression::AssignAnd(..) => Expression::BitwiseAnd {
+                loc: *loc,
+                ty: ty.clone(),
+                left: Box::new(assign),
+                right: Box::new(set),
+            },
+            pt::Expression::AssignXor(..) => Expression::BitwiseXor {
+                loc: *loc,
+                ty: ty.clone(),
+                left: Box::new(assign),
+                right: Box::new(set),
+            },
+            pt::Expression::AssignShiftLeft(..) => Expression::ShiftLeft {
+                loc: *loc,
+                ty: ty.clone(),
+                left: Box::new(assign),
+                right: Box::new(set),
+            },
+            pt::Expression::AssignShiftRight(..) => Expression::ShiftRight {
+                loc: *loc,
+                ty: ty.clone(),
+                left: Box::new(assign),
+                right: Box::new(set),
+                sign: ty.is_signed_int(),
+            },
+            pt::Expression::AssignDivide(..) => Expression::Divide {
+                loc: *loc,
+                ty: ty.clone(),
+                left: Box::new(assign),
+                right: Box::new(set),
+            },
+            pt::Expression::AssignModulo(..) => Expression::Modulo {
+                loc: *loc,
+                ty: ty.clone(),
+                left: Box::new(assign),
+                right: Box::new(set),
+            },
             _ => unreachable!(),
         })
     };
@@ -4563,18 +4599,30 @@ fn incr_decr(
 ) -> Result<Expression, ()> {
     let op = |e: Expression, ty: Type| -> Expression {
         match expr {
-            pt::Expression::PreIncrement(loc, _) => {
-                Expression::PreIncrement(*loc, ty, context.unchecked, Box::new(e))
-            }
-            pt::Expression::PreDecrement(loc, _) => {
-                Expression::PreDecrement(*loc, ty, context.unchecked, Box::new(e))
-            }
-            pt::Expression::PostIncrement(loc, _) => {
-                Expression::PostIncrement(*loc, ty, context.unchecked, Box::new(e))
-            }
-            pt::Expression::PostDecrement(loc, _) => {
-                Expression::PostDecrement(*loc, ty, context.unchecked, Box::new(e))
-            }
+            pt::Expression::PreIncrement(loc, _) => Expression::PreIncrement {
+                loc: *loc,
+                ty,
+                unchecked: context.unchecked,
+                expr: Box::new(e),
+            },
+            pt::Expression::PreDecrement(loc, _) => Expression::PreDecrement {
+                loc: *loc,
+                ty,
+                unchecked: context.unchecked,
+                expr: Box::new(e),
+            },
+            pt::Expression::PostIncrement(loc, _) => Expression::PostIncrement {
+                loc: *loc,
+                ty,
+                unchecked: context.unchecked,
+                expr: Box::new(e),
+            },
+            pt::Expression::PostDecrement(loc, _) => Expression::PostDecrement {
+                loc: *loc,
+                ty,
+                unchecked: context.unchecked,
+                expr: Box::new(e),
+            },
             _ => unreachable!(),
         }
     };

+ 4 - 4
src/sema/mutability.rs

@@ -231,10 +231,10 @@ fn recurse_statements(stmts: &[Statement], ns: &Namespace, state: &mut StateChec
 
 fn read_expression(expr: &Expression, state: &mut StateCheck) -> bool {
     match expr {
-        Expression::PreIncrement(_, _, _, expr)
-        | Expression::PreDecrement(_, _, _, expr)
-        | Expression::PostIncrement(_, _, _, expr)
-        | Expression::PostDecrement(_, _, _, expr) => {
+        Expression::PreIncrement { expr, .. }
+        | Expression::PreDecrement { expr, .. }
+        | Expression::PostIncrement { expr, .. }
+        | Expression::PostDecrement { expr, .. } => {
             expr.recurse(state, write_expression);
         }
         Expression::Assign(_, _, left, right) => {

+ 14 - 14
src/sema/statements.rs

@@ -1412,13 +1412,13 @@ fn destructure_values(
             )?;
             used_variable(ns, &right, symtable);
 
-            return Ok(Expression::ConditionalOperator(
-                *loc,
-                Type::Unreachable,
-                Box::new(cond),
-                Box::new(left),
-                Box::new(right),
-            ));
+            return Ok(Expression::ConditionalOperator {
+                loc: *loc,
+                ty: Type::Unreachable,
+                cond: Box::new(cond),
+                true_option: Box::new(left),
+                false_option: Box::new(right),
+            });
         }
         _ => {
             let mut list = Vec::new();
@@ -1618,13 +1618,13 @@ fn return_with_values(
                 return_with_values(right, &right.loc(), context, symtable, ns, diagnostics)?;
             used_variable(ns, &right, symtable);
 
-            return Ok(Expression::ConditionalOperator(
-                *loc,
-                Type::Unreachable,
-                Box::new(cond),
-                Box::new(left),
-                Box::new(right),
-            ));
+            return Ok(Expression::ConditionalOperator {
+                loc: *loc,
+                ty: Type::Unreachable,
+                cond: Box::new(cond),
+                true_option: Box::new(left),
+                false_option: Box::new(right),
+            });
         }
         _ => {
             let returns = parameter_list_to_expr_list(returns, diagnostics)?;

+ 5 - 21
src/sema/unused_variable.rs

@@ -77,12 +77,7 @@ pub fn used_variable(ns: &mut Namespace, exp: &Expression, symtable: &mut Symtab
             assigned_variable(ns, &args[0], symtable);
             used_variable(ns, &args[0], symtable);
         }
-        Expression::StorageArrayLength {
-            loc: _,
-            ty: _,
-            array,
-            ..
-        } => {
+        Expression::StorageArrayLength { array, .. } => {
             //We should not eliminate an array from the code when 'length' is called
             //So the variable is also assigned
             assigned_variable(ns, array, symtable);
@@ -115,12 +110,7 @@ pub fn check_function_call(ns: &mut Namespace, exp: &Expression, symtable: &mut
             used_variable(ns, exp, symtable);
         }
 
-        Expression::InternalFunctionCall {
-            loc: _,
-            returns: _,
-            function,
-            args,
-        } => {
+        Expression::InternalFunctionCall { function, args, .. } => {
             for arg in args {
                 used_variable(ns, arg, symtable);
             }
@@ -128,11 +118,10 @@ pub fn check_function_call(ns: &mut Namespace, exp: &Expression, symtable: &mut
         }
 
         Expression::ExternalFunctionCall {
-            loc: _,
-            returns: _,
             function,
             args,
             call_args,
+            ..
         } => {
             for arg in args {
                 used_variable(ns, arg, symtable);
@@ -142,11 +131,7 @@ pub fn check_function_call(ns: &mut Namespace, exp: &Expression, symtable: &mut
         }
 
         Expression::Constructor {
-            loc: _,
-            contract_no: _,
-            constructor_no: _,
-            args,
-            call_args,
+            args, call_args, ..
         } => {
             for arg in args {
                 used_variable(ns, arg, symtable);
@@ -155,11 +140,10 @@ pub fn check_function_call(ns: &mut Namespace, exp: &Expression, symtable: &mut
         }
 
         Expression::ExternalFunctionCallRaw {
-            loc: _,
-            ty: _,
             address,
             args,
             call_args,
+            ..
         } => {
             used_variable(ns, args, symtable);
             used_variable(ns, address, symtable);