top and bottom types

This commit is contained in:
Janis 2025-07-14 18:09:23 +02:00
parent bbaa9cb671
commit adfc2c27f8
4 changed files with 46 additions and 7 deletions

View file

@ -22,6 +22,12 @@ pub enum SimpleType {
USize, USize,
ISize, ISize,
ComptimeInt, ComptimeInt,
/// Top type: this is the supertype of all types, and any value can coerce into it.
/// Although Rust's `()` is not a top type, it can be thought of as a top type in some contexts.
Top,
/// Bottom type: this is the subtype of all types, and it can coerce into a value of any type.
/// Akin to Rust's `!`.
Bottom,
} }
impl From<u8> for SimpleType { impl From<u8> for SimpleType {
@ -52,6 +58,8 @@ impl Display for SimpleType {
SimpleType::USize => "usize", SimpleType::USize => "usize",
SimpleType::ISize => "isize", SimpleType::ISize => "isize",
SimpleType::ComptimeInt => "comptime_int", SimpleType::ComptimeInt => "comptime_int",
SimpleType::Top => "",
SimpleType::Bottom => "",
} }
) )
} }
@ -527,6 +535,8 @@ macro_rules! static_keys {
} }
static_keys!( static_keys!(
TOP => Key::SimpleType {ty: SimpleType::Top,},
BOTTOM => Key::SimpleType {ty: SimpleType::Bottom,},
BOOL => Key::SimpleType {ty: SimpleType::Bool,}, BOOL => Key::SimpleType {ty: SimpleType::Bool,},
F32 => Key::SimpleType {ty: SimpleType::F32,}, F32 => Key::SimpleType {ty: SimpleType::F32,},
F64 => Key::SimpleType {ty: SimpleType::F64,}, F64 => Key::SimpleType {ty: SimpleType::F64,},
@ -632,6 +642,18 @@ impl InternPool {
pub fn get_i64_type(&self) -> Index { pub fn get_i64_type(&self) -> Index {
self.get_assume_present(&Key::SIntType { bit_width: 64 }) self.get_assume_present(&Key::SIntType { bit_width: 64 })
} }
pub fn get_top_type(&self) -> Index {
self.get_assume_present(&Key::SimpleType {
ty: SimpleType::Top,
})
}
pub fn get_bottom_type(&self) -> Index {
self.get_assume_present(&Key::SimpleType {
ty: SimpleType::Bottom,
})
}
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -740,8 +762,8 @@ impl InternPool {
todo!("void can't be turned into a mir type") todo!("void can't be turned into a mir type")
} }
SimpleType::ISize | SimpleType::USize => Type::QWord, SimpleType::ISize | SimpleType::USize => Type::QWord,
SimpleType::ComptimeInt => { SimpleType::Top | SimpleType::Bottom | SimpleType::ComptimeInt => {
panic!("comptime int can't be turned into a mir type") panic!("{ty} can't be turned into a mir type")
} }
}, },
Key::ArrayType { .. } => { Key::ArrayType { .. } => {
@ -816,6 +838,9 @@ impl InternPool {
}, },
SimpleType::USize => ptr_size, SimpleType::USize => ptr_size,
SimpleType::ISize => ptr_size, SimpleType::ISize => ptr_size,
SimpleType::Top | SimpleType::Bottom => {
panic!("top and bottom types are not sized")
}
SimpleType::ComptimeInt => panic!("comptime int is unsized"), SimpleType::ComptimeInt => panic!("comptime int is unsized"),
}, },
Key::PointerType { .. } => ptr_size, Key::PointerType { .. } => ptr_size,
@ -953,6 +978,9 @@ impl InternPool {
SimpleType::USize => Type::Integer(IntegralType::new(false, pointer_bits)), SimpleType::USize => Type::Integer(IntegralType::new(false, pointer_bits)),
SimpleType::ISize => Type::Integer(IntegralType::new(true, pointer_bits)), SimpleType::ISize => Type::Integer(IntegralType::new(true, pointer_bits)),
SimpleType::ComptimeInt => Type::comptime_number(), SimpleType::ComptimeInt => Type::comptime_number(),
SimpleType::Top | SimpleType::Bottom => {
panic!("top and bottom types cannot be converted to ast1 types")
}
}, },
Key::PointerType { pointee, flags } => Type::Pointer { Key::PointerType { pointee, flags } => Type::Pointer {
constness: flags.is_const, constness: flags.is_const,

View file

@ -1,11 +1,12 @@
#![allow(unused_variables)]
use std::collections::HashMap; use std::collections::HashMap;
use crate::{ use crate::{
ast2::{ ast2::{
intern::{self, AMD64_POINTER_TYPE_INFO},
Index, Index,
intern::{self, AMD64_POINTER_TYPE_INFO},
}, },
triples::{self, Inst, IR}, triples::{self, IR, Inst},
}; };
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
@ -15,9 +16,9 @@ enum Error {
} }
use super::{ use super::{
Ast, Data, PlaceOrValue, Tag, TypeCache,
intern::InternPoolWrapper as InternPool, intern::InternPoolWrapper as InternPool,
visitor::{AstExt, AstVisitorTrait}, visitor::{AstExt, AstVisitorTrait},
Ast, Data, PlaceOrValue, Tag, TypeCache,
}; };
struct IrBuilder { struct IrBuilder {

View file

@ -5,7 +5,7 @@ use std::{
fmt::{Debug, Display}, fmt::{Debug, Display},
}; };
use intern::{InternPoolWrapper as InternPool, PointerFlags, StructFlags, AMD64_POINTER_TYPE_INFO}; use intern::{AMD64_POINTER_TYPE_INFO, InternPoolWrapper as InternPool, PointerFlags, StructFlags};
use num_bigint::BigInt; use num_bigint::BigInt;
use crate::{ use crate::{
@ -2251,6 +2251,9 @@ where
}; };
ComptimeNumber::Integral(ComptimeInt::Comptime(bigint)) ComptimeNumber::Integral(ComptimeInt::Comptime(bigint))
} }
intern::SimpleType::Top | intern::SimpleType::Bottom => {
unreachable!()
}
}, },
_ => { _ => {
unreachable!() unreachable!()

View file

@ -1,10 +1,17 @@
//! Type checking for the AST.
//! This module implements a bi-unification type-checking algorithm to infer
//! types for each node in the AST.
// Visitor pattern has lots of unused arguments
#![allow(unused_variables)]
use crate::variant; use crate::variant;
use super::{ use super::{
Ast, Data, Index, Tag,
intern::{self}, intern::{self},
tag::{AstNode, AstNodeExt}, tag::{AstNode, AstNodeExt},
visitor::{AstExt, AstVisitorTrait}, visitor::{AstExt, AstVisitorTrait},
Ast, Data, Index, Tag,
}; };
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]