Add mutability to arrays
This commit is contained in:
parent
d99c450e61
commit
d2587df4c9
@ -9,7 +9,7 @@ fn main() -> u16 {
|
||||
|
||||
let mut list = array();
|
||||
|
||||
// list[1] = 5;
|
||||
list[3] = 5;
|
||||
|
||||
return list[3];
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use reid_lib::{
|
||||
TerminatorKind as Term, Type,
|
||||
};
|
||||
|
||||
use crate::mir::{self, types::ReturnType, NamedVariableRef, TypeKind};
|
||||
use crate::mir::{self, types::ReturnType, IndexedVariableReference, NamedVariableRef, TypeKind};
|
||||
|
||||
/// Context that contains all of the given modules as complete codegenerated
|
||||
/// LLIR that can then be finally compiled into LLVM IR.
|
||||
@ -153,6 +153,42 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexedVariableReference {
|
||||
fn get_stack_value(&self, scope: &mut Scope) -> Option<StackValue> {
|
||||
use StackValueKind as Kind;
|
||||
|
||||
match &self.kind {
|
||||
mir::IndexedVariableReferenceKind::Named(NamedVariableRef(_, name, _)) => {
|
||||
scope.stack_values.get(name).cloned()
|
||||
}
|
||||
mir::IndexedVariableReferenceKind::Index(inner, idx) => {
|
||||
let inner_val = inner.get_stack_value(scope)?;
|
||||
let inner_instr = match inner_val.0 {
|
||||
Kind::Immutable(val) => val,
|
||||
Kind::Mutable(val) => val,
|
||||
};
|
||||
|
||||
match inner_val.1 {
|
||||
Type::ArrayPtr(inner_ty, _) => {
|
||||
let gep_instr = scope
|
||||
.block
|
||||
.build(Instr::ArrayGEP(inner_instr, vec![*idx as u32]))
|
||||
.unwrap();
|
||||
Some(StackValue(
|
||||
match inner_val.0 {
|
||||
Kind::Immutable(_) => Kind::Immutable(gep_instr),
|
||||
Kind::Mutable(_) => Kind::Mutable(gep_instr),
|
||||
},
|
||||
*inner_ty,
|
||||
))
|
||||
}
|
||||
_ => panic!("Tried to codegen indexing a non-indexable value!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl mir::Statement {
|
||||
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>) -> Option<InstructionValue> {
|
||||
match &self.0 {
|
||||
@ -163,7 +199,9 @@ impl mir::Statement {
|
||||
StackValue(
|
||||
match mutable {
|
||||
false => StackValueKind::Immutable(value),
|
||||
true => StackValueKind::Mutable({
|
||||
true => match ty {
|
||||
TypeKind::Array(_, _) => StackValueKind::Mutable(value),
|
||||
_ => StackValueKind::Mutable({
|
||||
let alloca = scope
|
||||
.block
|
||||
.build(Instr::Alloca(name.clone(), ty.get_type()))
|
||||
@ -172,26 +210,26 @@ impl mir::Statement {
|
||||
alloca
|
||||
}),
|
||||
},
|
||||
},
|
||||
ty.get_type(),
|
||||
),
|
||||
);
|
||||
None
|
||||
}
|
||||
mir::StmtKind::Set(var, val) => {
|
||||
todo!("Re-think how set needs to work with arrays");
|
||||
// if let Some(StackValue(kind, _)) = scope.stack_values.get(&var.1).cloned() {
|
||||
// match kind {
|
||||
// StackValueKind::Immutable(_) => {
|
||||
// panic!("Tried to mutate an immutable variable")
|
||||
// }
|
||||
// StackValueKind::Mutable(ptr) => {
|
||||
// let expression = val.codegen(scope).unwrap();
|
||||
// Some(scope.block.build(Instr::Store(ptr, expression)).unwrap())
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// panic!("")
|
||||
// }
|
||||
if let Some(StackValue(kind, _)) = var.get_stack_value(scope) {
|
||||
match kind {
|
||||
StackValueKind::Immutable(_) => {
|
||||
panic!("Tried to mutate an immutable variable")
|
||||
}
|
||||
StackValueKind::Mutable(ptr) => {
|
||||
let expression = val.codegen(scope).unwrap();
|
||||
Some(scope.block.build(Instr::Store(ptr, expression)).unwrap())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!("")
|
||||
}
|
||||
}
|
||||
// mir::StmtKind::If(if_expression) => if_expression.codegen(scope),
|
||||
mir::StmtKind::Import(_) => todo!(),
|
||||
@ -267,9 +305,10 @@ impl mir::Expression {
|
||||
.expect("Variable reference not found?!");
|
||||
Some(match v.0 {
|
||||
StackValueKind::Immutable(val) => val.clone(),
|
||||
StackValueKind::Mutable(val) => {
|
||||
scope.block.build(Instr::Load(val, v.1.clone())).unwrap()
|
||||
}
|
||||
StackValueKind::Mutable(val) => match v.1 {
|
||||
Type::ArrayPtr(_, _) => val,
|
||||
_ => scope.block.build(Instr::Load(val, v.1.clone())).unwrap(),
|
||||
},
|
||||
})
|
||||
}
|
||||
mir::ExprKind::Literal(lit) => Some(lit.as_const(&mut scope.block)),
|
||||
|
@ -7,7 +7,7 @@ use TypeKind::*;
|
||||
use VagueType::*;
|
||||
|
||||
use super::{
|
||||
pass::{Pass, PassState, ScopeFunction, ScopeVariable},
|
||||
pass::{Pass, PassState, ScopeFunction, ScopeVariable, Storage},
|
||||
typerefs::TypeRefs,
|
||||
types::ReturnType,
|
||||
};
|
||||
@ -169,41 +169,46 @@ impl Block {
|
||||
None
|
||||
}
|
||||
StmtKind::Set(variable_reference, expression) => {
|
||||
todo!("Re-think how set needs to work with arrays")
|
||||
// if let Some(var) = state.scope.variables.get(&variable_reference.1).cloned() {
|
||||
// // Typecheck expression and coerce to variable type
|
||||
// let res = expression.typecheck(&mut state, &hints, Some(&var.ty));
|
||||
if let Some(var) = state
|
||||
.ok(
|
||||
variable_reference.get_variable(&state.scope.variables),
|
||||
variable_reference.meta,
|
||||
)
|
||||
.flatten()
|
||||
{
|
||||
// Typecheck expression and coerce to variable type
|
||||
let res = expression.typecheck(&mut state, &hints, Some(&var.ty));
|
||||
|
||||
// // If expression resolution itself was erronous, resolve as
|
||||
// // Unknown.
|
||||
// let expr_ty = state.or_else(res, Vague(Unknown), expression.1);
|
||||
// If expression resolution itself was erronous, resolve as
|
||||
// Unknown.
|
||||
let expr_ty = state.or_else(res, Vague(Unknown), expression.1);
|
||||
|
||||
// // Make sure the expression and variable type to really
|
||||
// // be the same
|
||||
// let res_t = state.or_else(
|
||||
// expr_ty.collapse_into(&variable_reference.0.resolve_hinted(&hints)),
|
||||
// Vague(Unknown),
|
||||
// variable_reference.2 + expression.1,
|
||||
// );
|
||||
// Make sure the expression and variable type to really
|
||||
// be the same
|
||||
let res_t = state.or_else(
|
||||
expr_ty.collapse_into(&var.ty.resolve_hinted(&hints)),
|
||||
Vague(Unknown),
|
||||
variable_reference.meta + expression.1,
|
||||
);
|
||||
|
||||
// // Update typing to be more accurate
|
||||
// variable_reference.0 = res_t;
|
||||
// Update typing to be more accurate
|
||||
variable_reference.update_type(&res_t);
|
||||
|
||||
// if !var.mutable {
|
||||
// state.ok::<_, Infallible>(
|
||||
// Err(ErrorKind::VariableNotMutable(variable_reference.1.clone())),
|
||||
// variable_reference.2,
|
||||
// );
|
||||
// }
|
||||
if !var.mutable {
|
||||
state.ok::<_, Infallible>(
|
||||
Err(ErrorKind::VariableNotMutable(variable_reference.get_name())),
|
||||
variable_reference.meta,
|
||||
);
|
||||
}
|
||||
|
||||
// None
|
||||
// } else {
|
||||
// state.ok::<_, Infallible>(
|
||||
// Err(ErrorKind::VariableNotDefined(variable_reference.1.clone())),
|
||||
// variable_reference.2,
|
||||
// );
|
||||
// None
|
||||
// }
|
||||
None
|
||||
} else {
|
||||
state.ok::<_, Infallible>(
|
||||
Err(ErrorKind::VariableNotDefined(variable_reference.get_name())),
|
||||
variable_reference.meta,
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
StmtKind::Import(_) => todo!(), // TODO
|
||||
StmtKind::Expression(expression) => {
|
||||
@ -438,6 +443,32 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexedVariableReference {
|
||||
fn get_variable(
|
||||
&self,
|
||||
storage: &Storage<ScopeVariable>,
|
||||
) -> Result<Option<ScopeVariable>, ErrorKind> {
|
||||
match &self.kind {
|
||||
IndexedVariableReferenceKind::Named(NamedVariableRef(_, name, _)) => {
|
||||
Ok(storage.get(&name).cloned())
|
||||
}
|
||||
IndexedVariableReferenceKind::Index(inner_ref, _) => {
|
||||
if let Some(var) = inner_ref.get_variable(storage)? {
|
||||
match &var.ty {
|
||||
TypeKind::Array(inner_ty, _) => Ok(Some(ScopeVariable {
|
||||
ty: *inner_ty.clone(),
|
||||
mutable: var.mutable,
|
||||
})),
|
||||
_ => Err(ErrorKind::TriedIndexingNonArray(var.ty.clone())),
|
||||
}
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Literal {
|
||||
/// Try to coerce this literal, ie. convert it to a more specific type in
|
||||
/// regards to the given hint if any.
|
||||
|
@ -13,8 +13,8 @@ use super::{
|
||||
typecheck::ErrorKind,
|
||||
typerefs::{ScopeTypeRefs, TypeRef, TypeRefs},
|
||||
types::{pick_return, ReturnType},
|
||||
Block, ExprKind, Expression, FunctionDefinition, FunctionDefinitionKind, IfExpression, Module,
|
||||
ReturnKind, StmtKind,
|
||||
Block, ExprKind, Expression, FunctionDefinition, FunctionDefinitionKind, IfExpression,
|
||||
IndexedVariableReference, Module, NamedVariableRef, ReturnKind, StmtKind,
|
||||
TypeKind::*,
|
||||
VagueType::*,
|
||||
};
|
||||
@ -113,24 +113,23 @@ impl Block {
|
||||
}
|
||||
}
|
||||
StmtKind::Set(var, expr) => {
|
||||
todo!("Re-think how set needs to work with arrays")
|
||||
// // Get the TypeRef for this variable declaration
|
||||
// let var_ref = inner_hints.find_hint(&var.1);
|
||||
// Get the TypeRef for this variable declaration
|
||||
let var_ref = var.find_hint(&inner_hints)?;
|
||||
|
||||
// // If ok, update the MIR type to this TypeRef
|
||||
// if let Some((_, var_ref)) = &var_ref {
|
||||
// var.0 = var_ref.as_type()
|
||||
// }
|
||||
// If ok, update the MIR type to this TypeRef
|
||||
if let Some((_, var_ref)) = &var_ref {
|
||||
var.update_type(&var_ref.as_type());
|
||||
}
|
||||
|
||||
// // Infer hints for the expression itself
|
||||
// let inferred = expr.infer_types(&mut state, &inner_hints);
|
||||
// let expr_ty_ref = state.ok(inferred, expr.1);
|
||||
// Infer hints for the expression itself
|
||||
let inferred = expr.infer_types(&mut state, &inner_hints);
|
||||
let expr_ty_ref = state.ok(inferred, expr.1);
|
||||
|
||||
// // Try to narrow the variable type declaration with the
|
||||
// // expression
|
||||
// if let (Some((_, mut var_ref)), Some(expr_ty_ref)) = (var_ref, expr_ty_ref) {
|
||||
// var_ref.narrow(&expr_ty_ref);
|
||||
// }
|
||||
// Try to narrow the variable type declaration with the
|
||||
// expression
|
||||
if let (Some((_, mut var_ref)), Some(expr_ty_ref)) = (var_ref, expr_ty_ref) {
|
||||
var_ref.narrow(&expr_ty_ref);
|
||||
}
|
||||
}
|
||||
StmtKind::Import(_) => todo!(),
|
||||
StmtKind::Expression(expr) => {
|
||||
@ -161,6 +160,33 @@ impl Block {
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexedVariableReference {
|
||||
fn find_hint<'s>(
|
||||
&self,
|
||||
hints: &'s ScopeTypeRefs,
|
||||
) -> Result<Option<(bool, TypeRef<'s>)>, ErrorKind> {
|
||||
match &self.kind {
|
||||
super::IndexedVariableReferenceKind::Named(NamedVariableRef(_, name, _)) => {
|
||||
Ok(hints.find_hint(&name))
|
||||
}
|
||||
super::IndexedVariableReferenceKind::Index(inner, _) => {
|
||||
if let Some((mutable, inner_ref)) = inner.find_hint(hints)? {
|
||||
let inner_ty = inner_ref.as_type();
|
||||
match inner_ty {
|
||||
Array(type_kind, _) => Ok(hints
|
||||
.from_type(&type_kind)
|
||||
.clone()
|
||||
.map(|t_ref| (mutable, t_ref))),
|
||||
_ => Err(ErrorKind::TriedIndexingNonArray(inner_ty.clone())),
|
||||
}
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
fn infer_types<'s>(
|
||||
&mut self,
|
||||
|
@ -1,4 +1,8 @@
|
||||
use super::*;
|
||||
use super::{
|
||||
pass::{ScopeVariable, Storage},
|
||||
typecheck::ErrorKind,
|
||||
*,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ReturnTypeOther {
|
||||
@ -160,3 +164,23 @@ pub fn pick_return<T>(lhs: (ReturnKind, T), rhs: (ReturnKind, T)) -> (ReturnKind
|
||||
(_, _) => (Soft, lhs.1),
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexedVariableReference {
|
||||
pub fn get_name(&self) -> String {
|
||||
match &self.kind {
|
||||
IndexedVariableReferenceKind::Named(NamedVariableRef(_, name, _)) => name.clone(),
|
||||
IndexedVariableReferenceKind::Index(inner, idx) => {
|
||||
format!("{}[{}]", inner.get_name(), idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_type(&mut self, new_ty: &TypeKind) {
|
||||
match &mut self.kind {
|
||||
IndexedVariableReferenceKind::Named(NamedVariableRef(ty, _, _)) => {
|
||||
*ty = new_ty.clone();
|
||||
}
|
||||
IndexedVariableReferenceKind::Index(inner, _) => inner.update_type(new_ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user