Merge pull request #88 from mist-go/separate-self-param

Separate self param
This commit is contained in:
2026-06-25 20:08:38 +02:00
committed by GitHub
7 changed files with 82 additions and 85 deletions
+29 -29
View File
@@ -51,7 +51,7 @@ impl ClassProcessedData {
if matches!(method.item.visibility, Visibility::Public) { if matches!(method.item.visibility, Visibility::Public) {
match &method.item.is_override { match &method.item.is_override {
None => { None => {
if method.item.is_using_self() { if method.item.self_param.is_some() {
v_table.push(method.item.name.clone()); v_table.push(method.item.name.clone());
} }
} }
@@ -263,7 +263,7 @@ impl ClassProcessedData {
continue; continue;
} }
if let TypeExpr::Ref { mutable, .. } = params.remove(0) { if let Some((_, _, mutable)) = &method.item.self_param {
method.gen_span(cg); method.gen_span(cg);
cg.add_indented(&format!("{}::__m_", target_rust_path)); cg.add_indented(&format!("{}::__m_", target_rust_path));
cg.add(&method.item.name.get_rust()); cg.add(&method.item.name.get_rust());
@@ -273,7 +273,7 @@ impl ClassProcessedData {
0, 0,
TypeExpr::Ref { TypeExpr::Ref {
lifetime: None, lifetime: None,
mutable, mutable: *mutable,
ty: Box::new(get_type_from_path(&target_path)), ty: Box::new(get_type_from_path(&target_path)),
}, },
); );
@@ -375,20 +375,6 @@ impl ClassProcessedData {
cg.indent -= 1; cg.indent -= 1;
cg.add_indentedln("}\n"); cg.add_indentedln("}\n");
let mut constructor_params = vec![VarDecl {
name: Pattern::Path(false, Path(vec![Identifier(String::from("self"))])),
type_: Some(TypeExpr::Ref {
lifetime: None,
mutable: true,
ty: Box::new(TypeExpr::Path(
Path(vec![Identifier(String::from("Self"))]),
None,
)),
}),
}];
constructor_params.append(&mut constructor.item.params.0.clone());
Spanned { Spanned {
line: constructor.line, line: constructor.line,
column: constructor.column, column: constructor.column,
@@ -397,7 +383,8 @@ impl ClassProcessedData {
is_override: None, is_override: None,
name: Identifier(String::from("constructor")), name: Identifier(String::from("constructor")),
generics: constructor.item.generics.clone(), generics: constructor.item.generics.clone(),
params: ParamList(constructor_params), params: constructor.item.params.clone(),
self_param: Some((true, None, true)),
return_type: Some(TypeExpr::Tuple(Vec::new())), return_type: Some(TypeExpr::Tuple(Vec::new())),
body: Some(constructor.item.body.clone()), body: Some(constructor.item.body.clone()),
}, },
@@ -409,7 +396,7 @@ impl ClassProcessedData {
for method in &self.methods { for method in &self.methods {
match method.item.visibility { match method.item.visibility {
Visibility::Public => { Visibility::Public => {
if method.item.is_using_self() { if method.item.self_param.is_some() {
if method.item.is_override.is_none() { if method.item.is_override.is_none() {
gen_method_point(&method.item, ctx, cg); gen_method_point(&method.item, ctx, cg);
} }
@@ -513,6 +500,7 @@ fn construct_pattern(pat: &Pattern, idx: usize) -> Pattern {
} }
pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustCodegen) { pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustCodegen) {
let mutable_self = if let Some((is_ref, lifetime, is_mut)) = &method.self_param {
cg.add_indented(&format!( cg.add_indented(&format!(
"{}fn {}{}(", "{}fn {}{}(",
method.visibility.get_rust(), method.visibility.get_rust(),
@@ -520,6 +508,25 @@ pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustC
method.generics.get_rust(), method.generics.get_rust(),
)); ));
if *is_ref {
cg.add("&");
}
if let Some(lifetime) = lifetime {
cg.add(&format!("'{} ", lifetime.0));
}
if *is_mut {
cg.add("mut ");
}
cg.add("self,");
*is_mut
} else {
panic!();
};
let params = method let params = method
.params .params
.0 .0
@@ -566,14 +573,10 @@ pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustC
.filter_map(|v| v.type_) .filter_map(|v| v.type_)
.collect(); .collect();
let TypeExpr::Ref { mutable, .. } = param_types.remove(0) else {
panic!("")
};
param_types.insert( param_types.insert(
0, 0,
TypeExpr::UnsafePtr { TypeExpr::UnsafePtr {
mutable, mutable: mutable_self,
ty: Box::new(TypeExpr::Path( ty: Box::new(TypeExpr::Path(
Path(vec![ Path(vec![
Identifier(String::from("std")), Identifier(String::from("std")),
@@ -588,16 +591,13 @@ pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustC
cg.add(&TypeExpr::StaticFn(param_types, method.return_type.clone().map(Box::new)).get_rust()); cg.add(&TypeExpr::StaticFn(param_types, method.return_type.clone().map(Box::new)).get_rust());
cg.addln(" = std::mem::transmute(func_ptr);"); cg.addln(" = std::mem::transmute(func_ptr);");
if mutable { if mutable_self {
cg.add_indented("func(self as *mut Self as *const std::ffi::c_void"); cg.add_indented("func(self as *mut Self as *const std::ffi::c_void");
} else { } else {
cg.add_indented("func(self as *const Self as *const std::ffi::c_void"); cg.add_indented("func(self as *const Self as *const std::ffi::c_void");
} }
for (i, param) in &params { for (_, param) in &params {
if *i == 0 {
continue; // self already fulfills it
}
cg.add(", "); cg.add(", ");
ctx.expr_ensure_semicolon = false; ctx.expr_ensure_semicolon = false;
param.name.gen_rust(ctx, cg); param.name.gen_rust(ctx, cg);
+16
View File
@@ -80,6 +80,22 @@ impl GenRust for FunctionDecl {
self.generics.get_rust(), self.generics.get_rust(),
)); ));
if let Some((is_ref, lifetime, is_mut)) = &self.self_param {
if *is_ref {
cg.add("&");
}
if let Some(lifetime) = lifetime {
cg.add(&format!("'{} ", lifetime.0));
}
if *is_mut {
cg.add("mut ");
}
cg.add("self,");
}
for (i, param) in self.params.0.iter().enumerate() { for (i, param) in self.params.0.iter().enumerate() {
if i > 0 { if i > 0 {
cg.add(", "); cg.add(", ");
+1 -15
View File
@@ -100,6 +100,7 @@ pub struct FunctionDecl {
pub is_override: Option<Override>, pub is_override: Option<Override>,
pub name: Identifier, pub name: Identifier,
pub generics: GenericsDecl, pub generics: GenericsDecl,
pub self_param: Option<(bool, Option<Identifier>, bool)>,
pub params: ParamList, pub params: ParamList,
pub return_type: Option<TypeExpr>, pub return_type: Option<TypeExpr>,
pub body: Option<Block>, pub body: Option<Block>,
@@ -125,18 +126,3 @@ pub struct FieldDeclStmt {
pub decl: FieldDecl, pub decl: FieldDecl,
pub init: Option<Expression>, pub init: Option<Expression>,
} }
impl FunctionDecl {
pub fn is_using_self(&self) -> bool {
match self.params.0.get(0) {
Some(VarDecl { name, .. }) => {
if let Pattern::Path(_, v) = name {
v.0.len() == 1 && v.0[0].0 == "self"
} else {
false
}
}
_ => false,
}
}
}
+9 -32
View File
@@ -3,7 +3,7 @@ use crate::{
ast::*, ast::*,
ast_ensure, ast_ensure,
error::{self, AstError, AstResult}, error::{self, AstError, AstResult},
parser::{consume_rule, listen_rule}, parser::{consume_rule, consume_rule_map, listen_rule},
}; };
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for FunctionDecl { impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for FunctionDecl {
@@ -25,43 +25,19 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for FunctionDecl {
.transpose() .transpose()
.map(|v| v.unwrap_or_default())?; .map(|v| v.unwrap_or_default())?;
let self_param = consume_rule(&mut inner, Rule::self_param).map(|param| { let self_param = consume_rule_map(&mut inner, Rule::self_param, |param| {
let mut param_inner = param.into_inner(); let mut param_inner = param.into_inner();
let is_ref = listen_rule(&mut param_inner, Rule::ref_px); let is_ref = listen_rule(&mut param_inner, Rule::ref_px);
let lifetime = consume_rule(&mut param_inner, Rule::lifetime); let lifetime = consume_rule(&mut param_inner, Rule::lifetime);
let mutable = listen_rule(&mut param_inner, Rule::mutable); let mutable = listen_rule(&mut param_inner, Rule::mutable);
let name = Pattern::Path(mutable && !is_ref, Path(vec![Identifier(String::from("self"))]));
let self_ty = TypeExpr::Path(Path(vec![Identifier(String::from("Self"))]), None);
VarDecl { Ok((is_ref, lifetime.map(|v| -> AstResult<Identifier> {
name: name.clone(), Identifier::try_from(v.into_inner().next().unwrap())
type_: Some(if is_ref { }).transpose()?, mutable))
TypeExpr::Ref { })?;
lifetime:
lifetime.map(|v| Lifetime::try_from(v.into_inner().next().unwrap()))
.transpose()
.expect("Failed to get lifetime identifier"),
mutable,
ty: Box::new(self_ty)
}
} else {
self_ty
}),
}
});
let params = consume_rule(&mut inner, Rule::param_list) let params = consume_rule(&mut inner, Rule::param_list).map(ParamList::try_from).transpose()?.unwrap_or_default();
.map({
let self_param = self_param.clone();
|params_pair| -> AstResult<'a, ParamList> {
let mut params = ParamList::try_from(params_pair)?;
if let Some(x) = self_param {
params.0.insert(0, x);
}
Ok(params)
}
})
.unwrap_or_else(|| Ok(ParamList(self_param.into_iter().collect())))?;
let is_override = consume_rule(&mut inner, Rule::override_kw).map(Override::try_from).transpose()?; let is_override = consume_rule(&mut inner, Rule::override_kw).map(Override::try_from).transpose()?;
@@ -73,6 +49,7 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for FunctionDecl {
return_type: return_type, return_type: return_type,
name: name, name: name,
generics: generics, generics: generics,
self_param: self_param,
params: params, params: params,
body: body, body: body,
}) })
+19 -1
View File
@@ -1,7 +1,11 @@
pub mod common; pub mod common;
pub mod items; pub mod items;
use crate::{Rule, ast::Spanned, error::AstError}; use crate::{
Rule,
ast::Spanned,
error::{AstError, AstResult},
};
pub fn listen_rule(pairs: &mut pest::iterators::Pairs<'_, Rule>, rule: Rule) -> bool { pub fn listen_rule(pairs: &mut pest::iterators::Pairs<'_, Rule>, rule: Rule) -> bool {
let consumed = pairs let consumed = pairs
@@ -28,6 +32,20 @@ pub fn consume_rule<'a>(
if consumed { pairs.next() } else { None } if consumed { pairs.next() } else { None }
} }
pub fn consume_rule_map<'a, T>(
pairs: &mut pest::iterators::Pairs<'a, Rule>,
rule: Rule,
map: impl Fn(pest::iterators::Pair<'a, Rule>) -> AstResult<'a, T>,
) -> AstResult<'a, Option<T>> {
let pair = consume_rule(pairs, rule);
if let Some(pair) = pair {
Some(map(pair)).transpose()
} else {
Ok(None)
}
}
impl<T> Spanned<T> { impl<T> Spanned<T> {
fn new_pair(pair: pest::iterators::Pair<'_, Rule>, item: T) -> Self { fn new_pair(pair: pest::iterators::Pair<'_, Rule>, item: T) -> Self {
let span = pair.as_span().start_pos().line_col(); let span = pair.as_span().start_pos().line_col();
+1 -1
View File
@@ -22,7 +22,7 @@ pub fn find_function_call<'a>(
) -> Option<&'a Spanned<FunctionDecl>> { ) -> Option<&'a Spanned<FunctionDecl>> {
items.iter().find_map(|v| { items.iter().find_map(|v| {
if let ClassItem::Method(m) = v { if let ClassItem::Method(m) = v {
if m.item.is_using_self() && &m.item.name == name { if m.item.self_param.is_some() && &m.item.name == name {
Some(m) Some(m)
} else { } else {
None None
+1 -1
View File
@@ -11,7 +11,7 @@ pub class Animal {
"Unknown".to_string() "Unknown".to_string()
} }
pub void test_speak(&self) { pub void test_speak<'a>(&'a self) {
assert_eq!(self.speak(), "Woof!"); assert_eq!(self.speak(), "Woof!");
} }