Make mir array implementation halfway, compiling but not working yet
This commit is contained in:
		
							parent
							
								
									bf8baa7cd4
								
							
						
					
					
						commit
						587ab8afd5
					
				@ -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(),
 | 
			
		||||
 | 
			
		||||
@ -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<VariableReference>, u64),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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<Self, Error> {
 | 
			
		||||
        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)
 | 
			
		||||
 | 
			
		||||
@ -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<ast::ReturnType> 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<ast::TypeKind> 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)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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<InstructionValue> {
 | 
			
		||||
        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"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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(']')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -32,7 +32,7 @@ impl From<TokenRange> 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<TypeKind>, 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<Expression>, u64),
 | 
			
		||||
    Literal(Literal),
 | 
			
		||||
    BinOp(BinaryOperator, Box<Expression>, Box<Expression>),
 | 
			
		||||
    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<IndexedVariableReference>, 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),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
                        },
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
@ -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<ErrorKind>,
 | 
			
		||||
        hints: &TypeRefs,
 | 
			
		||||
        hint_t: Option<TypeKind>,
 | 
			
		||||
        hint_t: Option<&TypeKind>,
 | 
			
		||||
    ) -> Result<TypeKind, ErrorKind> {
 | 
			
		||||
        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<ErrorKind>,
 | 
			
		||||
        hints: &TypeRefs,
 | 
			
		||||
        hint_t: Option<TypeKind>,
 | 
			
		||||
        hint_t: Option<&TypeKind>,
 | 
			
		||||
    ) -> Result<TypeKind, ErrorKind> {
 | 
			
		||||
        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<TypeKind>) -> Result<Self, ErrorKind> {
 | 
			
		||||
        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<TypeKind, ErrorKind> {
 | 
			
		||||
        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())),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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<TypeRef<'scope>> {
 | 
			
		||||
@ -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<TypeIdRef> {
 | 
			
		||||
    pub fn find(&self, ty: &TypeKind) -> Option<TypeIdRef> {
 | 
			
		||||
        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<TypeKind> {
 | 
			
		||||
        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<TypeRef<'outer>, 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)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
@ -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()))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user