diff --git a/reid/src/ast/mod.rs b/reid/src/ast/mod.rs index 665f286..2811250 100644 --- a/reid/src/ast/mod.rs +++ b/reid/src/ast/mod.rs @@ -27,7 +27,7 @@ pub enum TypeKind { String, Array(Box, u64), Custom(String), - Borrow(Box), + Borrow(Box, bool), } #[derive(Debug, Clone)] @@ -43,7 +43,7 @@ pub struct Expression(pub ExpressionKind, pub TokenRange); #[derive(Debug, Clone)] pub enum ExpressionKind { VariableName(String), - Borrow(String), + Borrow(String, bool), Deref(String), Literal(Literal), Array(Vec), diff --git a/reid/src/ast/parse.rs b/reid/src/ast/parse.rs index be2d6ab..47c1b59 100644 --- a/reid/src/ast/parse.rs +++ b/reid/src/ast/parse.rs @@ -26,8 +26,15 @@ impl Parse for Type { TypeKind::Array(Box::new(inner.0), length) } else if let Some(Token::Et) = stream.peek() { stream.expect(Token::Et)?; + let mutable = if let Some(Token::MutKeyword) = stream.peek() { + stream.next(); + true + } else { + false + }; + let inner = stream.parse::()?; - TypeKind::Borrow(Box::new(inner.0)) + TypeKind::Borrow(Box::new(inner.0), mutable) } else { if let Some(Token::Identifier(ident)) = stream.next() { match &*ident { @@ -87,12 +94,19 @@ impl Parse for PrimaryExpression { Kind::StructExpression(stream.parse()?), stream.get_range().unwrap(), ) + } else if let (Some(Token::Et), Some(Token::MutKeyword)) = (stream.peek(), stream.peek2()) { + stream.next(); // Consume Et + stream.next(); // Consume mut + let Some(Token::Identifier(name)) = stream.next() else { + return Err(stream.expected_err("identifier")?); + }; + Expression(Kind::Borrow(name, true), stream.get_range().unwrap()) } else if let (Some(Token::Et), Some(Token::Identifier(name))) = (stream.peek(), stream.peek2()) { stream.next(); // Consume Et stream.next(); // Consume identifier - Expression(Kind::Borrow(name), stream.get_range().unwrap()) + Expression(Kind::Borrow(name, false), stream.get_range().unwrap()) } else if let (Some(Token::Star), Some(Token::Identifier(name))) = (stream.peek(), stream.peek2()) { diff --git a/reid/src/ast/process.rs b/reid/src/ast/process.rs index 3b872b5..395602a 100644 --- a/reid/src/ast/process.rs +++ b/reid/src/ast/process.rs @@ -225,11 +225,14 @@ impl ast::Expression { mir::TypeKind::Vague(mir::VagueType::Unknown), name.clone(), ), - ast::ExpressionKind::Borrow(name) => mir::ExprKind::Borrow(NamedVariableRef( - mir::TypeKind::Vague(mir::VagueType::Unknown), - name.clone(), - self.1.as_meta(module_id), - )), + ast::ExpressionKind::Borrow(name, mutable) => mir::ExprKind::Borrow( + NamedVariableRef( + mir::TypeKind::Vague(mir::VagueType::Unknown), + name.clone(), + self.1.as_meta(module_id), + ), + *mutable, + ), ast::ExpressionKind::Deref(name) => mir::ExprKind::Deref(NamedVariableRef( mir::TypeKind::Vague(mir::VagueType::Unknown), name.clone(), @@ -287,8 +290,8 @@ impl From for mir::TypeKind { } ast::TypeKind::String => mir::TypeKind::StringPtr, ast::TypeKind::Custom(name) => mir::TypeKind::CustomType(name.clone()), - ast::TypeKind::Borrow(type_kind) => { - mir::TypeKind::Borrow(Box::new(mir::TypeKind::from(*type_kind.clone()))) + ast::TypeKind::Borrow(type_kind, mutable) => { + mir::TypeKind::Borrow(Box::new(mir::TypeKind::from(*type_kind.clone())), *mutable) } } } diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index 6343017..29d0bd1 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -114,6 +114,13 @@ pub enum StackValueKind { } impl StackValueKind { + fn mutable(mutable: bool, instr: InstructionValue) -> StackValueKind { + match mutable { + true => StackValueKind::Mutable(instr), + false => StackValueKind::Immutable(instr), + } + } + fn instr(&self) -> InstructionValue { match &self { StackValueKind::Immutable(val) => *val, @@ -934,13 +941,16 @@ impl mir::Expression { TypeKind::CustomType(name.clone()), )) } - mir::ExprKind::Borrow(varref) => { + mir::ExprKind::Borrow(varref, mutable) => { varref.0.known().expect("variable type unknown"); let v = scope .stack_values .get(&varref.1) .expect("Variable reference not found?!"); - Some(v.clone()) + Some(StackValue( + StackValueKind::mutable(*mutable, v.0.instr()), + v.1.clone(), + )) } mir::ExprKind::Deref(varref) => { varref.0.known().expect("variable type unknown"); @@ -1166,7 +1176,7 @@ impl TypeKind { TypeKind::Ptr(type_kind) => { Type::Ptr(Box::new(type_kind.get_type(type_vals, typedefs))) } - TypeKind::Borrow(type_kind) => { + TypeKind::Borrow(type_kind, _) => { Type::Ptr(Box::new(type_kind.get_type(type_vals, typedefs))) } } @@ -1213,7 +1223,7 @@ impl TypeKind { ), size_bits: self.size_of(), }), - TypeKind::Ptr(inner) | TypeKind::Borrow(inner) => { + TypeKind::Ptr(inner) | TypeKind::Borrow(inner, _) => { DebugTypeData::Pointer(DebugPointerType { name, pointee: inner.get_debug_type_hard( diff --git a/reid/src/mir/fmt.rs b/reid/src/mir/fmt.rs index 0b4e2d7..7a9f2b3 100644 --- a/reid/src/mir/fmt.rs +++ b/reid/src/mir/fmt.rs @@ -208,7 +208,8 @@ impl Display for ExprKind { write_access(f, name)?; write!(f, "<{}>", type_kind) } - ExprKind::Borrow(var_ref) => write!(f, "&{}", var_ref), + ExprKind::Borrow(var_ref, false) => write!(f, "&{}", var_ref), + ExprKind::Borrow(var_ref, true) => write!(f, "&mut {}", var_ref), ExprKind::Deref(var_ref) => write!(f, "*{}", var_ref), } } diff --git a/reid/src/mir/impl.rs b/reid/src/mir/impl.rs index aeae147..8e22a07 100644 --- a/reid/src/mir/impl.rs +++ b/reid/src/mir/impl.rs @@ -46,7 +46,7 @@ impl TypeKind { TypeKind::CustomType(_) => 32, TypeKind::Ptr(_) => 64, TypeKind::Vague(_) => panic!("Tried to sizeof a vague type!"), - TypeKind::Borrow(_) => 64, + TypeKind::Borrow(_, _) => 64, } } @@ -69,7 +69,14 @@ impl TypeKind { TypeKind::CustomType(_) => 32, TypeKind::Ptr(_) => 64, TypeKind::Vague(_) => panic!("Tried to sizeof a vague type!"), - TypeKind::Borrow(_) => 64, + TypeKind::Borrow(_, _) => 64, + } + } + + pub fn is_mutable(&self) -> bool { + match self { + TypeKind::Borrow(_, true) => true, + _ => false, } } } @@ -221,14 +228,14 @@ impl Expression { } Accessed(_, type_kind, _) => Ok((ReturnKind::Soft, type_kind.clone())), Struct(name, _) => Ok((ReturnKind::Soft, TypeKind::CustomType(name.clone()))), - Borrow(var) => { + Borrow(var, mutable) => { let ret_type = var.return_type()?; - Ok((ret_type.0, TypeKind::Borrow(Box::new(ret_type.1)))) + Ok((ret_type.0, TypeKind::Borrow(Box::new(ret_type.1), *mutable))) } Deref(var) => { let (kind, ret_type) = var.return_type()?; match ret_type.resolve_weak(refs) { - TypeKind::Borrow(type_kind) => Ok((kind, *type_kind)), + TypeKind::Borrow(type_kind, _) => Ok((kind, *type_kind)), _ => Err(ReturnTypeOther::DerefNonBorrow(var.2)), } } @@ -240,7 +247,7 @@ impl Expression { ExprKind::Variable(var_ref) => Some(var_ref), ExprKind::Indexed(lhs, _, _) => lhs.backing_var(), ExprKind::Accessed(lhs, _, _) => lhs.backing_var(), - ExprKind::Borrow(var) => Some(var), + ExprKind::Borrow(var, _) => Some(var), ExprKind::Deref(var) => Some(var), ExprKind::Block(block) => block.backing_var(), ExprKind::Array(_) => None, @@ -335,7 +342,9 @@ impl TypeKind { let resolved = self.resolve_weak(refs); match resolved { TypeKind::Array(t, len) => TypeKind::Array(Box::new(t.resolve_ref(refs)), len), - TypeKind::Borrow(inner) => TypeKind::Borrow(Box::new(inner.resolve_ref(refs))), + TypeKind::Borrow(inner, mutable) => { + TypeKind::Borrow(Box::new(inner.resolve_ref(refs)), mutable) + } _ => resolved, } } diff --git a/reid/src/mir/mod.rs b/reid/src/mir/mod.rs index 2eb8320..8ef140c 100644 --- a/reid/src/mir/mod.rs +++ b/reid/src/mir/mod.rs @@ -110,7 +110,7 @@ pub enum TypeKind { #[error("{0}")] CustomType(String), #[error("Borrow({0})")] - Borrow(Box), + Borrow(Box, bool), #[error("Ptr({0})")] Ptr(Box), #[error(transparent)] @@ -247,7 +247,7 @@ pub enum ExprKind { FunctionCall(FunctionCall), If(IfExpression), Block(Block), - Borrow(NamedVariableRef), + Borrow(NamedVariableRef, bool), Deref(NamedVariableRef), } diff --git a/reid/src/mir/typecheck.rs b/reid/src/mir/typecheck.rs index 1d5232e..d438205 100644 --- a/reid/src/mir/typecheck.rs +++ b/reid/src/mir/typecheck.rs @@ -629,7 +629,7 @@ impl Expression { } Ok(TypeKind::CustomType(struct_name.clone())) } - ExprKind::Borrow(var_ref) => { + ExprKind::Borrow(var_ref, mutable) => { let existing = state .or_else( state @@ -651,7 +651,7 @@ impl Expression { var_ref.2, ); - Ok(TypeKind::Borrow(Box::new(var_ref.0.clone()))) + Ok(TypeKind::Borrow(Box::new(var_ref.0.clone()), *mutable)) } ExprKind::Deref(var_ref) => { let existing = state @@ -669,7 +669,7 @@ impl Expression { .resolve_ref(typerefs); // Update typing to be more accurate - let TypeKind::Borrow(inner) = state.or_else( + let TypeKind::Borrow(inner, mutable) = state.or_else( var_ref.0.resolve_ref(typerefs).collapse_into(&existing), TypeKind::Vague(Vague::Unknown), var_ref.2, @@ -677,7 +677,7 @@ impl Expression { return Err(ErrorKind::AttemptedDerefNonBorrow(var_ref.1.clone())); }; - var_ref.0 = TypeKind::Borrow(inner.clone()); + var_ref.0 = TypeKind::Borrow(inner.clone(), mutable); Ok(*inner) } @@ -761,9 +761,10 @@ impl Collapsable for TypeKind { (TypeKind::Vague(Vague::Unknown), other) | (other, TypeKind::Vague(Vague::Unknown)) => { Ok(other.clone()) } - (TypeKind::Borrow(val1), TypeKind::Borrow(val2)) => { - Ok(TypeKind::Borrow(Box::new(val1.collapse_into(val2)?))) - } + (TypeKind::Borrow(val1, mut1), TypeKind::Borrow(val2, mut2)) => Ok(TypeKind::Borrow( + Box::new(val1.collapse_into(val2)?), + *mut1 && *mut2, + )), _ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())), } } diff --git a/reid/src/mir/typeinference.rs b/reid/src/mir/typeinference.rs index 5e02dc0..f00c38a 100644 --- a/reid/src/mir/typeinference.rs +++ b/reid/src/mir/typeinference.rs @@ -364,7 +364,7 @@ impl Expression { .from_type(&TypeKind::CustomType(struct_name.clone())) .unwrap()) } - ExprKind::Borrow(var) => { + ExprKind::Borrow(var, mutable) => { // Find variable type let type_ref = type_refs .find_var(&var.1) @@ -377,7 +377,7 @@ impl Expression { } Ok(type_refs - .from_type(&TypeKind::Borrow(Box::new(var.0.clone()))) + .from_type(&TypeKind::Borrow(Box::new(var.0.clone()), *mutable)) .unwrap()) } ExprKind::Deref(var) => { @@ -393,7 +393,7 @@ impl Expression { } match &var.0.resolve_weak(type_refs.types) { - Borrow(type_kind) => Ok(type_refs.from_type(&type_kind).unwrap()), + Borrow(type_kind, _) => Ok(type_refs.from_type(&type_kind).unwrap()), _ => Err(ErrorKind::AttemptedDerefNonBorrow(var.1.clone())), } } diff --git a/reid/src/mir/typerefs.rs b/reid/src/mir/typerefs.rs index 15230cb..885c953 100644 --- a/reid/src/mir/typerefs.rs +++ b/reid/src/mir/typerefs.rs @@ -163,10 +163,10 @@ impl<'outer> ScopeTypeRefs<'outer> { self.types .new(&TypeKind::Array(Box::new(elem_ty.as_type()), *length)) } - TypeKind::Borrow(ty) => { + TypeKind::Borrow(ty, mutable) => { let inner_ty = self.from_type(ty)?; self.types - .new(&&TypeKind::Borrow(Box::new(inner_ty.as_type()))) + .new(&&TypeKind::Borrow(Box::new(inner_ty.as_type()), *mutable)) } _ => { if let Some(ty_ref) = self.types.find(ty) { diff --git a/reid_src/borrow.reid b/reid_src/borrow.reid index ac52245..861caa8 100644 --- a/reid_src/borrow.reid +++ b/reid_src/borrow.reid @@ -4,7 +4,7 @@ fn main() -> u32 { let mut value = [4, 3, 2]; - let mut borrow = &value; + let mut borrow = &mut value; (*borrow)[1] = 17; return value[1]; diff --git a/reid_src/borrow_hard.reid b/reid_src/borrow_hard.reid index 87545b5..38fe32e 100644 --- a/reid_src/borrow_hard.reid +++ b/reid_src/borrow_hard.reid @@ -1,13 +1,13 @@ // Arithmetic, function calls and imports! -fn changer(param: &u32) { +fn changer(param: &mut u32) { *param = 17; } fn main() -> u32 { let mut value = 6; - changer(&value); + changer(&mut value); return value; }