diff --git a/reid/examples/testcodegen.rs b/reid/examples/testcodegen.rs index 35b2033..dc31b03 100644 --- a/reid/examples/testcodegen.rs +++ b/reid/examples/testcodegen.rs @@ -19,7 +19,7 @@ fn main() { ExprKind::BinOp( BinaryOperator::Cmp(CmpOperator::GT), Box::new(Expression( - ExprKind::Variable(VariableReference( + ExprKind::Variable(NamedVariableRef( TypeKind::I32, "N".to_string(), Default::default(), @@ -52,7 +52,7 @@ fn main() { BinaryOperator::Minus, Box::new(Expression( ExprKind::Variable( - VariableReference( + NamedVariableRef( TypeKind::I32, fibonacci_n.clone(), Default::default(), @@ -80,7 +80,7 @@ fn main() { BinaryOperator::Minus, Box::new(Expression( ExprKind::Variable( - VariableReference( + NamedVariableRef( TypeKind::I32, fibonacci_n.clone(), Default::default(), diff --git a/reid/src/ast/mod.rs b/reid/src/ast/mod.rs index ddc1096..51fad1e 100644 --- a/reid/src/ast/mod.rs +++ b/reid/src/ast/mod.rs @@ -133,7 +133,10 @@ pub struct Block( ); #[derive(Debug, Clone)] -pub enum VariableReference { +pub struct VariableReference(VariableReferenceKind, TokenRange); + +#[derive(Debug, Clone)] +pub enum VariableReferenceKind { Name(String), Index(Box, u64), } diff --git a/reid/src/ast/parse.rs b/reid/src/ast/parse.rs index 54901ef..1c8103a 100644 --- a/reid/src/ast/parse.rs +++ b/reid/src/ast/parse.rs @@ -350,7 +350,7 @@ impl Parse for Block { stream.expect(Token::BraceOpen)?; while !matches!(stream.peek(), Some(Token::BraceClose)) { - if let Some((r_type, e)) = return_stmt.take() { + if let Some((_, e)) = return_stmt.take() { // Special list of expressions that are simply not warned about, // if semicolon is missing. if !matches!(e, Expression(ExpressionKind::IfExpr(_), _)) { @@ -383,12 +383,18 @@ impl Parse for Block { impl Parse for VariableReference { fn parse(mut stream: TokenStream) -> Result { if let Some(Token::Identifier(ident)) = stream.next() { - let mut var_ref = VariableReference::Name(ident); + let mut var_ref = VariableReference( + VariableReferenceKind::Name(ident), + stream.get_range().unwrap(), + ); dbg!(&var_ref); while let Ok(ValueIndex(idx)) = stream.parse() { dbg!(idx); - var_ref = VariableReference::Index(Box::new(var_ref), idx); + var_ref = VariableReference( + VariableReferenceKind::Index(Box::new(var_ref), idx), + stream.get_range().unwrap(), + ); } Ok(var_ref) diff --git a/reid/src/ast/process.rs b/reid/src/ast/process.rs index e2feae2..d92085b 100644 --- a/reid/src/ast/process.rs +++ b/reid/src/ast/process.rs @@ -1,6 +1,6 @@ use crate::{ ast::{self}, - mir::{self, StmtKind, VariableReference}, + mir::{self, NamedVariableRef, StmtKind}, }; impl mir::Context { @@ -61,7 +61,7 @@ impl ast::Block { let (kind, range) = match statement { ast::BlockLevelStatement::Let(s_let) => ( mir::StmtKind::Let( - mir::VariableReference( + mir::NamedVariableRef( s_let .1 .clone() @@ -75,9 +75,9 @@ impl ast::Block { ), s_let.4, ), - ast::BlockLevelStatement::Set(name, expression, range) => ( + ast::BlockLevelStatement::Set(var_ref, expression, range) => ( StmtKind::Set( - VariableReference( + NamedVariableRef( mir::TypeKind::Vague(mir::VagueType::Unknown), todo!(), // was name.clone() (*range).into(), @@ -117,10 +117,27 @@ impl From for mir::ReturnKind { } } +impl ast::VariableReference { + fn process(&self) -> mir::IndexedVariableReference { + match &self.0 { + ast::VariableReferenceKind::Name(name) => { + mir::IndexedVariableReference::Named(NamedVariableRef( + mir::TypeKind::Vague(mir::VagueType::Unknown), + name.clone(), + self.1.into(), + )) + } + ast::VariableReferenceKind::Index(var_ref, idx) => { + mir::IndexedVariableReference::Index(Box::new(var_ref.process()), *idx) + } + } + } +} + impl ast::Expression { fn process(&self) -> mir::Expression { let kind = match &self.0 { - ast::ExpressionKind::VariableName(name) => mir::ExprKind::Variable(VariableReference( + ast::ExpressionKind::VariableName(name) => mir::ExprKind::Variable(NamedVariableRef( mir::TypeKind::Vague(mir::VagueType::Unknown), name.clone(), self.1.into(), @@ -149,8 +166,10 @@ impl ast::Expression { }; mir::ExprKind::If(mir::IfExpression(Box::new(cond), then_block, else_block)) } - ast::ExpressionKind::Array(expressions) => todo!(), - ast::ExpressionKind::Index(expression, _) => todo!(), + ast::ExpressionKind::Array(expressions) => todo!("process for array expression"), + ast::ExpressionKind::Index(expression, idx) => { + mir::ExprKind::Index(Box::new(expression.process()), *idx) + } }; mir::Expression(kind, self.1.into()) @@ -197,7 +216,9 @@ impl From for mir::TypeKind { ast::TypeKind::U32 => mir::TypeKind::U32, ast::TypeKind::U64 => mir::TypeKind::U64, ast::TypeKind::U128 => mir::TypeKind::U128, - ast::TypeKind::Array(type_kind, length) => todo!(), + ast::TypeKind::Array(type_kind, length) => { + mir::TypeKind::Array(Box::new(mir::TypeKind::from(*type_kind.clone())), *length) + } } } } diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index a56cfb4..5115cbb 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -5,7 +5,7 @@ use reid_lib::{ TerminatorKind as Term, Type, }; -use crate::mir::{self, types::ReturnType, TypeKind, VariableReference}; +use crate::mir::{self, types::ReturnType, NamedVariableRef, TypeKind}; /// Context that contains all of the given modules as complete codegenerated /// LLIR that can then be finally compiled into LLVM IR. @@ -156,7 +156,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> { impl mir::Statement { fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>) -> Option { match &self.0 { - mir::StmtKind::Let(VariableReference(ty, name, _), mutable, expression) => { + mir::StmtKind::Let(NamedVariableRef(ty, name, _), mutable, expression) => { let value = expression.codegen(scope).unwrap(); scope.stack_values.insert( name.clone(), @@ -333,6 +333,7 @@ impl mir::Expression { None } } + mir::ExprKind::Index(expression, _) => todo!("codegen for index expression"), } } } @@ -413,6 +414,7 @@ impl TypeKind { TypeKind::Bool => Type::Bool, TypeKind::Void => panic!("Void not a supported type"), TypeKind::Vague(_) => panic!("Tried to compile a vague type!"), + TypeKind::Array(_, _) => todo!("codegen for array type"), } } } diff --git a/reid/src/mir/display.rs b/reid/src/mir/display.rs index d24ff76..78f0c07 100644 --- a/reid/src/mir/display.rs +++ b/reid/src/mir/display.rs @@ -122,12 +122,16 @@ impl Display for Expression { impl Display for ExprKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::Variable(var) => Display::fmt(var, f), - Self::Literal(lit) => Display::fmt(lit, f), - Self::BinOp(op, lhs, rhs) => write!(f, "{} {} {}", lhs, op, rhs), - Self::FunctionCall(fc) => Display::fmt(fc, f), - Self::If(if_exp) => Display::fmt(&if_exp, f), - Self::Block(block) => Display::fmt(block, f), + ExprKind::Variable(var) => Display::fmt(var, f), + ExprKind::Literal(lit) => Display::fmt(lit, f), + ExprKind::BinOp(op, lhs, rhs) => write!(f, "{} {} {}", lhs, op, rhs), + ExprKind::FunctionCall(fc) => Display::fmt(fc, f), + ExprKind::If(if_exp) => Display::fmt(&if_exp, f), + ExprKind::Block(block) => Display::fmt(block, f), + ExprKind::Index(expression, idx) => { + Display::fmt(&expression, f)?; + write_index(f, *idx) + } } } } @@ -156,12 +160,24 @@ impl Display for FunctionCall { } } -impl Display for VariableReference { +impl Display for NamedVariableRef { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "v(\"{}\", {})", &self.1, &self.0) } } +impl Display for IndexedVariableReference { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + IndexedVariableReference::Named(name) => Display::fmt(name, f), + IndexedVariableReference::Index(variable_reference_kind, idx) => { + Display::fmt(&variable_reference_kind, f)?; + write_index(f, *idx) + } + } + } +} + impl Display for Literal { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -211,3 +227,9 @@ impl Display for Metadata { write!(f, "{:?}", self.range) } } + +fn write_index(f: &mut std::fmt::Formatter<'_>, idx: u64) -> std::fmt::Result { + f.write_char('[')?; + Display::fmt(&idx, f)?; + f.write_char(']') +} diff --git a/reid/src/mir/mod.rs b/reid/src/mir/mod.rs index afbbf54..fb9f3c4 100644 --- a/reid/src/mir/mod.rs +++ b/reid/src/mir/mod.rs @@ -32,7 +32,7 @@ impl From for Metadata { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)] +#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] pub enum TypeKind { #[error("bool")] Bool, @@ -58,6 +58,8 @@ pub enum TypeKind { U128, #[error("void")] Void, + #[error("[{0}; {1}]")] + Array(Box, u64), #[error(transparent)] Vague(#[from] VagueType), } @@ -77,7 +79,7 @@ impl TypeKind { if let TypeKind::Vague(vague) = self { Err(*vague) } else { - Ok(*self) + Ok(self.clone()) } } } @@ -98,6 +100,7 @@ impl TypeKind { TypeKind::U32 => false, TypeKind::U64 => false, TypeKind::U128 => false, + TypeKind::Array(_, _) => false, } } @@ -117,6 +120,7 @@ impl TypeKind { Bool => true, Vague(_) => false, Void => false, + Array(_, _) => false, } } } @@ -196,14 +200,15 @@ pub enum ReturnKind { } #[derive(Debug)] -pub struct VariableReference(pub TypeKind, pub String, pub Metadata); +pub struct NamedVariableRef(pub TypeKind, pub String, pub Metadata); #[derive(Debug)] pub struct Import(pub String, pub Metadata); #[derive(Debug)] pub enum ExprKind { - Variable(VariableReference), + Variable(NamedVariableRef), + Index(Box, u64), Literal(Literal), BinOp(BinaryOperator, Box, Box), FunctionCall(FunctionCall), @@ -267,11 +272,16 @@ pub struct Block { #[derive(Debug)] pub struct Statement(pub StmtKind, pub Metadata); +pub enum IndexedVariableReference { + Named(NamedVariableRef), + Index(Box, u64), +} + #[derive(Debug)] pub enum StmtKind { /// Variable name++mutability+type, evaluation - Let(VariableReference, bool, Expression), - Set(VariableReference, Expression), + Let(NamedVariableRef, bool, Expression), + Set(NamedVariableRef, Expression), Import(Import), Expression(Expression), } diff --git a/reid/src/mir/pass.rs b/reid/src/mir/pass.rs index 5bbc756..8da3abc 100644 --- a/reid/src/mir/pass.rs +++ b/reid/src/mir/pass.rs @@ -129,7 +129,7 @@ impl Scope { Scope { function_returns: self.function_returns.clone(), variables: self.variables.clone(), - return_type_hint: self.return_type_hint, + return_type_hint: self.return_type_hint.clone(), } } } @@ -211,8 +211,8 @@ impl Module { .set( function.name.clone(), ScopeFunction { - ret: function.return_type, - params: function.parameters.iter().map(|v| v.1).collect(), + ret: function.return_type.clone(), + params: function.parameters.iter().cloned().map(|v| v.1).collect(), }, ) .ok(); @@ -234,7 +234,7 @@ impl FunctionDefinition { .set( param.0.clone(), ScopeVariable { - ty: param.1, + ty: param.1.clone(), mutable: false, }, ) @@ -245,7 +245,7 @@ impl FunctionDefinition { match &mut self.kind { FunctionDefinitionKind::Local(block, _) => { - scope.return_type_hint = Some(self.return_type); + scope.return_type_hint = Some(self.return_type.clone()); block.pass(pass, state, scope); } FunctionDefinitionKind::Extern => {} @@ -289,7 +289,7 @@ impl Statement { .set( variable_reference.1.clone(), ScopeVariable { - ty: variable_reference.0, + ty: variable_reference.0.clone(), mutable: *mutable, }, ) diff --git a/reid/src/mir/typecheck.rs b/reid/src/mir/typecheck.rs index 46e7b2f..004ba5d 100644 --- a/reid/src/mir/typecheck.rs +++ b/reid/src/mir/typecheck.rs @@ -84,8 +84,8 @@ impl FunctionDefinition { let return_type = self.return_type.clone(); let inferred = match &mut self.kind { FunctionDefinitionKind::Local(block, _) => { - state.scope.return_type_hint = Some(self.return_type); - block.typecheck(state, &hints, Some(return_type)) + state.scope.return_type_hint = Some(self.return_type.clone()); + block.typecheck(state, &hints, Some(&return_type)) } FunctionDefinitionKind::Extern => Ok(Vague(Unknown)), }; @@ -104,7 +104,7 @@ impl Block { &mut self, state: &mut PassState, hints: &TypeRefs, - hint_t: Option, + hint_t: Option<&TypeKind>, ) -> Result { let mut state = state.inner(); @@ -117,7 +117,7 @@ impl Block { let var_t_resolved = variable_reference.0.resolve_hinted(&hints); // Typecheck (and coerce) expression with said type - let res = expression.typecheck(&mut state, &hints, Some(var_t_resolved)); + let res = expression.typecheck(&mut state, &hints, Some(&var_t_resolved)); // If expression resolution itself was erronous, resolve as // Unknown and note error. @@ -136,7 +136,7 @@ impl Block { state.or_else(res_t.or_default(), Vague(Unknown), variable_reference.2); // Re-typecheck and coerce expression to default type - let expr_res = expression.typecheck(&mut state, &hints, Some(res_t)); + let expr_res = expression.typecheck(&mut state, &hints, Some(&res_t)); state.ok(expr_res, expression.1); res_t @@ -154,7 +154,7 @@ impl Block { .set( variable_reference.1.clone(), ScopeVariable { - ty: variable_reference.0, + ty: variable_reference.0.clone(), mutable: *mutable, }, ) @@ -167,7 +167,7 @@ impl Block { StmtKind::Set(variable_reference, expression) => { 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)); + let res = expression.typecheck(&mut state, &hints, Some(&var.ty)); // If expression resolution itself was erronous, resolve as // Unknown. @@ -221,18 +221,18 @@ impl Block { // as to not cause problems in codegen later (when unable to delete the // block) if let Some((ReturnKind::Hard, expr)) = early_return { - let hint = state.scope.return_type_hint; - let res = expr.typecheck(&mut state, &hints, hint); + let hint = state.scope.return_type_hint.clone(); + let res = expr.typecheck(&mut state, &hints, hint.as_ref()); return Ok(state.or_else(res, Vague(Unknown), expr.1)); } if let Some((return_kind, expr)) = &mut self.return_expression { // Use function return type as hint if return is hard. let ret_hint_t = match return_kind { - ReturnKind::Hard => state.scope.return_type_hint, - ReturnKind::Soft => hint_t, + ReturnKind::Hard => state.scope.return_type_hint.clone(), + ReturnKind::Soft => hint_t.cloned(), }; - let res = expr.typecheck(&mut state, &hints, ret_hint_t); + let res = expr.typecheck(&mut state, &hints, ret_hint_t.as_ref()); Ok(state.or_else(res, Vague(Unknown), expr.1)) } else { Ok(Void) @@ -245,7 +245,7 @@ impl Expression { &mut self, state: &mut PassState, hints: &TypeRefs, - hint_t: Option, + hint_t: Option<&TypeKind>, ) -> Result { match &mut self.0 { ExprKind::Variable(var_ref) => { @@ -268,10 +268,10 @@ impl Expression { var_ref.2, ); - Ok(var_ref.0) + Ok(var_ref.0.clone()) } ExprKind::Literal(literal) => { - *literal = literal.try_coerce(hint_t)?; + *literal = literal.try_coerce(hint_t.cloned())?; Ok(literal.as_type()) } ExprKind::BinOp(op, lhs, rhs) => { @@ -279,13 +279,13 @@ impl Expression { // operation once relevant let lhs_res = lhs.typecheck(state, &hints, None); let lhs_type = state.or_else(lhs_res, Vague(Unknown), lhs.1); - let rhs_res = rhs.typecheck(state, &hints, Some(lhs_type)); + let rhs_res = rhs.typecheck(state, &hints, Some(&lhs_type)); let rhs_type = state.or_else(rhs_res, Vague(Unknown), rhs.1); if let Some(collapsed) = state.ok(rhs_type.collapse_into(&rhs_type), self.1) { // Try to coerce both sides again with collapsed type - lhs.typecheck(state, &hints, Some(collapsed)).ok(); - rhs.typecheck(state, &hints, Some(collapsed)).ok(); + lhs.typecheck(state, &hints, Some(&collapsed)).ok(); + rhs.typecheck(state, &hints, Some(&collapsed)).ok(); } let both_t = lhs_type.collapse_into(&rhs_type)?; @@ -322,7 +322,7 @@ impl Expression { function_call.parameters.iter_mut().zip(true_params_iter) { // Typecheck every param separately - let param_res = param.typecheck(state, &hints, Some(true_param_t)); + let param_res = param.typecheck(state, &hints, Some(&true_param_t)); let param_t = state.or_else(param_res, Vague(Unknown), param.1); state.ok(param_t.collapse_into(&true_param_t), param.1); } @@ -333,14 +333,14 @@ impl Expression { .ret .collapse_into(&function_call.return_type.resolve_hinted(hints))?; // Update typing to be more accurate - function_call.return_type = ret_t; + function_call.return_type = ret_t.clone(); Ok(ret_t) } else { - Ok(function_call.return_type) + Ok(function_call.return_type.clone()) } } ExprKind::If(IfExpression(cond, lhs, rhs)) => { - let cond_res = cond.typecheck(state, &hints, Some(Bool)); + let cond_res = cond.typecheck(state, &hints, Some(&Bool)); let cond_t = state.or_else(cond_res, Vague(Unknown), cond.1); state.ok(cond_t.collapse_into(&Bool), cond.1); @@ -364,8 +364,8 @@ impl Expression { if let Some(rhs) = rhs { // If rhs existed, typecheck both sides to perform type // coercion. - let lhs_res = lhs.typecheck(state, &hints, Some(collapsed)); - let rhs_res = rhs.typecheck(state, &hints, Some(collapsed)); + let lhs_res = lhs.typecheck(state, &hints, Some(&collapsed)); + let rhs_res = rhs.typecheck(state, &hints, Some(&collapsed)); state.ok(lhs_res, lhs.meta); state.ok(rhs_res, rhs.meta); } @@ -373,6 +373,7 @@ impl Expression { Ok(collapsed) } ExprKind::Block(block) => block.typecheck(state, &hints, hint_t), + ExprKind::Index(expression, _) => todo!("typechecking for index expression"), } } } @@ -381,7 +382,7 @@ impl Literal { /// Try to coerce this literal, ie. convert it to a more specific type in /// regards to the given hint if any. fn try_coerce(self, hint: Option) -> Result { - if let Some(hint) = hint { + if let Some(hint) = &hint { use Literal as L; use VagueLiteral as VagueL; Ok(match (self, hint) { @@ -409,7 +410,7 @@ impl Literal { (L::Vague(VagueL::Number(v)), U64) => L::U64(v as u64), (L::Vague(VagueL::Number(v)), U128) => L::U128(v as u128), (_, Vague(_)) => self, - _ => Err(ErrorKind::LiteralIncompatible(self, hint))?, + _ => Err(ErrorKind::LiteralIncompatible(self, hint.clone()))?, }) } else { Ok(self) @@ -428,19 +429,19 @@ impl TypeKind { /// Error if not. fn or_default(&self) -> Result { match self { - Vague(vague_type) => match vague_type { + Vague(vague_type) => match &vague_type { Unknown => Err(ErrorKind::TypeIsVague(*vague_type)), Number => Ok(TypeKind::I32), TypeRef(_) => panic!("Hinted default!"), }, - _ => Ok(*self), + _ => Ok(self.clone()), } } fn resolve_hinted(&self, hints: &TypeRefs) -> TypeKind { match self { Vague(TypeRef(idx)) => hints.retrieve_type(*idx).unwrap(), - _ => *self, + _ => self.clone(), } } } @@ -461,11 +462,11 @@ impl Collapsable for TypeKind { (Vague(Number), other) | (other, Vague(Number)) => match other { Vague(Unknown) => Ok(Vague(Number)), Vague(Number) => Ok(Vague(Number)), - I8 | I16 | I32 | I64 | I128 | U8 | U16 | U32 | U64 | U128 => Ok(*other), - _ => Err(ErrorKind::TypesIncompatible(*self, *other)), + I8 | I16 | I32 | I64 | I128 | U8 | U16 | U32 | U64 | U128 => Ok(other.clone()), + _ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())), }, (Vague(Unknown), other) | (other, Vague(Unknown)) => Ok(other.clone()), - _ => Err(ErrorKind::TypesIncompatible(*self, *other)), + _ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())), } } } diff --git a/reid/src/mir/typeinference.rs b/reid/src/mir/typeinference.rs index 1bc6cd4..cee6bfa 100644 --- a/reid/src/mir/typeinference.rs +++ b/reid/src/mir/typeinference.rs @@ -59,7 +59,7 @@ impl FunctionDefinition { match &mut self.kind { FunctionDefinitionKind::Local(block, _) => { - state.scope.return_type_hint = Some(self.return_type); + state.scope.return_type_hint = Some(self.return_type.clone()); let scope_hints = ScopeTypeRefs::from(type_refs); // Infer block return type @@ -91,7 +91,7 @@ impl Block { StmtKind::Let(var, mutable, expr) => { // Get the TypeRef for this variable declaration let mut var_ref = - state.ok(inner_hints.new_var(var.1.clone(), *mutable, var.0), var.2); + state.ok(inner_hints.new_var(var.1.clone(), *mutable, &var.0), var.2); // If ok, update the MIR type to this TypeRef if let Some(var_ref) = &var_ref { @@ -149,7 +149,7 @@ impl Block { // Narow return type to declared type if hard return if kind == ReturnKind::Hard { - if let Some(hint) = state.scope.return_type_hint { + if let Some(hint) = &state.scope.return_type_hint { ret_type_ref.narrow(&mut outer_hints.from_type(&hint).unwrap()); } } @@ -260,6 +260,7 @@ impl Expression { ReturnKind::Soft => Ok(block_ref.1), } } + ExprKind::Index(expression, _) => todo!("type inference for index expression"), } } } diff --git a/reid/src/mir/typerefs.rs b/reid/src/mir/typerefs.rs index cbad7ab..423b21a 100644 --- a/reid/src/mir/typerefs.rs +++ b/reid/src/mir/typerefs.rs @@ -14,7 +14,14 @@ pub struct TypeRef<'scope>(TypeIdRef, &'scope ScopeTypeRefs<'scope>); impl<'scope> TypeRef<'scope> { pub unsafe fn resolve_type(&self) -> TypeKind { - unsafe { *self.1.types.hints.borrow().get_unchecked(*self.0.borrow()) } + unsafe { + self.1 + .types + .hints + .borrow() + .get_unchecked(*self.0.borrow()) + .clone() + } } pub fn narrow(&mut self, other: &TypeRef) -> Option> { @@ -46,15 +53,15 @@ pub struct TypeRefs { } impl TypeRefs { - pub fn new(&self, ty: TypeKind) -> TypeIdRef { + pub fn new(&self, ty: &TypeKind) -> TypeIdRef { let idx = self.hints.borrow().len(); let typecell = Rc::new(RefCell::new(idx)); self.type_refs.borrow_mut().push(typecell.clone()); - self.hints.borrow_mut().push(ty); + self.hints.borrow_mut().push(ty.clone()); typecell } - pub fn find(&self, ty: TypeKind) -> Option { + pub fn find(&self, ty: &TypeKind) -> Option { if ty.known().is_err() { // Only do this for non-vague types that can not be further narrowed // down. @@ -66,7 +73,7 @@ impl TypeRefs { .borrow_mut() .iter() .enumerate() - .find(|(_, t)| **t == ty) + .find(|(_, t)| *t == ty) .map(|(i, _)| i) { Some(Rc::new(RefCell::new(idx))) @@ -89,7 +96,7 @@ impl TypeRefs { pub fn retrieve_type(&self, idx: usize) -> Option { let inner_idx = unsafe { *self.recurse_type_ref(idx).borrow() }; - self.hints.borrow().get(inner_idx).copied() + self.hints.borrow().get(inner_idx).cloned() } } @@ -114,7 +121,7 @@ impl<'outer> ScopeTypeRefs<'outer> { &'outer self, name: String, mutable: bool, - initial_ty: TypeKind, + initial_ty: &TypeKind, ) -> Result, ErrorKind> { if self.variables.borrow().contains_key(&name) { return Err(ErrorKind::VariableAlreadyDefined(name)); @@ -132,12 +139,12 @@ impl<'outer> ScopeTypeRefs<'outer> { let inner_idx = unsafe { *self.types.recurse_type_ref(*idx).borrow() }; self.types.type_refs.borrow().get(inner_idx).cloned()? } - TypeKind::Vague(_) => self.types.new(*ty), + TypeKind::Vague(_) => self.types.new(ty), _ => { - if let Some(ty_ref) = self.types.find(*ty) { + if let Some(ty_ref) = self.types.find(ty) { ty_ref } else { - self.types.new(*ty) + self.types.new(ty) } } }; diff --git a/reid/src/mir/types.rs b/reid/src/mir/types.rs index 5d96293..b01082f 100644 --- a/reid/src/mir/types.rs +++ b/reid/src/mir/types.rs @@ -15,10 +15,11 @@ impl TypeKind { pub fn binop_type(&self, op: &BinaryOperator) -> TypeKind { // TODO make some type of mechanism that allows to binop two values of // differing types.. + // TODO Return None for arrays later match op { - BinaryOperator::Add => *self, - BinaryOperator::Minus => *self, - BinaryOperator::Mult => *self, + BinaryOperator::Add => self.clone(), + BinaryOperator::Minus => self.clone(), + BinaryOperator::Mult => self.clone(), BinaryOperator::And => TypeKind::Bool, BinaryOperator::Cmp(_) => TypeKind::Bool, } @@ -85,6 +86,7 @@ impl ReturnType for Expression { Block(block) => block.return_type(), FunctionCall(fcall) => fcall.return_type(), If(expr) => expr.return_type(), + Index(expression, _) => todo!("return type for index"), } } } @@ -107,7 +109,7 @@ impl ReturnType for IfExpression { } } -impl ReturnType for VariableReference { +impl ReturnType for NamedVariableRef { fn return_type(&self) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> { Ok((ReturnKind::Soft, self.0.clone())) }