// An array type can look like foo[2] foo.baz.bar, if foo is an enum type. The lalrpop parses
// this as an expression, so we need to convert it to Type and check there are
// no unexpected expressions types.
An array type can look like foo[2] foo.baz.bar, if foo is an enum type. The lalrpop parses
this as an expression, so we need to convert it to Type and check there are
no unexpected expressions types.
An array type can look like foo [ 2 ] foo . baz . bar if foo is an enum type . The lalrpop parses this as an expression so we need to convert it to Type and check there are no unexpected expressions types .
pub fn expr_to_type<'a>(
        &mut self,
        file_no: usize,
        contract_no: Option<usize>,
        expr: &'a pt::Expression,
        diagnostics: &mut Vec<ast::Diagnostic>,
    ) -> Result<(Vec<&'a pt::Identifier>, pt::Expression, Vec<ArrayDimension>), ()> {
        let mut expr = expr;
        let mut dimensions = Vec::new();
        loop {
            expr = match expr {
                pt::Expression::ArraySubscript(_, r, None) => {
                    dimensions.push(None);
                    r.as_ref()
                }
                pt::Expression::ArraySubscript(_, r, Some(index)) => {
                    dimensions.push(self.resolve_array_dimension(
                        file_no,
                        contract_no,
                        index,
                        diagnostics,
                    )?);
                    r.as_ref()
                }
                pt::Expression::Variable(_) | pt::Expression::Type(_, _) => {
                    return Ok((Vec::new(), expr.clone(), dimensions))
                }
                pt::Expression::MemberAccess(_, namespace, id) => {
                    let mut names = Vec::new();
                    let mut expr = namespace.as_ref();
                    while let pt::Expression::MemberAccess(_, member, name) = expr {
                        names.insert(0, name);
                        expr = member.as_ref();
                    }
                    if let pt::Expression::Variable(namespace) = expr {
                        names.insert(0, namespace);
                        return Ok((names, pt::Expression::Variable(id.clone()), dimensions));
                    } else {
                        diagnostics.push(ast::Diagnostic::decl_error(
                            namespace.loc(),
                            "expression found where type expected".to_string(),
                        ));
                        return Err(());
                    }
                }
                _ => {
                    diagnostics.push(ast::Diagnostic::decl_error(
                        expr.loc(),
                        "expression found where type expected".to_string(),
                    ));
                    return Err(());
                }
            }
        }
    }
pub fn expr_to_type < ' a > ( & mut self , file_no : usize , contract_no : Option < usize > , expr : & ' a pt :: Expression , diagnostics : & mut Vec < ast :: Diagnostic > , ) -> Result < ( Vec < & ' a pt :: Identifier > , pt :: Expression , Vec < ArrayDimension > ) , ( ) > { let mut expr = expr ; let mut dimensions = Vec :: new ( ) ; loop { expr = match expr { pt :: Expression :: ArraySubscript ( _ , r , None ) => { dimensions . push ( None ) ; r . as_ref ( ) } pt :: Expression :: ArraySubscript ( _ , r , Some ( index ) ) => { dimensions . push ( self . resolve_array_dimension ( file_no , contract_no , index , diagnostics , ) ? ) ; r . as_ref ( ) } pt :: Expression :: Variable ( _ ) | pt :: Expression :: Type ( _ , _ ) => { return Ok ( ( Vec :: new ( ) , expr . clone ( ) , dimensions ) ) } pt :: Expression :: MemberAccess ( _ , namespace , id ) => { let mut names = Vec :: new ( ) ; let mut expr = namespace . as_ref ( ) ; while let pt :: Expression :: MemberAccess ( _ , member , name ) = expr { names . insert ( 0 , name ) ; expr = member . as_ref ( ) ; } if let pt :: Expression :: Variable ( namespace ) = expr { names . insert ( 0 , namespace ) ; return Ok ( ( names , pt :: Expression :: Variable ( id . clone ( ) ) , dimensions ) ) ; } else { diagnostics . push ( ast :: Diagnostic :: decl_error ( namespace . loc ( ) , " " . to_string ( ) , ) ) ; return Err ( ( ) ) ; } } _ => { diagnostics . push ( ast :: Diagnostic :: decl_error ( expr . loc ( ) , " " . to_string ( ) , ) ) ; return Err ( ( ) ) ; } } } }
An array type can look like foo[2] foo.baz.bar, if foo is an enum type.
An array type can look like foo [ 2 ] foo . baz . bar if foo is an enum type .
&mut self
file_no
usize
contract_no
Option<usize>
expr
&'a pt::Expression
diagnostics
&mut Vec<ast::Diagnostic>