@@ -119,6 +119,18 @@ fn check_expr(expr: &QccCell<Expr>) -> Result<Type> {
119119
120120 Ok ( val_type)
121121 }
122+ Expr :: Assign ( ref var, ref val) => {
123+ if !var. is_typed ( ) {
124+ return Err ( QccErrorKind :: UnknownType ) ?;
125+ }
126+ let val_type = check_expr ( val) ?;
127+
128+ if var. get_type ( ) != val_type {
129+ return Err ( QccErrorKind :: TypeMismatch ) ?;
130+ }
131+
132+ Ok ( val_type)
133+ }
122134 Expr :: Conditional ( ref conditional, ref truth_block, ref false_block) => {
123135 for expr in truth_block {
124136 check_expr ( expr) ;
@@ -435,6 +447,23 @@ fn infer_expr(expr: &QccCell<Expr>) -> Option<Type> {
435447 }
436448 }
437449
450+ Expr :: Assign ( ref mut var, ref val) => {
451+ // val is an expression and it must have the same type as var
452+ if var. get_type ( ) == Type :: Bottom {
453+ // we need to type check from expression first
454+ let rhs_type = infer_expr ( & val) ?;
455+ var. set_type ( rhs_type) ;
456+ return Some ( rhs_type) ;
457+ } else {
458+ let lhs_type = var. get_type ( ) ;
459+ let rhs_type = infer_expr ( & val) ?;
460+ if lhs_type != rhs_type {
461+ return None ;
462+ }
463+ return Some ( lhs_type) ;
464+ }
465+ }
466+
438467 Expr :: Conditional ( ref conditional, ref truth_block, ref false_block) => {
439468 let mut truth_block_type = Some ( Type :: Bottom ) ;
440469 for expr in truth_block {
@@ -646,6 +675,55 @@ fn infer_from_table(
646675 . into ( ) ) )
647676 }
648677 }
678+ Expr :: Assign ( ref mut var, ref val) => {
679+ let rhs_info = infer_from_table ( val, param_st, local_st, function_st) ;
680+
681+ if rhs_info. is_some ( ) {
682+ return rhs_info;
683+ }
684+
685+ let var_type = var. get_type ( ) ;
686+ let val_type = val. as_ref ( ) . borrow ( ) . get_type ( ) ;
687+
688+ if !var. is_typed ( ) {
689+ var. set_type ( val. as_ref ( ) . borrow ( ) . get_type ( ) ) ;
690+ None
691+ } else if ( var_type == Type :: Qbit || var_type == Type :: Bit )
692+ && ( val_type == Type :: Qbit || val_type == Type :: Bit )
693+ && ( var_type != val_type)
694+ {
695+ // If one of lhs or rhs is qbit while the other is bit, then we
696+ // will put a measure operator before it is assigned during
697+ // codegen.
698+ //
699+ // let x: bit = y; # y := qbit
700+ //
701+ // This holds according to our subtyping rules. Codegen will
702+ // lower this to:
703+ //
704+ // let x0: bit = measure(y);
705+ // let x: bit = x0;
706+ //
707+ // Similarily,
708+ //
709+ // let x: qbit = y; # y := bit
710+ //
711+ // This is also fine. When codegen lowers this code, it
712+ // automatically puts required stub to create a logical qubit.
713+ None
714+ } else if var_type == val_type {
715+ None
716+ } else if var_type != val_type {
717+ // if one is qbit and other is bit, pass
718+ Some ( Err ( QccErrorKind :: TypeMismatch . into ( ) ) )
719+ } else {
720+ Some ( Ok ( Expr :: Var ( VarAST :: new (
721+ var. name ( ) . clone ( ) ,
722+ var. location ( ) . clone ( ) ,
723+ ) )
724+ . into ( ) ) )
725+ }
726+ }
649727 Expr :: Conditional ( ref mut conditional, ref mut truth_block, ref mut false_block) => {
650728 for expr in truth_block {
651729 let info = infer_from_table ( expr, param_st, local_st, function_st) ;
0 commit comments