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::from_str;
import std::String;
struct Otus {
field: u32,

View File

@ -1,22 +1,19 @@
import std::print;
import std::from_str;
import std::add_char;
import std::set_char;
import std::free_string;
import std::add_num_to_str;
import std::concat_strings;
import std::String;
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, '!');
add_char(&mut test, '\n');
test.add_char('!');
test.add_char('\n');
add_num_to_str(&mut test, 175);
test.push_num(175);
print(test);

View File

@ -20,6 +20,61 @@ impl String {
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 {

View File

@ -691,12 +691,23 @@ impl Parse for FunctionSignature {
let self_kind = stream.parse::<SelfParam>().map(|s| s.0).unwrap_or(SelfKind::None);
if let Ok(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));
match &self_kind {
SelfKind::None => {
if let Ok(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));
}
}
}
_ => {
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
}
}
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 {

View File

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

View File

@ -749,7 +749,9 @@ impl Expression {
.into_iter()
.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
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);

View File

@ -603,17 +603,31 @@ impl Expression {
.get_mut(0)
.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();
*type_kind = state.or_else(
param_ty.ok_or(ErrorKind::CouldNotInferType(format!("{}", first_param))),
Void,
first_param.1,
);
*type_kind = state
.or_else(
param_ty.ok_or(ErrorKind::CouldNotInferType(format!("{}", first_param))),
Void,
first_param.1,
)
.unroll_borrows()
.resolve_ref(type_refs.types);
let backing_var = first_param.backing_var().expect("todo").1.clone();
dbg!(&backing_var);
dbg!(&state.scope.variables.get(&backing_var));
let mutable = state.scope.variables.get(&backing_var).expect("todo").mutable;
if !mutable {
first_param.remove_borrow_mutability();
*first_param = if backing_var == "self" {
let ExprKind::Borrow(val, _) = &first_param.0 else {
panic!()
};
*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));
}
}
}