Fix using self within self

This commit is contained in:
Sofia 2025-07-28 00:41:35 +03:00
parent dc360ef196
commit 1f56fa5dc3
8 changed files with 126 additions and 33 deletions

View File

@ -1,5 +1,6 @@
import std::print; import std::print;
import std::from_str; import std::from_str;
import std::String;
struct Otus { struct Otus {
field: u32, field: u32,

View File

@ -1,22 +1,19 @@
import std::print; import std::print;
import std::from_str; import std::from_str;
import std::add_char;
import std::set_char; import std::set_char;
import std::free_string; import std::free_string;
import std::add_num_to_str;
import std::concat_strings;
import std::String; import std::String;
fn main() { fn main() {
let mut test = String::new(); let mut test = String::from("hello");
concat_strings(&mut test, from_str(" world")); test.push(String::from(" world"));
add_char(&mut test, '!'); test.add_char('!');
add_char(&mut test, '\n'); test.add_char('\n');
add_num_to_str(&mut test, 175); test.push_num(175);
print(test); print(test);

View File

@ -20,6 +20,61 @@ impl String {
must_be_freed: true, must_be_freed: true,
} }
} }
pub fn from(str: *char) -> String {
let length = str_length(str) as u64;
let mut new = String::new();
let static = String {
inner: str,
length: length - 1,
max_length: length,
must_be_freed: false,
};
concat_strings(&mut new, static);
return new;
}
pub fn push(&mut self, other: String) {
for i in 0 .. (str_length(other.inner) - 1) {
add_char(self, other.inner[i]);
}
}
pub fn add_char(&mut self, c: char) {
if ((*self).length + 1) >= (*self).max_length {
let new = allocate((*self).max_length + 4) as *char;
copy_bits((*self).inner, new, (*self).max_length);
if (*self).must_be_freed == true {
free((*self).inner as *u8);
}
(*self).max_length = (*self).max_length + 4;
(*self).inner = new;
(*self).must_be_freed = true;
}
(*self).inner[(*self).length] = c;
(((*self).inner) as *u8)[(*self).length + 1] = 0;
(*self).length = (*self).length + 1;
}
pub fn push_num(&mut self, num: u64) {
if num >= 10 {
self.push_num(num / 10)
}
let rem = num % 10;
if rem == 0 { self.add_char('0'); }
else if rem == 1 { self.add_char('1'); }
else if rem == 2 { self.add_char('2'); }
else if rem == 3 { self.add_char('3'); }
else if rem == 4 { self.add_char('4'); }
else if rem == 5 { self.add_char('5'); }
else if rem == 6 { self.add_char('6'); }
else if rem == 7 { self.add_char('7'); }
else if rem == 8 { self.add_char('8'); }
else if rem == 9 { self.add_char('9'); }
}
} }
impl binop (lhs: String) + (rhs: *char) -> String { impl binop (lhs: String) + (rhs: *char) -> String {

View File

@ -691,12 +691,23 @@ impl Parse for FunctionSignature {
let self_kind = stream.parse::<SelfParam>().map(|s| s.0).unwrap_or(SelfKind::None); let self_kind = stream.parse::<SelfParam>().map(|s| s.0).unwrap_or(SelfKind::None);
if let Ok(param) = stream.parse::<FunctionParam>() { match &self_kind {
params.push((param.0, param.1)); SelfKind::None => {
while let Some(Token::Comma) = stream.peek() { if let Ok(param) = stream.parse::<FunctionParam>() {
stream.next(); params.push((param.0, param.1));
let param = stream.parse::<FunctionParam>()?; while let Some(Token::Comma) = stream.peek() {
params.push((param.0, param.1)); stream.next();
let param = stream.parse::<FunctionParam>()?;
params.push((param.0, param.1));
}
}
}
_ => {
while let Some(Token::Comma) = stream.peek() {
stream.next();
let param = stream.parse::<FunctionParam>()?;
params.push((param.0, param.1));
}
} }
} }

View File

@ -208,6 +208,19 @@ impl TypeKind {
None None
} }
} }
pub fn unroll_borrows(&self) -> TypeKind {
match self {
TypeKind::Borrow(type_kind, mut1) => match *type_kind.clone() {
TypeKind::Borrow(type_kind, mut2) => match (mut1, mut2) {
(false, false) => TypeKind::Borrow(Box::new(*type_kind.clone()), false),
_ => TypeKind::Borrow(Box::new(*type_kind.clone()), true),
},
_ => self.clone(),
},
_ => self.clone(),
}
}
} }
impl BinaryOperator { impl BinaryOperator {

View File

@ -248,7 +248,7 @@ pub struct NamedVariableRef(pub TypeKind, pub String, pub Metadata);
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Import(pub Vec<String>, pub Metadata); pub struct Import(pub Vec<String>, pub Metadata);
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum ExprKind { pub enum ExprKind {
Variable(NamedVariableRef), Variable(NamedVariableRef),
Indexed(Box<Expression>, TypeKind, Box<Expression>), Indexed(Box<Expression>, TypeKind, Box<Expression>),
@ -266,14 +266,14 @@ pub enum ExprKind {
CastTo(Box<Expression>, TypeKind), CastTo(Box<Expression>, TypeKind),
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct Expression(pub ExprKind, pub Metadata); pub struct Expression(pub ExprKind, pub Metadata);
/// Condition, Then, Else /// Condition, Then, Else
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct IfExpression(pub Box<Expression>, pub Box<Expression>, pub Box<Option<Expression>>); pub struct IfExpression(pub Box<Expression>, pub Box<Expression>, pub Box<Option<Expression>>);
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct FunctionCall { pub struct FunctionCall {
pub name: String, pub name: String,
pub return_type: TypeKind, pub return_type: TypeKind,
@ -328,7 +328,7 @@ impl FunctionDefinition {
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct Block { pub struct Block {
/// List of non-returning statements /// List of non-returning statements
pub statements: Vec<Statement>, pub statements: Vec<Statement>,
@ -336,10 +336,10 @@ pub struct Block {
pub meta: Metadata, pub meta: Metadata,
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct Statement(pub StmtKind, pub Metadata); pub struct Statement(pub StmtKind, pub Metadata);
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum StmtKind { pub enum StmtKind {
/// Variable name++mutability+type, evaluation /// Variable name++mutability+type, evaluation
Let(NamedVariableRef, bool, Expression), Let(NamedVariableRef, bool, Expression),
@ -349,7 +349,7 @@ pub enum StmtKind {
While(WhileStatement), While(WhileStatement),
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct WhileStatement { pub struct WhileStatement {
pub condition: Expression, pub condition: Expression,
pub block: Block, pub block: Block,

View File

@ -749,7 +749,9 @@ impl Expression {
.into_iter() .into_iter()
.chain(iter::repeat(TypeKind::Vague(Vague::Unknown))); .chain(iter::repeat(TypeKind::Vague(Vague::Unknown)));
for (param, true_param_t) in function_call.parameters.iter_mut().zip(true_params_iter) { for (i, (param, true_param_t)) in
function_call.parameters.iter_mut().zip(true_params_iter).enumerate()
{
// Typecheck every param separately // Typecheck every param separately
let param_res = param.typecheck(state, &typerefs, HintKind::Coerce(true_param_t.clone())); let param_res = param.typecheck(state, &typerefs, HintKind::Coerce(true_param_t.clone()));
let param_t = state.or_else(param_res, TypeKind::Vague(Vague::Unknown), param.1); let param_t = state.or_else(param_res, TypeKind::Vague(Vague::Unknown), param.1);

View File

@ -603,17 +603,31 @@ impl Expression {
.get_mut(0) .get_mut(0)
.expect("Unknown-type associated function NEEDS to always have at least one parameter!"); .expect("Unknown-type associated function NEEDS to always have at least one parameter!");
let param_ty = first_param.infer_types(state, type_refs).unwrap().resolve_deep(); let param_ty = first_param.infer_types(state, type_refs).unwrap().resolve_deep();
*type_kind = state.or_else( *type_kind = state
param_ty.ok_or(ErrorKind::CouldNotInferType(format!("{}", first_param))), .or_else(
Void, param_ty.ok_or(ErrorKind::CouldNotInferType(format!("{}", first_param))),
first_param.1, Void,
); first_param.1,
)
.unroll_borrows()
.resolve_ref(type_refs.types);
let backing_var = first_param.backing_var().expect("todo").1.clone(); let backing_var = first_param.backing_var().expect("todo").1.clone();
dbg!(&backing_var);
dbg!(&state.scope.variables.get(&backing_var)); *first_param = if backing_var == "self" {
let mutable = state.scope.variables.get(&backing_var).expect("todo").mutable; let ExprKind::Borrow(val, _) = &first_param.0 else {
if !mutable { panic!()
first_param.remove_borrow_mutability(); };
*val.clone()
} else {
first_param.clone()
};
if let Some((mutable, _)) = type_refs.find_var(&backing_var) {
if !mutable {
first_param.remove_borrow_mutability();
}
} else {
return Err(ErrorKind::VariableNotDefined(backing_var));
} }
} }
} }