microsoft/qdk
Publicmirrored from https://github.com/microsoft/qdkAvailable
source/compiler/qsc_fir/src/extensions.rs
123lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | use crate::{ |
| 5 | fir::{CallableDecl, LocalVarId, Package, Pat, PatId, PatKind}, |
| 6 | ty::Ty, |
| 7 | }; |
| 8 | use qsc_data_structures::index_map::IndexMap; |
| 9 | |
| 10 | /// The index corresponding to an input parameter. |
| 11 | #[derive(Clone, Copy, Debug, Eq, PartialEq)] |
| 12 | pub struct InputParamIndex(usize); |
| 13 | |
| 14 | impl From<InputParamIndex> for usize { |
| 15 | fn from(value: InputParamIndex) -> Self { |
| 16 | value.0 |
| 17 | } |
| 18 | } |
| 19 | |
| 20 | impl From<usize> for InputParamIndex { |
| 21 | fn from(value: usize) -> Self { |
| 22 | Self(value) |
| 23 | } |
| 24 | } |
| 25 | |
| 26 | /// An input parameter. |
| 27 | #[derive(Clone, Debug)] |
| 28 | pub struct InputParam { |
| 29 | pub index: InputParamIndex, |
| 30 | pub pat: PatId, |
| 31 | pub ty: Ty, |
| 32 | pub var: Option<LocalVarId>, |
| 33 | } |
| 34 | |
| 35 | impl Package { |
| 36 | #[must_use] |
| 37 | pub fn derive_callable_input_params(&self, callable: &CallableDecl) -> Vec<InputParam> { |
| 38 | let input_elements = derive_callable_input_pattern_elements(callable, &self.pats); |
| 39 | let mut input_params = Vec::new(); |
| 40 | let mut param_index = InputParamIndex(0); |
| 41 | for element in input_elements { |
| 42 | let maybe_input_param = match &element.kind { |
| 43 | InputPatternElementKind::Discard => Some(InputParam { |
| 44 | index: param_index, |
| 45 | pat: element.pat, |
| 46 | ty: element.ty.clone(), |
| 47 | var: None, |
| 48 | }), |
| 49 | InputPatternElementKind::Ident(local_var_id) => Some(InputParam { |
| 50 | index: param_index, |
| 51 | pat: element.pat, |
| 52 | ty: element.ty.clone(), |
| 53 | var: Some(*local_var_id), |
| 54 | }), |
| 55 | InputPatternElementKind::Tuple => None, |
| 56 | }; |
| 57 | |
| 58 | if let Some(input_param) = maybe_input_param { |
| 59 | input_params.push(input_param); |
| 60 | param_index.0 += 1; |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | input_params |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | /// An element related to an input pattern. |
| 69 | #[derive(Debug)] |
| 70 | struct InputPatternElement { |
| 71 | pub pat: PatId, |
| 72 | pub ty: Ty, |
| 73 | pub kind: InputPatternElementKind, |
| 74 | } |
| 75 | |
| 76 | /// Kinds of input pattern elements. |
| 77 | #[derive(Debug)] |
| 78 | enum InputPatternElementKind { |
| 79 | Discard, |
| 80 | Ident(LocalVarId), |
| 81 | Tuple, |
| 82 | } |
| 83 | |
| 84 | /// Creates a vector of flattened input pattern elements. |
| 85 | fn derive_callable_input_pattern_elements( |
| 86 | callable: &CallableDecl, |
| 87 | pats: &IndexMap<PatId, Pat>, |
| 88 | ) -> Vec<InputPatternElement> { |
| 89 | fn create_input_elements( |
| 90 | pat_id: PatId, |
| 91 | pats: &IndexMap<PatId, Pat>, |
| 92 | ) -> Vec<InputPatternElement> { |
| 93 | let pat = pats.get(pat_id).expect("pattern should exist"); |
| 94 | match &pat.kind { |
| 95 | PatKind::Bind(ident) => { |
| 96 | vec![InputPatternElement { |
| 97 | pat: pat_id, |
| 98 | ty: pat.ty.clone(), |
| 99 | kind: InputPatternElementKind::Ident(ident.id), |
| 100 | }] |
| 101 | } |
| 102 | PatKind::Tuple(tuple_pats) => { |
| 103 | let mut tuple_params = vec![InputPatternElement { |
| 104 | pat: pat_id, |
| 105 | ty: pat.ty.clone(), |
| 106 | kind: InputPatternElementKind::Tuple, |
| 107 | }]; |
| 108 | for tuple_item_pat_id in tuple_pats { |
| 109 | let mut tuple_item_params = create_input_elements(*tuple_item_pat_id, pats); |
| 110 | tuple_params.append(&mut tuple_item_params); |
| 111 | } |
| 112 | tuple_params |
| 113 | } |
| 114 | PatKind::Discard => vec![InputPatternElement { |
| 115 | pat: pat_id, |
| 116 | ty: pat.ty.clone(), |
| 117 | kind: InputPatternElementKind::Discard, |
| 118 | }], |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | create_input_elements(callable.input, pats) |
| 123 | } |