More advanced class semantics
This commit is contained in:
+141
-23
@@ -1,6 +1,6 @@
|
||||
use crate::ast::{
|
||||
Block, ClassItem, Expression, FunctionDecl, Identifier, Postfix, Spanned, TopLevel,
|
||||
TopLevelKind,
|
||||
Block, ClassItem, Expression, FunctionDecl, Identifier, MatchItem, Postfix, Prefix, Spanned,
|
||||
Statement, StatementBranch, TopLevel, TopLevelKind, VarDeclStmt,
|
||||
};
|
||||
|
||||
pub trait GetMutability {
|
||||
@@ -112,28 +112,123 @@ 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 {
|
||||
fn get_self_ref(&self) -> Option<Identifier> {
|
||||
match self {
|
||||
Self::Fix {
|
||||
initial, postfixes, ..
|
||||
} => match &**initial {
|
||||
Self::Path(v) => {
|
||||
if v.0[0].ident.0 == "self" {
|
||||
if let Some(field) = postfixes.get(0) {
|
||||
match field {
|
||||
Postfix::FieldAccess(field, _) => return Some(field.clone()),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
} => get_self_ref(initial, postfixes),
|
||||
_ => None,
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,14 +257,37 @@ impl GetMutability for Expression {
|
||||
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 {
|
||||
matches!(
|
||||
op,
|
||||
"=" | "+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "^=" | "<<=" | ">>=" | "->"
|
||||
)
|
||||
matches!(op, "=" | "->" | "+=" | "-=" | "*=" | "/=")
|
||||
}
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
pub module class_test;
|
||||
|
||||
pub class Animal<T> {
|
||||
pub class Animal {
|
||||
pub name String;
|
||||
pub val T;
|
||||
pub val i32;
|
||||
|
||||
constructor() {
|
||||
self.name = "Rex".to_string();
|
||||
|
||||
self.init_v();
|
||||
}
|
||||
|
||||
pub fn void init_v(*mut self) {
|
||||
self.val = 0;
|
||||
}
|
||||
|
||||
pub fn String speak(*self) {
|
||||
@@ -19,7 +25,7 @@ pub class Animal<T> {
|
||||
pub fn void static_method() {}
|
||||
}
|
||||
|
||||
pub class Mammal<T> : Animal<T> {
|
||||
pub class Mammal : Animal {
|
||||
constructor() {
|
||||
super = Super::new();
|
||||
}
|
||||
@@ -30,12 +36,12 @@ pub class Mammal<T> : Animal<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub class Dog : Mammal<i32> {
|
||||
pub class Dog : Mammal {
|
||||
constructor() {
|
||||
super = Super::new();
|
||||
}
|
||||
|
||||
pub override(Animal<i32>) fn String speak(*self) {
|
||||
pub override(Animal) fn String speak(*self) {
|
||||
"Woof!".to_string()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user