Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API: Wrap *Kind enums in *Kind enums #244

Merged
merged 7 commits into from
Sep 17, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions marker_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ version = { workspace = true }
[dependencies]
visibility = { workspace = true }

[dev-dependencies]
expect-test = { workspace = true }

[features]
# Some items should only be used by the driver implementing the functionality,
# this feature enables the export of these items. Note that this interface is
Expand Down
29 changes: 1 addition & 28 deletions marker_api/src/ast/common/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,32 +142,5 @@ new_id! {

new_id! {
/// This ID uniquely identifies a statement during linting.
pub StmtId: StmtIdInner
}

impl StmtId {
/// This is an extra constructor for api internal use. The `new_id` macro
/// only generates methods for drivers.
pub(crate) fn ast_new(data: StmtIdInner) -> Self {
Self { data }
}
}

#[repr(C)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "driver-api", visibility::make(pub))]
#[allow(clippy::exhaustive_enums)] // Only driver public
pub(crate) enum StmtIdInner {
Expr(ExprId),
Item(ItemId),
LetStmt(LetStmtId),
}

new_id! {
/// **Unstable**
///
/// This id is used to identify a `let` statement. It's intended to be used
/// inside [`StmtIdInner`]
#[cfg_attr(feature = "driver-api", visibility::make(pub))]
pub(crate) LetStmtId: u64
pub StmtId: u64
}
65 changes: 33 additions & 32 deletions marker_api/src/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,43 +368,44 @@ impl<'ast> ConstExpr<'ast> {
#[cfg(all(test, target_arch = "x86_64", target_pointer_width = "64"))]
mod test {
use super::*;
use expect_test::expect;
use std::mem::size_of;

#[test]
fn test_expr_struct_size() {
// These sizes are allowed to change, this is just a check to have a
// general overview and to prevent accidental changes
assert_eq!(40, size_of::<IntLitExpr<'_>>(), "IntLitExpr<'_>");
assert_eq!(32, size_of::<FloatLitExpr<'_>>(), "FloatLitExpr<'_>");
assert_eq!(48, size_of::<StrLitExpr<'_>>(), "StrLitExpr<'_>");
assert_eq!(24, size_of::<CharLitExpr<'_>>(), "CharLitExpr<'_>");
assert_eq!(24, size_of::<BoolLitExpr<'_>>(), "BoolLitExpr<'_>");
assert_eq!(96, size_of::<BlockExpr<'_>>(), "BlockExpr<'_>");
assert_eq!(72, size_of::<ClosureExpr<'_>>(), "ClosureExpr<'_>");
assert_eq!(40, size_of::<UnaryOpExpr<'_>>(), "UnaryOpExpr<'_>");
assert_eq!(40, size_of::<RefExpr<'_>>(), "RefExpr<'_>");
assert_eq!(56, size_of::<BinaryOpExpr<'_>>(), "BinaryOpExpr<'_>");
assert_eq!(32, size_of::<TryExpr<'_>>(), "TryExpr<'_>");
assert_eq!(80, size_of::<AssignExpr<'_>>(), "AssignExpr<'_>");
assert_eq!(48, size_of::<AsExpr<'_>>(), "AsExpr<'_>");
assert_eq!(96, size_of::<PathExpr<'_>>(), "PathExpr<'_>");
assert_eq!(48, size_of::<CallExpr<'_>>(), "CallExpr<'_>");
assert_eq!(80, size_of::<MethodExpr<'_>>(), "MethodExpr<'_>");
assert_eq!(56, size_of::<ArrayExpr<'_>>(), "ArrayExpr<'_>");
assert_eq!(32, size_of::<TupleExpr<'_>>(), "TupleExpr<'_>");
assert_eq!(136, size_of::<CtorExpr<'_>>(), "CtorExpr<'_>");
assert_eq!(72, size_of::<RangeExpr<'_>>(), "RangeExpr<'_>");
assert_eq!(48, size_of::<IndexExpr<'_>>(), "IndexExpr<'_>");
assert_eq!(48, size_of::<FieldExpr<'_>>(), "FieldExpr<'_>");
assert_eq!(72, size_of::<IfExpr<'_>>(), "IfExpr<'_>");
assert_eq!(72, size_of::<LetExpr<'_>>(), "LetExpr<'_>");
assert_eq!(48, size_of::<MatchExpr<'_>>(), "MatchExpr<'_>");
assert_eq!(72, size_of::<BreakExpr<'_>>(), "BreakExpr<'_>");
assert_eq!(40, size_of::<ReturnExpr<'_>>(), "ReturnExpr<'_>");
assert_eq!(48, size_of::<ContinueExpr<'_>>(), "ContinueExpr<'_>");
assert_eq!(112, size_of::<ForExpr<'_>>(), "ForExpr<'_>");
assert_eq!(56, size_of::<LoopExpr<'_>>(), "LoopExpr<'_>");
assert_eq!(72, size_of::<WhileExpr<'_>>(), "WhileExpr<'_>");
assert_eq!(24, size_of::<UnstableExpr<'_>>(), "UnstableExpr<'_>");
expect!["IntLitExpr = 40"].assert_eq(&format!("IntLitExpr = {}", size_of::<IntLitExpr<'_>>()));
xFrednet marked this conversation as resolved.
Show resolved Hide resolved
expect!["FloatLitExpr = 32"].assert_eq(&format!("FloatLitExpr = {}", size_of::<FloatLitExpr<'_>>()));
expect!["StrLitExpr = 48"].assert_eq(&format!("StrLitExpr = {}", size_of::<StrLitExpr<'_>>()));
expect!["CharLitExpr = 24"].assert_eq(&format!("CharLitExpr = {}", size_of::<CharLitExpr<'_>>()));
expect!["BoolLitExpr = 24"].assert_eq(&format!("BoolLitExpr = {}", size_of::<BoolLitExpr<'_>>()));
expect!["BlockExpr = 96"].assert_eq(&format!("BlockExpr = {}", size_of::<BlockExpr<'_>>()));
expect!["ClosureExpr = 72"].assert_eq(&format!("ClosureExpr = {}", size_of::<ClosureExpr<'_>>()));
expect!["UnaryOpExpr = 40"].assert_eq(&format!("UnaryOpExpr = {}", size_of::<UnaryOpExpr<'_>>()));
expect!["RefExpr = 40"].assert_eq(&format!("RefExpr = {}", size_of::<RefExpr<'_>>()));
expect!["BinaryOpExpr = 56"].assert_eq(&format!("BinaryOpExpr = {}", size_of::<BinaryOpExpr<'_>>()));
expect!["TryExpr = 32"].assert_eq(&format!("TryExpr = {}", size_of::<TryExpr<'_>>()));
expect!["AssignExpr = 56"].assert_eq(&format!("AssignExpr = {}", size_of::<AssignExpr<'_>>()));
expect!["AsExpr = 48"].assert_eq(&format!("AsExpr = {}", size_of::<AsExpr<'_>>()));
expect!["PathExpr = 96"].assert_eq(&format!("PathExpr = {}", size_of::<PathExpr<'_>>()));
expect!["CallExpr = 48"].assert_eq(&format!("CallExpr = {}", size_of::<CallExpr<'_>>()));
expect!["MethodExpr = 80"].assert_eq(&format!("MethodExpr = {}", size_of::<MethodExpr<'_>>()));
expect!["ArrayExpr = 56"].assert_eq(&format!("ArrayExpr = {}", size_of::<ArrayExpr<'_>>()));
expect!["TupleExpr = 32"].assert_eq(&format!("TupleExpr = {}", size_of::<TupleExpr<'_>>()));
expect!["CtorExpr = 136"].assert_eq(&format!("CtorExpr = {}", size_of::<CtorExpr<'_>>()));
expect!["RangeExpr = 72"].assert_eq(&format!("RangeExpr = {}", size_of::<RangeExpr<'_>>()));
expect!["IndexExpr = 48"].assert_eq(&format!("IndexExpr = {}", size_of::<IndexExpr<'_>>()));
expect!["FieldExpr = 48"].assert_eq(&format!("FieldExpr = {}", size_of::<FieldExpr<'_>>()));
expect!["IfExpr = 72"].assert_eq(&format!("IfExpr = {}", size_of::<IfExpr<'_>>()));
expect!["LetExpr = 48"].assert_eq(&format!("LetExpr = {}", size_of::<LetExpr<'_>>()));
expect!["MatchExpr = 48"].assert_eq(&format!("MatchExpr = {}", size_of::<MatchExpr<'_>>()));
expect!["BreakExpr = 72"].assert_eq(&format!("BreakExpr = {}", size_of::<BreakExpr<'_>>()));
expect!["ReturnExpr = 40"].assert_eq(&format!("ReturnExpr = {}", size_of::<ReturnExpr<'_>>()));
expect!["ContinueExpr = 48"].assert_eq(&format!("ContinueExpr = {}", size_of::<ContinueExpr<'_>>()));
expect!["ForExpr = 88"].assert_eq(&format!("ForExpr = {}", size_of::<ForExpr<'_>>()));
expect!["LoopExpr = 56"].assert_eq(&format!("LoopExpr = {}", size_of::<LoopExpr<'_>>()));
expect!["WhileExpr = 72"].assert_eq(&format!("WhileExpr = {}", size_of::<WhileExpr<'_>>()));
expect!["UnstableExpr = 24"].assert_eq(&format!("UnstableExpr = {}", size_of::<UnstableExpr<'_>>()));
}
}
41 changes: 18 additions & 23 deletions marker_api/src/ast/pat.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
use crate::{private::Sealed, CtorBlocker};
use crate::private::Sealed;

use super::{
expr::{ExprKind, LitExprKind},
Span, SpanId,
};
use super::{Span, SpanId};

use std::{fmt::Debug, marker::PhantomData};

mod ident_pat;
mod lit_pat;
mod or_pat;
mod path_pat;
mod place_pat;
mod range_pat;
mod ref_pat;
mod rest_pat;
Expand All @@ -19,8 +18,10 @@ mod tuple_pat;
mod unstable_pat;
mod wildcard_pat;
pub use ident_pat::*;
pub use lit_pat::*;
pub use or_pat::*;
pub use path_pat::*;
pub use place_pat::*;
pub use range_pat::*;
pub use ref_pat::*;
pub use rest_pat::*;
Expand All @@ -30,7 +31,7 @@ pub use tuple_pat::*;
pub use unstable_pat::*;
pub use wildcard_pat::*;

/// This trait combines methods, which are common between all patterns.
/// This trait combines methods, which all patterns have in common.
///
/// This trait is only meant to be implemented inside this crate. The `Sealed`
/// super trait prevents external implementations.
Expand All @@ -51,10 +52,10 @@ pub enum PatKind<'ast> {
Tuple(&'ast TuplePat<'ast>),
Slice(&'ast SlicePat<'ast>),
Or(&'ast OrPat<'ast>),
/// Patterns are used as assignees in [`AssignExpr`](super::expr::AssignExpr)
/// Patterns are used as assignees in [`AssignExpr`](crate::ast::expr::AssignExpr)
/// nodes. Assign expressions can target place expressions like
/// variables, [`IndexExpr`](super::expr::IndexExpr)s and
/// [`FieldExpr`](super::expr::FieldExpr)s. These expressions would
/// variables, [`IndexExpr`](crate::ast::expr::IndexExpr)s and
/// [`FieldExpr`](crate::ast::expr::FieldExpr)s. These expressions would
/// be stored as this variant.
///
/// ```
Expand All @@ -72,18 +73,18 @@ pub enum PatKind<'ast> {
/// // ^^^^ An index expression on local variable `c`
///
/// (a, b.0) = some_fn();
/// // ^^^^^^^^ Place expressions nested in a tuple pattern
/// // ^ ^^^ Place expressions nested in a tuple pattern
/// ```
///
/// Place expressions can currently only occur as targets in
/// [`AssignExpr`](super::expr::AssignExpr)s. Patterns from
/// [`LetStmts`](super::stmt::LetStmt)s and arguments in
/// [`FnItem`](super::item::FnItem) will never contain place expressions.
/// Static paths identifying [`ConstItem`](super::item::ConstItem)s or
/// [`EnumItem`](super::item::EnumItem) variants are expressed with the
/// [`AssignExpr`](crate::ast::expr::AssignExpr)s. Patterns from
/// [`LetStmts`](crate::ast::stmt::LetStmt)s and arguments in
/// [`FnItem`](crate::ast::item::FnItem) will never contain place expressions.
/// Static paths identifying [`ConstItem`](crate::ast::item::ConstItem)s or
/// [`EnumItem`](crate::ast::item::EnumItem) variants are expressed with the
/// [`PatKind::Path`] variant.
Place(ExprKind<'ast>, CtorBlocker),
Lit(LitExprKind<'ast>, CtorBlocker),
Place(&'ast PlacePat<'ast>),
Lit(&'ast LitPat<'ast>),
Path(&'ast PathPat<'ast>),
Range(&'ast RangePat<'ast>),
Unstable(&'ast UnstablePat<'ast>),
Expand Down Expand Up @@ -111,12 +112,6 @@ macro_rules! impl_pat_data_fn {

use impl_pat_data_fn;

impl<'ast> PatData<'ast> for ExprKind<'ast> {
fn span(&self) -> &Span<'ast> {
self.span()
}
}

#[repr(C)]
#[derive(Debug)]
#[cfg_attr(feature = "driver-api", visibility::make(pub))]
Expand Down
36 changes: 36 additions & 0 deletions marker_api/src/ast/pat/lit_pat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use crate::ast::expr::LitExprKind;

use super::CommonPatData;

/// A literal expression inside a pattern.
///
/// ```
/// # let string = "marker remix";
/// match string {
/// "example" => true,
/// // ^^^^^^^^^ A string literal used as a pattern
/// _ => false,
/// };
/// ```
#[repr(C)]
#[derive(Debug)]
pub struct LitPat<'ast> {
data: CommonPatData<'ast>,
lit: LitExprKind<'ast>,
}

impl<'ast> LitPat<'ast> {
/// The literal expression used as a pattern.
pub fn lit_expr(&self) -> LitExprKind<'ast> {
xFrednet marked this conversation as resolved.
Show resolved Hide resolved
self.lit
}
}

super::impl_pat_data!(LitPat<'ast>, Lit);

#[cfg(feature = "driver-api")]
impl<'ast> LitPat<'ast> {
pub fn new(data: CommonPatData<'ast>, lit: LitExprKind<'ast>) -> Self {
Self { data, lit }
}
}
57 changes: 57 additions & 0 deletions marker_api/src/ast/pat/place_pat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use crate::prelude::ExprKind;

use super::CommonPatData;

/// Patterns are used as assignees in [`AssignExpr`](crate::ast::expr::AssignExpr)
/// nodes. Assign expressions can target place expressions like
/// variables, [`IndexExpr`](crate::ast::expr::IndexExpr)s and
/// [`FieldExpr`](crate::ast::expr::FieldExpr)s. These expressions would
/// be stored as this variant.
///
/// ```
/// # fn some_fn() -> (i32, i32) { (4, 5) }
/// # let mut a = 1;
/// # let mut b = (2, 3);
/// # let mut c = [4, 5];
/// a = 6;
/// // ^ A path expression targeting the local variable `a`
///
/// b.1 = 7;
/// // ^^^ A field expression accessing field 1 on the local variable `b`
///
/// c[0] = 8;
/// // ^^^^ An index expression on local variable `c`
///
/// (a, b.0) = some_fn();
/// // ^ ^^^ Place expressions nested in a tuple pattern
/// ```
///
/// Place expressions can currently only occur as targets in
/// [`AssignExpr`](crate::ast::expr::AssignExpr)s. Patterns from
/// [`LetStmts`](crate::ast::stmt::LetStmt)s and arguments in
/// [`FnItem`](crate::ast::item::FnItem) will never contain place expressions.
/// Static paths identifying [`ConstItem`](crate::ast::item::ConstItem)s or
/// [`EnumItem`](crate::ast::item::EnumItem) variants are expressed with the
/// [`PatKind::Path`](crate::ast::pat::PatKind::Path) variant.
#[repr(C)]
#[derive(Debug)]
pub struct PlacePat<'ast> {
data: CommonPatData<'ast>,
place: ExprKind<'ast>,
}

impl<'ast> PlacePat<'ast> {
/// The expression, which identifies the place.
pub fn place(&self) -> ExprKind<'ast> {
self.place
}
}

super::impl_pat_data!(PlacePat<'ast>, Place);

#[cfg(feature = "driver-api")]
impl<'ast> PlacePat<'ast> {
pub fn new(data: CommonPatData<'ast>, place: ExprKind<'ast>) -> Self {
Self { data, place }
}
}