diff --git a/examples/associated_functions_shorthand.reid b/examples/associated_functions_shorthand.reid index db78842..a3b402d 100644 --- a/examples/associated_functions_shorthand.reid +++ b/examples/associated_functions_shorthand.reid @@ -1,5 +1,6 @@ import std::print; import std::from_str; +import std::String; struct Otus { field: u32, diff --git a/examples/hello_world_harder.reid b/examples/hello_world_harder.reid index 5913486..f3452e2 100644 --- a/examples/hello_world_harder.reid +++ b/examples/hello_world_harder.reid @@ -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); diff --git a/reid/lib/std.reid b/reid/lib/std.reid index add5733..1abdebf 100644 --- a/reid/lib/std.reid +++ b/reid/lib/std.reid @@ -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 { diff --git a/reid/src/ast/parse.rs b/reid/src/ast/parse.rs index b78685e..de92825 100644 --- a/reid/src/ast/parse.rs +++ b/reid/src/ast/parse.rs @@ -691,12 +691,23 @@ impl Parse for FunctionSignature { let self_kind = stream.parse::().map(|s| s.0).unwrap_or(SelfKind::None); - if let Ok(param) = stream.parse::() { - params.push((param.0, param.1)); - while let Some(Token::Comma) = stream.peek() { - stream.next(); - let param = stream.parse::()?; - params.push((param.0, param.1)); + match &self_kind { + SelfKind::None => { + if let Ok(param) = stream.parse::() { + params.push((param.0, param.1)); + while let Some(Token::Comma) = stream.peek() { + stream.next(); + let param = stream.parse::()?; + params.push((param.0, param.1)); + } + } + } + _ => { + while let Some(Token::Comma) = stream.peek() { + stream.next(); + let param = stream.parse::()?; + params.push((param.0, param.1)); + } } } diff --git a/reid/src/mir/implement.rs b/reid/src/mir/implement.rs index 16bef72..619e537 100644 --- a/reid/src/mir/implement.rs +++ b/reid/src/mir/implement.rs @@ -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 { diff --git a/reid/src/mir/mod.rs b/reid/src/mir/mod.rs index d2bc78e..4b3ff62 100644 --- a/reid/src/mir/mod.rs +++ b/reid/src/mir/mod.rs @@ -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, pub Metadata); -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum ExprKind { Variable(NamedVariableRef), Indexed(Box, TypeKind, Box), @@ -266,14 +266,14 @@ pub enum ExprKind { CastTo(Box, 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, pub Box, pub Box>); -#[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, @@ -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, diff --git a/reid/src/mir/typecheck/typecheck.rs b/reid/src/mir/typecheck/typecheck.rs index 1baa1a3..1589cf7 100644 --- a/reid/src/mir/typecheck/typecheck.rs +++ b/reid/src/mir/typecheck/typecheck.rs @@ -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); diff --git a/reid/src/mir/typecheck/typeinference.rs b/reid/src/mir/typecheck/typeinference.rs index 8aee019..bea048c 100644 --- a/reid/src/mir/typecheck/typeinference.rs +++ b/reid/src/mir/typecheck/typeinference.rs @@ -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)); } } }