Add MIR support for struct types
This commit is contained in:
		
							parent
							
								
									d9a1e8456d
								
							
						
					
					
						commit
						f139a5ad6c
					
				@ -163,6 +163,7 @@ fn main() {
 | 
			
		||||
            name: "test module".to_owned(),
 | 
			
		||||
            imports: vec![],
 | 
			
		||||
            functions: vec![fibonacci, main],
 | 
			
		||||
            typedefs: Vec::new(),
 | 
			
		||||
            path: None,
 | 
			
		||||
            is_main: true,
 | 
			
		||||
        }],
 | 
			
		||||
 | 
			
		||||
@ -72,6 +72,7 @@ impl ast::Module {
 | 
			
		||||
            functions,
 | 
			
		||||
            path: self.path.clone(),
 | 
			
		||||
            is_main: self.is_main,
 | 
			
		||||
            typedefs: todo!("process for typedefs"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -197,7 +198,7 @@ impl ast::Expression {
 | 
			
		||||
            ast::ExpressionKind::Array(expressions) => {
 | 
			
		||||
                mir::ExprKind::Array(expressions.iter().map(|e| e.process()).collect())
 | 
			
		||||
            }
 | 
			
		||||
            ast::ExpressionKind::ArrayIndex(expression, idx) => mir::ExprKind::Index(
 | 
			
		||||
            ast::ExpressionKind::ArrayIndex(expression, idx) => mir::ExprKind::ArrayIndex(
 | 
			
		||||
                Box::new(expression.process()),
 | 
			
		||||
                mir::TypeKind::Vague(mir::VagueType::Unknown),
 | 
			
		||||
                *idx,
 | 
			
		||||
 | 
			
		||||
@ -385,7 +385,7 @@ impl mir::Expression {
 | 
			
		||||
                    None
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            mir::ExprKind::Index(expression, val_t, idx) => {
 | 
			
		||||
            mir::ExprKind::ArrayIndex(expression, val_t, idx) => {
 | 
			
		||||
                let array = expression.codegen(scope)?;
 | 
			
		||||
                let ptr = scope
 | 
			
		||||
                    .block
 | 
			
		||||
@ -428,6 +428,10 @@ impl mir::Expression {
 | 
			
		||||
 | 
			
		||||
                Some(array)
 | 
			
		||||
            }
 | 
			
		||||
            mir::ExprKind::StructIndex(expression, type_kind, _) => {
 | 
			
		||||
                todo!("codegen for struct index")
 | 
			
		||||
            }
 | 
			
		||||
            mir::ExprKind::Struct(_, items) => todo!("codegen for struct expression"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -511,6 +515,7 @@ impl TypeKind {
 | 
			
		||||
            TypeKind::Array(elem_t, _) => Type::Ptr(Box::new(elem_t.get_type())),
 | 
			
		||||
            TypeKind::Void => Type::Void,
 | 
			
		||||
            TypeKind::Vague(_) => panic!("Tried to compile a vague type!"),
 | 
			
		||||
            TypeKind::CustomType(_, custom_type_kind) => todo!("codegen for custom type"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -130,7 +130,7 @@ impl Display for ExprKind {
 | 
			
		||||
            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, elem_ty, idx) => {
 | 
			
		||||
            ExprKind::ArrayIndex(expression, elem_ty, idx) => {
 | 
			
		||||
                Display::fmt(&expression, f)?;
 | 
			
		||||
                write!(f, "<{}>", elem_ty)?;
 | 
			
		||||
                write_index(f, *idx)
 | 
			
		||||
@ -152,6 +152,28 @@ impl Display for ExprKind {
 | 
			
		||||
                }
 | 
			
		||||
                f.write_char(']')
 | 
			
		||||
            }
 | 
			
		||||
            ExprKind::Struct(name, items) => {
 | 
			
		||||
                write!(f, "{} ", name);
 | 
			
		||||
 | 
			
		||||
                f.write_char('{')?;
 | 
			
		||||
                let mut state = Default::default();
 | 
			
		||||
                let mut inner_f = PadAdapter::wrap(f, &mut state);
 | 
			
		||||
                let mut iter = items.iter();
 | 
			
		||||
                if let Some((name, expr)) = iter.next() {
 | 
			
		||||
                    write!(inner_f, "\n{}: {}", name, expr);
 | 
			
		||||
                    while let Some((name, expr)) = iter.next() {
 | 
			
		||||
                        writeln!(inner_f, ",")?;
 | 
			
		||||
                        write!(inner_f, "{}: {}", name, expr);
 | 
			
		||||
                    }
 | 
			
		||||
                    writeln!(inner_f, "")?;
 | 
			
		||||
                }
 | 
			
		||||
                f.write_char('}')
 | 
			
		||||
            }
 | 
			
		||||
            ExprKind::StructIndex(expression, type_kind, name) => {
 | 
			
		||||
                Display::fmt(&expression, f)?;
 | 
			
		||||
                write!(f, "<{}>", type_kind)?;
 | 
			
		||||
                write_access(f, name)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -254,3 +276,8 @@ fn write_index(f: &mut std::fmt::Formatter<'_>, idx: u64) -> std::fmt::Result {
 | 
			
		||||
    Display::fmt(&idx, f)?;
 | 
			
		||||
    f.write_char(']')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn write_access(f: &mut std::fmt::Formatter<'_>, name: &String) -> std::fmt::Result {
 | 
			
		||||
    f.write_char('.')?;
 | 
			
		||||
    Display::fmt(name, f)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
 | 
			
		||||
use std::path::PathBuf;
 | 
			
		||||
 | 
			
		||||
use crate::token_stream::TokenRange;
 | 
			
		||||
use crate::{ast::Type, token_stream::TokenRange};
 | 
			
		||||
 | 
			
		||||
mod display;
 | 
			
		||||
pub mod linker;
 | 
			
		||||
@ -65,6 +65,8 @@ pub enum TypeKind {
 | 
			
		||||
    StringPtr,
 | 
			
		||||
    #[error("[{0}; {1}]")]
 | 
			
		||||
    Array(Box<TypeKind>, u64),
 | 
			
		||||
    #[error("{0} ({1})")]
 | 
			
		||||
    CustomType(String, CustomTypeKind),
 | 
			
		||||
    #[error(transparent)]
 | 
			
		||||
    Vague(#[from] VagueType),
 | 
			
		||||
}
 | 
			
		||||
@ -79,6 +81,14 @@ pub enum VagueType {
 | 
			
		||||
    TypeRef(usize),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
 | 
			
		||||
pub enum CustomTypeKind {
 | 
			
		||||
    #[error("struct({0:?})")]
 | 
			
		||||
    Struct(Vec<TypeKind>),
 | 
			
		||||
    #[error("CustomType")]
 | 
			
		||||
    Unknown,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl TypeKind {
 | 
			
		||||
    pub fn known(&self) -> Result<TypeKind, VagueType> {
 | 
			
		||||
        if let TypeKind::Vague(vague) = self {
 | 
			
		||||
@ -107,6 +117,7 @@ impl TypeKind {
 | 
			
		||||
            TypeKind::U128 => false,
 | 
			
		||||
            TypeKind::StringPtr => false,
 | 
			
		||||
            TypeKind::Array(_, _) => false,
 | 
			
		||||
            TypeKind::CustomType(_, _) => false,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -126,8 +137,9 @@ impl TypeKind {
 | 
			
		||||
            Bool => true,
 | 
			
		||||
            Vague(_) => false,
 | 
			
		||||
            Void => false,
 | 
			
		||||
            TypeKind::StringPtr => false,
 | 
			
		||||
            StringPtr => false,
 | 
			
		||||
            Array(_, _) => false,
 | 
			
		||||
            TypeKind::CustomType(_, _) => false,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -217,8 +229,10 @@ pub struct Import(pub Vec<String>, pub Metadata);
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub enum ExprKind {
 | 
			
		||||
    Variable(NamedVariableRef),
 | 
			
		||||
    Index(Box<Expression>, TypeKind, u64),
 | 
			
		||||
    ArrayIndex(Box<Expression>, TypeKind, u64),
 | 
			
		||||
    StructIndex(Box<Expression>, TypeKind, String),
 | 
			
		||||
    Array(Vec<Expression>),
 | 
			
		||||
    Struct(String, Vec<(String, Expression)>),
 | 
			
		||||
    Literal(Literal),
 | 
			
		||||
    BinOp(BinaryOperator, Box<Expression>, Box<Expression>),
 | 
			
		||||
    FunctionCall(FunctionCall),
 | 
			
		||||
@ -306,11 +320,23 @@ pub enum StmtKind {
 | 
			
		||||
    Expression(Expression),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct TypeDefinition {
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub kind: TypeDefinitionKind,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub enum TypeDefinitionKind {
 | 
			
		||||
    Struct(Vec<(String, Type)>),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct Module {
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub imports: Vec<Import>,
 | 
			
		||||
    pub functions: Vec<FunctionDefinition>,
 | 
			
		||||
    pub typedefs: Vec<TypeDefinition>,
 | 
			
		||||
    pub path: Option<PathBuf>,
 | 
			
		||||
    pub is_main: bool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -427,7 +427,7 @@ impl Expression {
 | 
			
		||||
                Ok((_, ty)) => Ok(ty),
 | 
			
		||||
                Err(e) => Err(e),
 | 
			
		||||
            },
 | 
			
		||||
            ExprKind::Index(expression, elem_ty, idx) => {
 | 
			
		||||
            ExprKind::ArrayIndex(expression, elem_ty, idx) => {
 | 
			
		||||
                // Try to unwrap hint type from array if possible
 | 
			
		||||
                let hint_t = hint_t.map(|t| match t {
 | 
			
		||||
                    TypeKind::Array(type_kind, _) => &type_kind,
 | 
			
		||||
@ -487,6 +487,10 @@ impl Expression {
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            ExprKind::StructIndex(expression, type_kind, _) => {
 | 
			
		||||
                todo!("typechecking for struct index")
 | 
			
		||||
            }
 | 
			
		||||
            ExprKind::Struct(_, items) => todo!("typechecking for struct expression"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -283,7 +283,7 @@ impl Expression {
 | 
			
		||||
                    ReturnKind::Soft => Ok(block_ref.1),
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            ExprKind::Index(expression, index_ty, _) => {
 | 
			
		||||
            ExprKind::ArrayIndex(expression, index_ty, _) => {
 | 
			
		||||
                let expr_ty = expression.infer_types(state, type_refs)?;
 | 
			
		||||
 | 
			
		||||
                // Check that the resolved type is at least an array, no
 | 
			
		||||
@ -336,6 +336,10 @@ impl Expression {
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            ExprKind::StructIndex(expression, type_kind, _) => {
 | 
			
		||||
                todo!("type inference for struct indexes")
 | 
			
		||||
            }
 | 
			
		||||
            ExprKind::Struct(_, items) => todo!("type inference for struct expression"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
use crate::util::try_all;
 | 
			
		||||
 | 
			
		||||
use super::*;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
@ -87,7 +89,7 @@ impl ReturnType for Expression {
 | 
			
		||||
            Block(block) => block.return_type(),
 | 
			
		||||
            FunctionCall(fcall) => fcall.return_type(),
 | 
			
		||||
            If(expr) => expr.return_type(),
 | 
			
		||||
            Index(expression, _, _) => {
 | 
			
		||||
            ArrayIndex(expression, _, _) => {
 | 
			
		||||
                let expr_type = expression.return_type()?;
 | 
			
		||||
                if let (_, TypeKind::Array(elem_ty, _)) = expr_type {
 | 
			
		||||
                    Ok((ReturnKind::Soft, *elem_ty))
 | 
			
		||||
@ -106,6 +108,18 @@ impl ReturnType for Expression {
 | 
			
		||||
                    TypeKind::Array(Box::new(first.1), expressions.len() as u64),
 | 
			
		||||
                ))
 | 
			
		||||
            }
 | 
			
		||||
            StructIndex(expression, type_kind, _) => todo!("todo return type for struct index"),
 | 
			
		||||
            Struct(name, items) => {
 | 
			
		||||
                let f_types = try_all(items.iter().map(|e| e.1.return_type()).collect())
 | 
			
		||||
                    .map_err(|e| unsafe { e.get_unchecked(0).clone() })?
 | 
			
		||||
                    .iter()
 | 
			
		||||
                    .map(|r| r.1.clone())
 | 
			
		||||
                    .collect();
 | 
			
		||||
                Ok((
 | 
			
		||||
                    ReturnKind::Soft,
 | 
			
		||||
                    TypeKind::CustomType(name.clone(), CustomTypeKind::Struct(f_types)),
 | 
			
		||||
                ))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user