fn resolve_field_name(scope: &ScopeStack, target: Expression, field: Identifier) -> Result<(ScopeItem, Identifier), Error> {
    // The full path of the target type
    // Something like `std::foo::Foo` or `u8` or `()`
    let (target_instance, target_type_path) = match target {
        Expression::Identifier(target_name) => scope.lookup(&target_name).first().ok_or_else(|| {
            Error::UnresolvedName(target_name.clone())
        }).and_then(|item| match **item {
            ScopeItem::Constant {type_id, ..} => Ok(((*item).clone(), type_id)),
            ScopeItem::TypedBlock {type_id, ..} => Ok(((*item).clone(), type_id)),
            ScopeItem::Array {..} => unimplemented!(),
            ScopeItem::BuiltInFunction {type_id, ..} => Err(Error::UnresolvedField {
                target_type: scope.get_type(type_id).clone(),
                field: field.clone(),
            }),
            // These are unreachable because numeric literals and byte literals are never stored
            // directly
            ScopeItem::NumericLiteral(..) | ScopeItem::ByteLiteral(..) => unreachable!(),
        }).map(|(item, type_id)| (item, scope.get_type_name(type_id).clone())),

        //TODO: It's likely that the below line will just not work at all
        // because the scope item returned in the tuple is not the target we should return.
        // I think we need to map on this result and return the field as the target...not sure.
        //Expression::Access {target, field} => resolve_field_name(scope, *target, field),
        Expression::Access {..} => unimplemented!(),

        //TODO: ByteLiterals are valid targets for field access
        // In this case, we need to return [u8; N] where N is the length of the byte literal
        // We also likely need to allocate and store this into a temporary variable
        Expression::ByteLiteral(..) => unimplemented!(),

        //TODO: Numbers are valid targets for field access
        // In this case, we need to return u8 or another valid type
        // We also likely need to allocate and store this into a temporary variable
        Expression::Number(..) => unimplemented!(),

        //TODO: Calls are valid targets for field access
        // In this case, we need to return the type name of the return type
        // Implementing this will be a bit more complicated since we need to do the call and return
        // the ops necessary for that
        Expression::Call {..} => unimplemented!(),

        //TODO: Branch expressions are valid targets for field access
        // In this case, we need to return the type name of the branches
        // Implementing this will be a bit more complicated since we need to do the branching and
        // return the ops necessary for that
        Expression::Branch {..} => unimplemented!(),

        //TODO: This is not supported, probably want a good error here though
        Expression::UnitLiteral => unreachable!(),
    }?;

    Ok((target_instance, target_type_path.concat(field)))
}
/// Returns the full path of the target type with the field appended to it
/// e.g. If target's type is `std::Foo` and field is `bar`, you get: `std::Foo::bar`
/// Also returns the target ScopeItem of this operation
/// Since this is a field access, it needs to operate on the target object that the `target`
/// expression refers to
Returns the full path of the target type with the field appended to it
e.g.
Returns the full path of the target type with the field appended to it e . g .
fn resolve_field_name(scope: &ScopeStack, target: Expression, field: Identifier) -> Result<(ScopeItem, Identifier), Error> {
    // The full path of the target type
    // Something like `std::foo::Foo` or `u8` or `()`
    let (target_instance, target_type_path) = match target {
        Expression::Identifier(target_name) => scope.lookup(&target_name).first().ok_or_else(|| {
            Error::UnresolvedName(target_name.clone())
        }).and_then(|item| match **item {
            ScopeItem::Constant {type_id, ..} => Ok(((*item).clone(), type_id)),
            ScopeItem::TypedBlock {type_id, ..} => Ok(((*item).clone(), type_id)),
            ScopeItem::Array {..} => unimplemented!(),
            ScopeItem::BuiltInFunction {type_id, ..} => Err(Error::UnresolvedField {
                target_type: scope.get_type(type_id).clone(),
                field: field.clone(),
            }),
            // These are unreachable because numeric literals and byte literals are never stored
            // directly
            ScopeItem::NumericLiteral(..) | ScopeItem::ByteLiteral(..) => unreachable!(),
        }).map(|(item, type_id)| (item, scope.get_type_name(type_id).clone())),
        //TODO: It's likely that the below line will just not work at all
        // because the scope item returned in the tuple is not the target we should return.
        // I think we need to map on this result and return the field as the target...not sure.
        //Expression::Access {target, field} => resolve_field_name(scope, *target, field),
        Expression::Access {..} => unimplemented!(),
        //TODO: ByteLiterals are valid targets for field access
        // In this case, we need to return [u8; N] where N is the length of the byte literal
        // We also likely need to allocate and store this into a temporary variable
        Expression::ByteLiteral(..) => unimplemented!(),
        //TODO: Numbers are valid targets for field access
        // In this case, we need to return u8 or another valid type
        // We also likely need to allocate and store this into a temporary variable
        Expression::Number(..) => unimplemented!(),
        //TODO: Calls are valid targets for field access
        // In this case, we need to return the type name of the return type
        // Implementing this will be a bit more complicated since we need to do the call and return
        // the ops necessary for that
        Expression::Call {..} => unimplemented!(),
        //TODO: Branch expressions are valid targets for field access
        // In this case, we need to return the type name of the branches
        // Implementing this will be a bit more complicated since we need to do the branching and
        // return the ops necessary for that
        Expression::Branch {..} => unimplemented!(),
        //TODO: This is not supported, probably want a good error here though
        Expression::UnitLiteral => unreachable!(),
    }?;
    Ok((target_instance, target_type_path.concat(field)))
}
fn resolve_field_name ( scope : & ScopeStack , target : Expression , field : Identifier ) -> Result < ( ScopeItem , Identifier ) , Error > { // The full path of the target type // Something like `std::foo::Foo` or `u8` or `()` let ( target_instance , target_type_path ) = match target { Expression :: Identifier ( target_name ) => scope . lookup ( & target_name ) . first ( ) . ok_or_else ( | | { Error :: UnresolvedName ( target_name . clone ( ) ) } ) . and_then ( | item | match * * item { ScopeItem :: Constant { type_id , .. } => Ok ( ( ( * item ) . clone ( ) , type_id ) ) , ScopeItem :: TypedBlock { type_id , .. } => Ok ( ( ( * item ) . clone ( ) , type_id ) ) , ScopeItem :: Array { .. } => unimplemented ! ( ) , ScopeItem :: BuiltInFunction { type_id , .. } => Err ( Error :: UnresolvedField { target_type : scope . get_type ( type_id ) . clone ( ) , field : field . clone ( ) , } ) , // These are unreachable because numeric literals and byte literals are never stored // directly ScopeItem :: NumericLiteral ( .. ) | ScopeItem :: ByteLiteral ( .. ) => unreachable ! ( ) , } ) . map ( | ( item , type_id ) | ( item , scope . get_type_name ( type_id ) . clone ( ) ) ) , //TODO: It's likely that the below line will just not work at all // because the scope item returned in the tuple is not the target we should return. // I think we need to map on this result and return the field as the target...not sure. //Expression::Access {target, field} => resolve_field_name(scope, *target, field), Expression :: Access { .. } => unimplemented ! ( ) , //TODO: ByteLiterals are valid targets for field access // In this case, we need to return [u8; N] where N is the length of the byte literal // We also likely need to allocate and store this into a temporary variable Expression :: ByteLiteral ( .. ) => unimplemented ! ( ) , //TODO: Numbers are valid targets for field access // In this case, we need to return u8 or another valid type // We also likely need to allocate and store this into a temporary variable Expression :: Number ( .. ) => unimplemented ! ( ) , //TODO: Calls are valid targets for field access // In this case, we need to return the type name of the return type // Implementing this will be a bit more complicated since we need to do the call and return // the ops necessary for that Expression :: Call { .. } => unimplemented ! ( ) , //TODO: Branch expressions are valid targets for field access // In this case, we need to return the type name of the branches // Implementing this will be a bit more complicated since we need to do the branching and // return the ops necessary for that Expression :: Branch { .. } => unimplemented ! ( ) , //TODO: This is not supported, probably want a good error here though Expression :: UnitLiteral => unreachable ! ( ) , } ? ; Ok ( ( target_instance , target_type_path . concat ( field ) ) ) }
Returns the full path of the target type with the field appended to it
e.g.
Returns the full path of the target type with the field appended to it e . g .
scope
&ScopeStack
target
Expression
field
Identifier
scope
&ScopeStack
target
Expression
field
Identifier