Add borrow mutability
This commit is contained in:
parent
8da32c25c5
commit
60818842a5
@ -27,7 +27,7 @@ pub enum TypeKind {
|
|||||||
String,
|
String,
|
||||||
Array(Box<TypeKind>, u64),
|
Array(Box<TypeKind>, u64),
|
||||||
Custom(String),
|
Custom(String),
|
||||||
Borrow(Box<TypeKind>),
|
Borrow(Box<TypeKind>, bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -43,7 +43,7 @@ pub struct Expression(pub ExpressionKind, pub TokenRange);
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ExpressionKind {
|
pub enum ExpressionKind {
|
||||||
VariableName(String),
|
VariableName(String),
|
||||||
Borrow(String),
|
Borrow(String, bool),
|
||||||
Deref(String),
|
Deref(String),
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
Array(Vec<Expression>),
|
Array(Vec<Expression>),
|
||||||
|
@ -26,8 +26,15 @@ impl Parse for Type {
|
|||||||
TypeKind::Array(Box::new(inner.0), length)
|
TypeKind::Array(Box::new(inner.0), length)
|
||||||
} else if let Some(Token::Et) = stream.peek() {
|
} else if let Some(Token::Et) = stream.peek() {
|
||||||
stream.expect(Token::Et)?;
|
stream.expect(Token::Et)?;
|
||||||
|
let mutable = if let Some(Token::MutKeyword) = stream.peek() {
|
||||||
|
stream.next();
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
let inner = stream.parse::<Type>()?;
|
let inner = stream.parse::<Type>()?;
|
||||||
TypeKind::Borrow(Box::new(inner.0))
|
TypeKind::Borrow(Box::new(inner.0), mutable)
|
||||||
} else {
|
} else {
|
||||||
if let Some(Token::Identifier(ident)) = stream.next() {
|
if let Some(Token::Identifier(ident)) = stream.next() {
|
||||||
match &*ident {
|
match &*ident {
|
||||||
@ -87,12 +94,19 @@ impl Parse for PrimaryExpression {
|
|||||||
Kind::StructExpression(stream.parse()?),
|
Kind::StructExpression(stream.parse()?),
|
||||||
stream.get_range().unwrap(),
|
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))) =
|
} else if let (Some(Token::Et), Some(Token::Identifier(name))) =
|
||||||
(stream.peek(), stream.peek2())
|
(stream.peek(), stream.peek2())
|
||||||
{
|
{
|
||||||
stream.next(); // Consume Et
|
stream.next(); // Consume Et
|
||||||
stream.next(); // Consume identifier
|
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))) =
|
} else if let (Some(Token::Star), Some(Token::Identifier(name))) =
|
||||||
(stream.peek(), stream.peek2())
|
(stream.peek(), stream.peek2())
|
||||||
{
|
{
|
||||||
|
@ -225,11 +225,14 @@ impl ast::Expression {
|
|||||||
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
||||||
name.clone(),
|
name.clone(),
|
||||||
),
|
),
|
||||||
ast::ExpressionKind::Borrow(name) => mir::ExprKind::Borrow(NamedVariableRef(
|
ast::ExpressionKind::Borrow(name, mutable) => mir::ExprKind::Borrow(
|
||||||
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
NamedVariableRef(
|
||||||
name.clone(),
|
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
||||||
self.1.as_meta(module_id),
|
name.clone(),
|
||||||
)),
|
self.1.as_meta(module_id),
|
||||||
|
),
|
||||||
|
*mutable,
|
||||||
|
),
|
||||||
ast::ExpressionKind::Deref(name) => mir::ExprKind::Deref(NamedVariableRef(
|
ast::ExpressionKind::Deref(name) => mir::ExprKind::Deref(NamedVariableRef(
|
||||||
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
||||||
name.clone(),
|
name.clone(),
|
||||||
@ -287,8 +290,8 @@ impl From<ast::TypeKind> for mir::TypeKind {
|
|||||||
}
|
}
|
||||||
ast::TypeKind::String => mir::TypeKind::StringPtr,
|
ast::TypeKind::String => mir::TypeKind::StringPtr,
|
||||||
ast::TypeKind::Custom(name) => mir::TypeKind::CustomType(name.clone()),
|
ast::TypeKind::Custom(name) => mir::TypeKind::CustomType(name.clone()),
|
||||||
ast::TypeKind::Borrow(type_kind) => {
|
ast::TypeKind::Borrow(type_kind, mutable) => {
|
||||||
mir::TypeKind::Borrow(Box::new(mir::TypeKind::from(*type_kind.clone())))
|
mir::TypeKind::Borrow(Box::new(mir::TypeKind::from(*type_kind.clone())), *mutable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,13 @@ pub enum StackValueKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl StackValueKind {
|
impl StackValueKind {
|
||||||
|
fn mutable(mutable: bool, instr: InstructionValue) -> StackValueKind {
|
||||||
|
match mutable {
|
||||||
|
true => StackValueKind::Mutable(instr),
|
||||||
|
false => StackValueKind::Immutable(instr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn instr(&self) -> InstructionValue {
|
fn instr(&self) -> InstructionValue {
|
||||||
match &self {
|
match &self {
|
||||||
StackValueKind::Immutable(val) => *val,
|
StackValueKind::Immutable(val) => *val,
|
||||||
@ -934,13 +941,16 @@ impl mir::Expression {
|
|||||||
TypeKind::CustomType(name.clone()),
|
TypeKind::CustomType(name.clone()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
mir::ExprKind::Borrow(varref) => {
|
mir::ExprKind::Borrow(varref, mutable) => {
|
||||||
varref.0.known().expect("variable type unknown");
|
varref.0.known().expect("variable type unknown");
|
||||||
let v = scope
|
let v = scope
|
||||||
.stack_values
|
.stack_values
|
||||||
.get(&varref.1)
|
.get(&varref.1)
|
||||||
.expect("Variable reference not found?!");
|
.expect("Variable reference not found?!");
|
||||||
Some(v.clone())
|
Some(StackValue(
|
||||||
|
StackValueKind::mutable(*mutable, v.0.instr()),
|
||||||
|
v.1.clone(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
mir::ExprKind::Deref(varref) => {
|
mir::ExprKind::Deref(varref) => {
|
||||||
varref.0.known().expect("variable type unknown");
|
varref.0.known().expect("variable type unknown");
|
||||||
@ -1166,7 +1176,7 @@ impl TypeKind {
|
|||||||
TypeKind::Ptr(type_kind) => {
|
TypeKind::Ptr(type_kind) => {
|
||||||
Type::Ptr(Box::new(type_kind.get_type(type_vals, typedefs)))
|
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)))
|
Type::Ptr(Box::new(type_kind.get_type(type_vals, typedefs)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1213,7 +1223,7 @@ impl TypeKind {
|
|||||||
),
|
),
|
||||||
size_bits: self.size_of(),
|
size_bits: self.size_of(),
|
||||||
}),
|
}),
|
||||||
TypeKind::Ptr(inner) | TypeKind::Borrow(inner) => {
|
TypeKind::Ptr(inner) | TypeKind::Borrow(inner, _) => {
|
||||||
DebugTypeData::Pointer(DebugPointerType {
|
DebugTypeData::Pointer(DebugPointerType {
|
||||||
name,
|
name,
|
||||||
pointee: inner.get_debug_type_hard(
|
pointee: inner.get_debug_type_hard(
|
||||||
|
@ -208,7 +208,8 @@ impl Display for ExprKind {
|
|||||||
write_access(f, name)?;
|
write_access(f, name)?;
|
||||||
write!(f, "<{}>", type_kind)
|
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),
|
ExprKind::Deref(var_ref) => write!(f, "*{}", var_ref),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ impl TypeKind {
|
|||||||
TypeKind::CustomType(_) => 32,
|
TypeKind::CustomType(_) => 32,
|
||||||
TypeKind::Ptr(_) => 64,
|
TypeKind::Ptr(_) => 64,
|
||||||
TypeKind::Vague(_) => panic!("Tried to sizeof a vague type!"),
|
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::CustomType(_) => 32,
|
||||||
TypeKind::Ptr(_) => 64,
|
TypeKind::Ptr(_) => 64,
|
||||||
TypeKind::Vague(_) => panic!("Tried to sizeof a vague type!"),
|
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())),
|
Accessed(_, type_kind, _) => Ok((ReturnKind::Soft, type_kind.clone())),
|
||||||
Struct(name, _) => Ok((ReturnKind::Soft, TypeKind::CustomType(name.clone()))),
|
Struct(name, _) => Ok((ReturnKind::Soft, TypeKind::CustomType(name.clone()))),
|
||||||
Borrow(var) => {
|
Borrow(var, mutable) => {
|
||||||
let ret_type = var.return_type()?;
|
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) => {
|
Deref(var) => {
|
||||||
let (kind, ret_type) = var.return_type()?;
|
let (kind, ret_type) = var.return_type()?;
|
||||||
match ret_type.resolve_weak(refs) {
|
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)),
|
_ => Err(ReturnTypeOther::DerefNonBorrow(var.2)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,7 +247,7 @@ impl Expression {
|
|||||||
ExprKind::Variable(var_ref) => Some(var_ref),
|
ExprKind::Variable(var_ref) => Some(var_ref),
|
||||||
ExprKind::Indexed(lhs, _, _) => lhs.backing_var(),
|
ExprKind::Indexed(lhs, _, _) => lhs.backing_var(),
|
||||||
ExprKind::Accessed(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::Deref(var) => Some(var),
|
||||||
ExprKind::Block(block) => block.backing_var(),
|
ExprKind::Block(block) => block.backing_var(),
|
||||||
ExprKind::Array(_) => None,
|
ExprKind::Array(_) => None,
|
||||||
@ -335,7 +342,9 @@ impl TypeKind {
|
|||||||
let resolved = self.resolve_weak(refs);
|
let resolved = self.resolve_weak(refs);
|
||||||
match resolved {
|
match resolved {
|
||||||
TypeKind::Array(t, len) => TypeKind::Array(Box::new(t.resolve_ref(refs)), len),
|
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,
|
_ => resolved,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ pub enum TypeKind {
|
|||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
CustomType(String),
|
CustomType(String),
|
||||||
#[error("Borrow({0})")]
|
#[error("Borrow({0})")]
|
||||||
Borrow(Box<TypeKind>),
|
Borrow(Box<TypeKind>, bool),
|
||||||
#[error("Ptr({0})")]
|
#[error("Ptr({0})")]
|
||||||
Ptr(Box<TypeKind>),
|
Ptr(Box<TypeKind>),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
@ -247,7 +247,7 @@ pub enum ExprKind {
|
|||||||
FunctionCall(FunctionCall),
|
FunctionCall(FunctionCall),
|
||||||
If(IfExpression),
|
If(IfExpression),
|
||||||
Block(Block),
|
Block(Block),
|
||||||
Borrow(NamedVariableRef),
|
Borrow(NamedVariableRef, bool),
|
||||||
Deref(NamedVariableRef),
|
Deref(NamedVariableRef),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,7 +629,7 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
Ok(TypeKind::CustomType(struct_name.clone()))
|
Ok(TypeKind::CustomType(struct_name.clone()))
|
||||||
}
|
}
|
||||||
ExprKind::Borrow(var_ref) => {
|
ExprKind::Borrow(var_ref, mutable) => {
|
||||||
let existing = state
|
let existing = state
|
||||||
.or_else(
|
.or_else(
|
||||||
state
|
state
|
||||||
@ -651,7 +651,7 @@ impl Expression {
|
|||||||
var_ref.2,
|
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) => {
|
ExprKind::Deref(var_ref) => {
|
||||||
let existing = state
|
let existing = state
|
||||||
@ -669,7 +669,7 @@ impl Expression {
|
|||||||
.resolve_ref(typerefs);
|
.resolve_ref(typerefs);
|
||||||
|
|
||||||
// Update typing to be more accurate
|
// 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),
|
var_ref.0.resolve_ref(typerefs).collapse_into(&existing),
|
||||||
TypeKind::Vague(Vague::Unknown),
|
TypeKind::Vague(Vague::Unknown),
|
||||||
var_ref.2,
|
var_ref.2,
|
||||||
@ -677,7 +677,7 @@ impl Expression {
|
|||||||
return Err(ErrorKind::AttemptedDerefNonBorrow(var_ref.1.clone()));
|
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)
|
Ok(*inner)
|
||||||
}
|
}
|
||||||
@ -761,9 +761,10 @@ impl Collapsable for TypeKind {
|
|||||||
(TypeKind::Vague(Vague::Unknown), other) | (other, TypeKind::Vague(Vague::Unknown)) => {
|
(TypeKind::Vague(Vague::Unknown), other) | (other, TypeKind::Vague(Vague::Unknown)) => {
|
||||||
Ok(other.clone())
|
Ok(other.clone())
|
||||||
}
|
}
|
||||||
(TypeKind::Borrow(val1), TypeKind::Borrow(val2)) => {
|
(TypeKind::Borrow(val1, mut1), TypeKind::Borrow(val2, mut2)) => Ok(TypeKind::Borrow(
|
||||||
Ok(TypeKind::Borrow(Box::new(val1.collapse_into(val2)?)))
|
Box::new(val1.collapse_into(val2)?),
|
||||||
}
|
*mut1 && *mut2,
|
||||||
|
)),
|
||||||
_ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())),
|
_ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -364,7 +364,7 @@ impl Expression {
|
|||||||
.from_type(&TypeKind::CustomType(struct_name.clone()))
|
.from_type(&TypeKind::CustomType(struct_name.clone()))
|
||||||
.unwrap())
|
.unwrap())
|
||||||
}
|
}
|
||||||
ExprKind::Borrow(var) => {
|
ExprKind::Borrow(var, mutable) => {
|
||||||
// Find variable type
|
// Find variable type
|
||||||
let type_ref = type_refs
|
let type_ref = type_refs
|
||||||
.find_var(&var.1)
|
.find_var(&var.1)
|
||||||
@ -377,7 +377,7 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(type_refs
|
Ok(type_refs
|
||||||
.from_type(&TypeKind::Borrow(Box::new(var.0.clone())))
|
.from_type(&TypeKind::Borrow(Box::new(var.0.clone()), *mutable))
|
||||||
.unwrap())
|
.unwrap())
|
||||||
}
|
}
|
||||||
ExprKind::Deref(var) => {
|
ExprKind::Deref(var) => {
|
||||||
@ -393,7 +393,7 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match &var.0.resolve_weak(type_refs.types) {
|
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())),
|
_ => Err(ErrorKind::AttemptedDerefNonBorrow(var.1.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,10 +163,10 @@ impl<'outer> ScopeTypeRefs<'outer> {
|
|||||||
self.types
|
self.types
|
||||||
.new(&TypeKind::Array(Box::new(elem_ty.as_type()), *length))
|
.new(&TypeKind::Array(Box::new(elem_ty.as_type()), *length))
|
||||||
}
|
}
|
||||||
TypeKind::Borrow(ty) => {
|
TypeKind::Borrow(ty, mutable) => {
|
||||||
let inner_ty = self.from_type(ty)?;
|
let inner_ty = self.from_type(ty)?;
|
||||||
self.types
|
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) {
|
if let Some(ty_ref) = self.types.find(ty) {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
fn main() -> u32 {
|
fn main() -> u32 {
|
||||||
let mut value = [4, 3, 2];
|
let mut value = [4, 3, 2];
|
||||||
|
|
||||||
let mut borrow = &value;
|
let mut borrow = &mut value;
|
||||||
(*borrow)[1] = 17;
|
(*borrow)[1] = 17;
|
||||||
|
|
||||||
return value[1];
|
return value[1];
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
// Arithmetic, function calls and imports!
|
// Arithmetic, function calls and imports!
|
||||||
|
|
||||||
fn changer(param: &u32) {
|
fn changer(param: &mut u32) {
|
||||||
*param = 17;
|
*param = 17;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> u32 {
|
fn main() -> u32 {
|
||||||
let mut value = 6;
|
let mut value = 6;
|
||||||
|
|
||||||
changer(&value);
|
changer(&mut value);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user