More advanced class semantics

This commit is contained in:
2026-06-16 15:54:21 +02:00
parent ecfff0ac0d
commit d434ec78e7
2 changed files with 152 additions and 28 deletions
+141 -23
View File
@@ -1,6 +1,6 @@
use crate::ast::{ use crate::ast::{
Block, ClassItem, Expression, FunctionDecl, Identifier, Postfix, Spanned, TopLevel, Block, ClassItem, Expression, FunctionDecl, Identifier, MatchItem, Postfix, Prefix, Spanned,
TopLevelKind, Statement, StatementBranch, TopLevel, TopLevelKind, VarDeclStmt,
}; };
pub trait GetMutability { pub trait GetMutability {
@@ -112,30 +112,125 @@ impl GetMutability for Block {
} }
} }
impl GetMutability for Statement {
fn get_mutability(&self) -> Vec<Identifier> {
match self {
Statement::Block(body) | Statement::UnsafeBlock(body) => body.get_mutability(),
Statement::If {
initial,
else_if,
else_branch,
} => {
let mut all_sets: Vec<Vec<Identifier>> = Vec::new();
all_sets.push(initial.body.get_mutability());
for branch in else_if {
all_sets.push(branch.body.get_mutability());
}
if let Some(else_block) = else_branch {
all_sets.push(else_block.get_mutability());
} else {
return Vec::new();
}
let mut result = all_sets.remove(0);
for set in all_sets {
result.retain(|id| set.contains(id));
}
result
}
Statement::Loop(body) => body.get_mutability(),
Statement::While(branch) => branch.body.get_mutability(),
Statement::CStyleFor {
body, init, condition, update, ..
} => {
let mut a = init.get_mutability();
a.append(&mut condition.get_mutability());
a.append(&mut update.get_mutability());
a.append(&mut body.get_mutability());
a
}
Statement::For { body, iterator, .. } => {
let mut a = iterator.get_mutability();
a.append(&mut body.get_mutability());
a
}
Statement::Match(_, items) => {
if items.is_empty() {
return Vec::new();
}
let mut all_sets: Vec<Vec<Identifier>> =
items.iter().map(|item| item.item.get_mutability()).collect();
let mut result = all_sets.remove(0);
for set in all_sets {
result.retain(|id| set.contains(id));
}
result
}
Statement::VarDecl(stmt) => stmt
.init
.as_ref()
.map(|e| e.get_mutability())
.unwrap_or_default(),
Statement::Return(expr) => expr
.as_ref()
.map(|e| e.get_mutability())
.unwrap_or_default(),
Statement::Break | Statement::Continue => Vec::new(),
}
}
}
impl GetMutability for StatementBranch {
fn get_mutability(&self) -> Vec<Identifier> {
let mut a = self.condition.get_mutability();
a.append(&mut self.body.get_mutability());
a
}
}
impl GetMutability for MatchItem {
fn get_mutability(&self) -> Vec<Identifier> {
self.1.get_mutability()
}
}
impl GetMutability for VarDeclStmt {
fn get_mutability(&self) -> Vec<Identifier> {
self.init
.as_ref()
.map(|e| e.get_mutability())
.unwrap_or_default()
}
}
fn get_self_ref(initial: &Expression, postfixes: &[Postfix]) -> Option<Identifier> {
match initial {
Expression::Path(v) => {
if v.0.first()?.ident.0 == "self" {
if let Some(Postfix::FieldAccess(field, _)) = postfixes.first() {
if !matches!(postfixes.get(1), Some(Postfix::Call(_))) {
return Some(field.clone());
}
}
}
}
_ => {}
}
None
}
impl Expression { impl Expression {
fn get_self_ref(&self) -> Option<Identifier> { fn get_self_ref(&self) -> Option<Identifier> {
match self { match self {
Self::Fix { Self::Fix {
initial, postfixes, .. initial, postfixes, ..
} => match &**initial { } => get_self_ref(initial, postfixes),
Self::Path(v) => { _ => None,
if v.0[0].ident.0 == "self" {
if let Some(field) = postfixes.get(0) {
match field {
Postfix::FieldAccess(field, _) => return Some(field.clone()),
_ => {}
} }
} }
} }
}
_ => {}
},
_ => {}
}
None
}
}
impl GetMutability for Expression { impl GetMutability for Expression {
fn get_mutability(&self) -> Vec<Identifier> { fn get_mutability(&self) -> Vec<Identifier> {
@@ -162,14 +257,37 @@ impl GetMutability for Expression {
a a
} }
} }
_ => Vec::new(), Self::Statement(stmt) => stmt.get_mutability(),
Self::Fix {
initial,
prefixes,
postfixes,
} => {
let mut result = Vec::new();
if prefixes.iter().any(|p| matches!(p, Prefix::RefMut)) {
if let Some(self_ref) = get_self_ref(initial, postfixes) {
result.push(self_ref);
}
}
for postfix in postfixes {
if let Postfix::Assign(_, rhs) = postfix {
if let Some(self_ref) = get_self_ref(initial, postfixes) {
result.push(self_ref);
}
result.append(&mut rhs.get_mutability());
}
}
result
}
Self::Closure { body, .. } => body.get_mutability(),
Self::Literal(_) | Self::Path(_) => Vec::new(),
} }
} }
} }
pub fn mutates_lhs(op: &str) -> bool { pub fn mutates_lhs(op: &str) -> bool {
matches!( matches!(op, "=" | "->" | "+=" | "-=" | "*=" | "/=")
op,
"=" | "+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "^=" | "<<=" | ">>=" | "->"
)
} }
+11 -5
View File
@@ -1,11 +1,17 @@
pub module class_test; pub module class_test;
pub class Animal<T> { pub class Animal {
pub name String; pub name String;
pub val T; pub val i32;
constructor() { constructor() {
self.name = "Rex".to_string(); self.name = "Rex".to_string();
self.init_v();
}
pub fn void init_v(*mut self) {
self.val = 0;
} }
pub fn String speak(*self) { pub fn String speak(*self) {
@@ -19,7 +25,7 @@ pub class Animal<T> {
pub fn void static_method() {} pub fn void static_method() {}
} }
pub class Mammal<T> : Animal<T> { pub class Mammal : Animal {
constructor() { constructor() {
super = Super::new(); super = Super::new();
} }
@@ -30,12 +36,12 @@ pub class Mammal<T> : Animal<T> {
} }
} }
pub class Dog : Mammal<i32> { pub class Dog : Mammal {
constructor() { constructor() {
super = Super::new(); super = Super::new();
} }
pub override(Animal<i32>) fn String speak(*self) { pub override(Animal) fn String speak(*self) {
"Woof!".to_string() "Woof!".to_string()
} }