More advanced class semantics
This commit is contained in:
+141
-23
@@ -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,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 {
|
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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,
|
|
||||||
"=" | "+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "^=" | "<<=" | ">>=" | "->"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user