/// Attempts to infer the size of the array from various pieces of information
Attempts to infer the size of the array from various pieces of information
Attempts to infer the size of the array from various pieces of information
fn infer_size(
    scope: &ScopeStack,
    item_type: TypeId,
    size_expr: Option<Expression>,
    expr: &Option<Expression>,
    name: &Identifier,
) -> Result<ArraySize, Error> {
    //TODO: Do this better. Ideally, this kind of inference would be done in a separate
    // pass with all the other inference that needs to be done.
    match size_expr {
        Some(Expression::Number(value)) if value > 0 => Ok(value as ArraySize),
        // Since no size was declared, try to infer it from the expression
        None if expr.is_some() => match *expr.as_ref().unwrap() {
            Expression::ByteLiteral(ref literal) => Ok(literal.len()),
            Expression::Identifier(ref name) => scope.lookup(name).first().ok_or_else(|| {
                Error::UnresolvedName(name.clone())
            }).and_then(|item| match **item {
                ScopeItem::ByteLiteral(ref bytes) => Ok(bytes.len()),
                ScopeItem::Array {item, size, ..} if item == item_type => Ok(size),
                ref item => Err(Error::MismatchedTypes {
                    expected: ItemType::Array {
                        item: Some(item_type),
                        size: None,
                    },
                    found: match *item {
                        //TODO: Update this when more numeric types are added
                        ScopeItem::NumericLiteral(..) => scope.get_type(scope.primitives().u8()).clone(),
                        ScopeItem::ByteLiteral(..) => unreachable!(),
                        ScopeItem::Array {item, size, ..} => ItemType::Array {item: Some(item), size: Some(size)},
                        ref arg => scope.get_type(arg.type_id()).clone(),
                    },
                }),
            }),
            Expression::Number(..) => Err(Error::MismatchedTypes {
                expected: ItemType::Array {
                    item: Some(item_type),
                    size: None,
                },
                //TODO: Update this when more numeric types are added
                found: scope.get_type(scope.primitives().u8()).clone(),
            }),
            // These are unimplemented until a more robust static analysis is implemented
            //TODO: These can all be inferred, it would just be way too messy to do it here
            Expression::UnitLiteral | Expression::Call {..} | Expression::Access {..} | Expression::Branch {..} => unimplemented!(),
        },
        _ => Err(Error::UnsupportedArrayType {name: name.clone()}),
    }
}
fn infer_size ( scope : & ScopeStack , item_type : TypeId , size_expr : Option < Expression > , expr : & Option < Expression > , name : & Identifier , ) -> Result < ArraySize , Error > { //TODO: Do this better. Ideally, this kind of inference would be done in a separate // pass with all the other inference that needs to be done. match size_expr { Some ( Expression :: Number ( value ) ) if value > 0 => Ok ( value as ArraySize ) , // Since no size was declared, try to infer it from the expression None if expr . is_some ( ) => match * expr . as_ref ( ) . unwrap ( ) { Expression :: ByteLiteral ( ref literal ) => Ok ( literal . len ( ) ) , Expression :: Identifier ( ref name ) => scope . lookup ( name ) . first ( ) . ok_or_else ( | | { Error :: UnresolvedName ( name . clone ( ) ) } ) . and_then ( | item | match * * item { ScopeItem :: ByteLiteral ( ref bytes ) => Ok ( bytes . len ( ) ) , ScopeItem :: Array { item , size , .. } if item == item_type => Ok ( size ) , ref item => Err ( Error :: MismatchedTypes { expected : ItemType :: Array { item : Some ( item_type ) , size : None , } , found : match * item { //TODO: Update this when more numeric types are added ScopeItem :: NumericLiteral ( .. ) => scope . get_type ( scope . primitives ( ) . u8 ( ) ) . clone ( ) , ScopeItem :: ByteLiteral ( .. ) => unreachable ! ( ) , ScopeItem :: Array { item , size , .. } => ItemType :: Array { item : Some ( item ) , size : Some ( size ) } , ref arg => scope . get_type ( arg . type_id ( ) ) . clone ( ) , } , } ) , } ) , Expression :: Number ( .. ) => Err ( Error :: MismatchedTypes { expected : ItemType :: Array { item : Some ( item_type ) , size : None , } , //TODO: Update this when more numeric types are added found : scope . get_type ( scope . primitives ( ) . u8 ( ) ) . clone ( ) , } ) , // These are unimplemented until a more robust static analysis is implemented //TODO: These can all be inferred, it would just be way too messy to do it here Expression :: UnitLiteral | Expression :: Call { .. } | Expression :: Access { .. } | Expression :: Branch { .. } => unimplemented ! ( ) , } , _ => Err ( Error :: UnsupportedArrayType { name : name . clone ( ) } ) , } }
Attempts to infer the size of the array from various pieces of information
Attempts to infer the size of the array from various pieces of information
scope
&ScopeStack
item_type
TypeId
size_expr
Option<Expression>
expr
&Option<Expression>
name
&Identifier