Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions crates/cairo-lang-defs/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1395,13 +1395,15 @@ fn validate_attributes<'db>(
}
}
ast::ModuleItem::Struct(item) => {
validate_attributes_element_list(
db,
allowed_attributes,
&extra_allowed_attributes,
item.members(db).elements(db),
plugin_diagnostics,
);
if let ast::StructBody::Braces(body) = item.body(db) {
validate_attributes_element_list(
db,
allowed_attributes,
&extra_allowed_attributes,
body.members(db).elements(db),
plugin_diagnostics,
);
}
}
ast::ModuleItem::Enum(item) => {
validate_attributes_element_list(
Expand Down
3 changes: 2 additions & 1 deletion crates/cairo-lang-defs/src/ids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -992,7 +992,8 @@ define_named_language_element_id!(MemberId, MemberLongId, ast::Member<'db>);
impl<'db> MemberId<'db> {
pub fn struct_id(&self, db: &'db dyn Database) -> StructId<'db> {
let MemberLongId(module_id, ptr) = self.long(db).clone();
let struct_ptr = ast::ItemStructPtr(ptr.untyped().nth_parent(db, 2));
// Member -> MemberList -> StructBodyBraces -> ItemStruct (3 levels up).
let struct_ptr = ast::ItemStructPtr(ptr.untyped().nth_parent(db, 3));
StructLongId(module_id, struct_ptr).intern(db)
}
}
Expand Down
30 changes: 24 additions & 6 deletions crates/cairo-lang-lowering/src/lower/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1834,12 +1834,30 @@ fn lower_expr_member_access<'db>(
.collect();
(member_tys, member_idx)
}
TypeMemberKind::TupleElement(idx) => {
let tys = extract_matches!(container_long_ty, TypeLongId::Tuple);
let member_tys =
tys.iter().map(|&ty| wrap_in_snapshots(ctx.db, ty, expr.n_snapshots)).collect();
(member_tys, *idx)
}
TypeMemberKind::TupleElement(idx) => match container_long_ty {
TypeLongId::Tuple(tys) => {
let member_tys =
tys.iter().map(|&ty| wrap_in_snapshots(ctx.db, ty, expr.n_snapshots)).collect();
(member_tys, *idx)
}
TypeLongId::Concrete(semantic::ConcreteTypeId::Struct(concrete_struct_id)) => {
let positional_tys = ctx
.db
.concrete_struct_positional_types(concrete_struct_id)
.map_err(LoweringFlowError::Failed)?
.ok_or_else(|| {
LoweringFlowError::Failed(
ctx.diagnostics.report(expr.stable_ptr.untyped(), UnexpectedError),
)
})?;
let member_tys = positional_tys
.iter()
.map(|&(ty, _)| wrap_in_snapshots(ctx.db, ty, expr.n_snapshots))
.collect();
(member_tys, *idx)
}
_ => unreachable!("TupleElement access on unexpected container type"),
},
};
Ok(LoweredExpr::AtVariable(
generators::StructMemberAccess {
Expand Down
45 changes: 38 additions & 7 deletions crates/cairo-lang-parser/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,8 @@ impl<'a, 'mt> Parser<'a, 'mt> {
}

/// Assumes the current token is Struct.
/// Expected pattern: `struct<Identifier>{<ParamList>}`
/// Expected pattern: `struct<Identifier>{<MemberList>}` or
/// `struct<Identifier>(<StructArgMemberList>)`.
fn expect_item_struct(
&mut self,
attributes: AttributeListGreen<'a>,
Expand All @@ -495,22 +496,52 @@ impl<'a, 'mt> Parser<'a, 'mt> {
let struct_kw = self.take::<TerminalStruct<'_>>();
let name = self.parse_identifier();
let generic_params = self.parse_optional_generic_params();
let lbrace = self.parse_token::<TerminalLBrace<'_>>();
let members = self.parse_member_list();
let rbrace = self.parse_token::<TerminalRBrace<'_>>();
let body = if self.peek().kind == SyntaxKind::TerminalLParen {
let lparen = self.take::<TerminalLParen<'_>>();
let members = self.parse_struct_arg_member_list();
let rparen = self.parse_token::<TerminalRParen<'_>>();
StructBodyParens::new_green(self.db, lparen, members, rparen).into()
} else {
let lbrace = self.parse_token::<TerminalLBrace<'_>>();
let members = self.parse_member_list();
let rbrace = self.parse_token::<TerminalRBrace<'_>>();
StructBodyBraces::new_green(self.db, lbrace, members, rbrace).into()
};
ItemStruct::new_green(
self.db,
attributes,
visibility,
struct_kw,
name,
generic_params,
lbrace,
members,
rbrace,
body,
)
}

/// Returns a GreenId of a node with kind StructArgMemberList.
fn parse_struct_arg_member_list(&mut self) -> StructArgMemberListGreen<'a> {
StructArgMemberList::new_green(
self.db,
&self.parse_separated_list::<
StructArgMember<'_>,
TerminalComma<'_>,
StructArgMemberListElementOrSeparatorGreen<'_>,
>(
Self::try_parse_struct_arg_member,
is_of_kind!(rparen, block, lbrace, rbrace, module_item_kw),
"type",
),
)
}

/// Returns a GreenId of a node with kind StructArgMember, or TryParseFailure if a positional
/// struct member can't be parsed.
fn try_parse_struct_arg_member(&mut self) -> TryParseResult<StructArgMemberGreen<'a>> {
let visibility = self.parse_visibility();
let ty = self.try_parse_type_expr()?;
Ok(StructArgMember::new_green(self.db, visibility, ty))
}

/// Assumes the current token is Enum.
/// Expected pattern: `enum<Identifier>{<ParamList>}`
fn expect_item_enum(
Expand Down
Loading
Loading