Skip to content

Commit

Permalink
Allow storing of heap types in stack types
Browse files Browse the repository at this point in the history
Commit 8ca46bf introduces the ability to define stack allocated value
types. This commit extends support to also allow defining of stack
allocated types containing heap types. This means there are now three
different kinds of allocation strategies:

- class A: heap allocated, subject to single ownership
- class inline A: stack allocated, subject to single ownership
- class copy A: stack allocated, immutable value type that's copied upon
  a move

When borrowing an `inline` type, the compiler copies the stack allocated
portion and increments the borrow count for any heap values stored
within. When dropping this copy, the borrow count is reduces. This means
that borrowing an `inline` type is equivalent to borrowing all interior
heap values, just without the need for doing so manually. This approach
is inspired by Swift, which takes a similar approach using (atomic)
reference counting.

Changelog: added
  • Loading branch information
yorickpeterse committed Dec 9, 2024
1 parent 26070da commit 3878e72
Show file tree
Hide file tree
Showing 65 changed files with 1,408 additions and 703 deletions.
12 changes: 9 additions & 3 deletions ast/src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ pub enum TokenKind {
Comma,
Comment,
Constant,
Copy,
CurlyClose,
CurlyOpen,
Div,
Expand All @@ -103,6 +104,7 @@ pub enum TokenKind {
Else,
Enum,
Eq,
Extern,
False,
Field,
Float,
Expand All @@ -114,6 +116,7 @@ pub enum TokenKind {
If,
Implement,
Import,
Inline,
Integer,
Invalid,
InvalidStringEscape,
Expand Down Expand Up @@ -150,6 +153,7 @@ pub enum TokenKind {
SingleStringClose,
SingleStringOpen,
Static,
StringEscape,
StringExprClose,
StringExprOpen,
StringText,
Expand All @@ -160,13 +164,10 @@ pub enum TokenKind {
True,
Try,
Uni,
StringEscape,
UnsignedShr,
UnsignedShrAssign,
While,
Whitespace,
Extern,
Inline,
}

impl TokenKind {
Expand Down Expand Up @@ -270,6 +271,7 @@ impl TokenKind {
TokenKind::Replace => "a '=:'",
TokenKind::Extern => "the 'extern' keyword",
TokenKind::Inline => "the 'inline' keyword",
TokenKind::Copy => "the 'copy' keyword",
}
}
}
Expand Down Expand Up @@ -338,6 +340,7 @@ impl Token {
| TokenKind::Enum
| TokenKind::Extern
| TokenKind::Inline
| TokenKind::Copy
)
}

Expand Down Expand Up @@ -985,6 +988,7 @@ impl Lexer {
"true" => TokenKind::True,
"case" => TokenKind::Case,
"enum" => TokenKind::Enum,
"copy" => TokenKind::Copy,
_ => TokenKind::Identifier,
},
5 => match value.as_str() {
Expand Down Expand Up @@ -1354,6 +1358,7 @@ mod tests {
assert!(tok(TokenKind::Recover, "", 1..=1, 1..=1).is_keyword());
assert!(tok(TokenKind::Nil, "", 1..=1, 1..=1).is_keyword());
assert!(tok(TokenKind::Inline, "", 1..=1, 1..=1).is_keyword());
assert!(tok(TokenKind::Copy, "", 1..=1, 1..=1).is_keyword());
}

#[test]
Expand Down Expand Up @@ -1981,6 +1986,7 @@ mod tests {
assert_token!("true", True, "true", 1..=1, 1..=4);
assert_token!("case", Case, "case", 1..=1, 1..=4);
assert_token!("enum", Enum, "enum", 1..=1, 1..=4);
assert_token!("copy", Copy, "copy", 1..=1, 1..=4);

assert_token!("class", Class, "class", 1..=1, 1..=5);
assert_token!("async", Async, "async", 1..=1, 1..=5);
Expand Down
13 changes: 10 additions & 3 deletions ast/src/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,13 @@ impl Node for ClassExpressions {
}
}

#[derive(Debug, PartialEq, Eq)]
pub enum ClassSemantics {
Default,
Inline,
Copy,
}

#[derive(Debug, PartialEq, Eq)]
pub enum ClassKind {
Async,
Expand All @@ -491,8 +498,8 @@ pub enum ClassKind {

#[derive(Debug, PartialEq, Eq)]
pub struct DefineClass {
pub semantics: ClassSemantics,
pub public: bool,
pub inline: bool,
pub kind: ClassKind,
pub name: Constant,
pub type_parameters: Option<TypeParameters>,
Expand Down Expand Up @@ -638,15 +645,15 @@ impl Node for ReopenClass {
pub enum Requirement {
Trait(TypeName),
Mutable(Location),
Inline(Location),
Copy(Location),
}

impl Node for Requirement {
fn location(&self) -> &Location {
match self {
Requirement::Trait(n) => &n.location,
Requirement::Mutable(loc) => loc,
Requirement::Inline(loc) => loc,
Requirement::Copy(loc) => loc,
}
}
}
Expand Down
Loading

0 comments on commit 3878e72

Please sign in to comment.