@@ -833,6 +833,7 @@ impl Lowerer {
833833 syntax:: ExprKind :: Lit ( lit) => self . lower_lit_expr ( lit, None ) ,
834834 syntax:: ExprKind :: Paren ( pexpr) => self . lower_paren_expr ( pexpr, expr. span ) ,
835835 syntax:: ExprKind :: UnaryOp ( expr) => self . lower_unary_op_expr ( expr) ,
836+ syntax:: ExprKind :: DurationOf ( expr) => self . lower_duration_of_expr ( expr) ,
836837 }
837838 }
838839
@@ -1120,6 +1121,17 @@ impl Lowerer {
11201121 }
11211122 }
11221123
1124+ fn lower_duration_of_expr ( & mut self , expr : & syntax:: DurationofCall ) -> semantic:: Expr {
1125+ let scope = self . lower_block ( & expr. scope ) ;
1126+ let ty = Type :: Duration ( true ) ;
1127+ let kind = semantic:: ExprKind :: DurationofCall ( semantic:: DurationofCallExpr {
1128+ span : expr. span ,
1129+ fn_name_span : expr. name_span ,
1130+ scope,
1131+ } ) ;
1132+ semantic:: Expr :: new ( expr. span , kind, ty)
1133+ }
1134+
11231135 fn lower_annotations ( annotations : & [ Box < syntax:: Annotation > ] ) -> Vec < semantic:: Annotation > {
11241136 annotations
11251137 . iter ( )
@@ -1277,7 +1289,10 @@ impl Lowerer {
12771289 None => self . cast_expr_with_target_type_or_default ( None , & ty, stmt_span) ,
12781290 } ;
12791291
1280- if init_expr. ty . is_const ( ) {
1292+ // If the type is a duration subtype, we need to evaluate the init_expr
1293+ // to get the const value and set it in the symbol.
1294+ // This is because duration subtypes can only be const.
1295+ if type_is_duration_subtype ( & init_expr. ty ) {
12811296 init_expr = init_expr. with_const_value ( self ) ;
12821297 symbol = symbol. with_const_expr ( Rc :: new ( init_expr. clone ( ) ) ) ;
12831298 }
@@ -3439,6 +3454,7 @@ impl Lowerer {
34393454 }
34403455 Type :: BitArray ( size, _) => Self :: cast_bitarray_expr_to_type ( * size, ty, expr) ,
34413456 Type :: Array ( ..) => Self :: cast_array_expr_to_type ( ty, expr) ,
3457+ Type :: Duration ( ..) | Type :: Stretch ( ..) => cast_duration_subtype_expr_to_type ( ty, expr) ,
34423458 _ => None ,
34433459 }
34443460 }
@@ -3894,22 +3910,10 @@ impl Lowerer {
38943910 let left_type = lhs. ty . clone ( ) ;
38953911 let right_type = rhs. ty . clone ( ) ;
38963912
3897- // // The spec says that only these operators are allowed on durations and stretches.
3898- // if !matches!(
3899- // op,
3900- // syntax::BinOp::Add | syntax::BinOp::Sub | syntax::BinOp::Mul | syntax::BinOp::Div
3901- // ) {
3902- // return unsupported_binop(op, left_type, right_type, span);
3903- // }
3904-
39053913 // <https://openqasm.com/language/types.html#converting-duration-to-other-types>
39063914 // Division of two durations results in a machine-precision float
39073915 // No other operations between durations are allowed.
39083916 if both_types_are_duration_subtypes ( & left_type, & right_type) {
3909- // if op == syntax::BinOp::Mul {
3910- // return unsupported_binop(op, left_type, right_type, span);
3911- // }
3912-
39133917 let ty = if op == syntax:: BinOp :: Div {
39143918 // Division of two durations results in a machine-precision float
39153919 Type :: Float ( None , true )
@@ -4543,6 +4547,22 @@ fn cast_complex_expr_to_type(ty: &Type, rhs: &semantic::Expr) -> Option<semantic
45434547 None
45444548}
45454549
4550+ fn cast_duration_subtype_expr_to_type ( ty : & Type , rhs : & semantic:: Expr ) -> Option < semantic:: Expr > {
4551+ assert ! ( matches!( rhs. ty, Type :: Duration ( ..) | Type :: Stretch ( ..) ) ) ;
4552+
4553+ // we know the rhs is a duration or a stretch
4554+ // if the target type is a duration subtype, we can 'cast' it
4555+ if type_is_duration_subtype ( ty) {
4556+ // duration can only 'cast' to a duration subtype.
4557+ // We aren't going to actually cast, we just
4558+ // change the type of the expression.
4559+ let mut expr = rhs. clone ( ) ;
4560+ expr. ty = ty. clone ( ) ;
4561+ return Some ( expr) ;
4562+ }
4563+ None
4564+ }
4565+
45464566fn get_identifier_name ( identifier : & syntax:: IdentOrIndexedIdent ) -> Arc < str > {
45474567 match identifier {
45484568 syntax:: IdentOrIndexedIdent :: Ident ( ident) => ident. name . clone ( ) ,
0 commit comments