split ast tag arrays

This commit is contained in:
Janis 2025-03-01 19:22:31 +01:00
parent 43c828d96f
commit 379769bc59
8 changed files with 1379 additions and 2961 deletions

View file

@ -1,9 +1,6 @@
use std::num::NonZero; use std::num::NonZero;
use crate::{ use crate::ast2::intern;
ast2::intern,
string_table::{self, ImmOrIndex},
};
pub type Node = NonZero<u32>; pub type Node = NonZero<u32>;
@ -298,21 +295,14 @@ impl core::fmt::Display for Type {
Type::Integer(t) => t.fmt(f), Type::Integer(t) => t.fmt(f),
Type::Floating(t) => t.fmt(f), Type::Floating(t) => t.fmt(f),
Type::Pointer { constness, pointee } => { Type::Pointer { constness, pointee } => {
write!( write!(f, "*{}{}", if *constness { "const " } else { "" }, pointee)
f,
"*{}{}",
if *constness { "const " } else { "" },
pointee
)
} }
Type::Fn { Type::Fn {
parameter_types, parameter_types,
return_type, return_type,
} => { } => {
write!(f, "fn (")?; write!(f, "fn (")?;
for param in for param in parameter_types.iter().map(|p| Some(p)).intersperse(None) {
parameter_types.iter().map(|p| Some(p)).intersperse(None)
{
match param { match param {
Some(param) => param.fmt(f)?, Some(param) => param.fmt(f)?,
None => write!(f, ", ")?, None => write!(f, ", ")?,
@ -351,13 +341,8 @@ impl Type {
parameter_types: r_parameter_types, parameter_types: r_parameter_types,
return_type: r_return_type, return_type: r_return_type,
}, },
) => { ) => l_parameter_types == r_parameter_types && l_return_type == r_return_type,
l_parameter_types == r_parameter_types _ => core::mem::discriminant(self) == core::mem::discriminant(other),
&& l_return_type == r_return_type
}
_ => {
core::mem::discriminant(self) == core::mem::discriminant(other)
}
} }
} }
pub fn as_primitive_type(&self) -> Option<PrimitiveType> { pub fn as_primitive_type(&self) -> Option<PrimitiveType> {
@ -476,10 +461,9 @@ impl Type {
pub fn can_add_sub(&self) -> bool { pub fn can_add_sub(&self) -> bool {
match self { match self {
Type::ComptimeNumber Type::ComptimeNumber | Type::Pointer { .. } | Type::Floating(_) | Type::Integer(_) => {
| Type::Pointer { .. } true
| Type::Floating(_) }
| Type::Integer(_) => true,
_ => false, _ => false,
} }
} }
@ -501,10 +485,9 @@ impl Type {
} }
pub fn can_cmp(&self) -> bool { pub fn can_cmp(&self) -> bool {
match self { match self {
Type::ComptimeNumber Type::ComptimeNumber | Type::Pointer { .. } | Type::Floating(_) | Type::Integer(_) => {
| Type::Pointer { .. } true
| Type::Floating(_) }
| Type::Integer(_) => true,
_ => false, _ => false,
} }
} }
@ -613,12 +596,7 @@ pub mod tree_visitor {
pub fn new_range(start: Node, end: Node, pre: F1, post: F2) -> Self { pub fn new_range(start: Node, end: Node, pre: F1, post: F2) -> Self {
Self::new_inner(start, End::Exclusive(end), pre, post) Self::new_inner(start, End::Exclusive(end), pre, post)
} }
pub fn new_range_inclusive( pub fn new_range_inclusive(start: Node, end: Node, pre: F1, post: F2) -> Self {
start: Node,
end: Node,
pre: F1,
post: F2,
) -> Self {
Self::new_inner(start, End::Inclusive(end), pre, post) Self::new_inner(start, End::Inclusive(end), pre, post)
} }
pub fn new_seek(tree: &Tree, start: Node, pre: F1, post: F2) -> Self { pub fn new_seek(tree: &Tree, start: Node, pre: F1, post: F2) -> Self {
@ -717,10 +695,7 @@ pub mod tree_visitor {
} }
/// short-circuits on the first E /// short-circuits on the first E
pub fn visit_ok<T, E>( pub fn visit_ok<T, E>(mut self, tree: &Tree) -> core::result::Result<T, E>
mut self,
tree: &Tree,
) -> core::result::Result<T, E>
where where
F1: FnMut(&Tree, Node) -> core::result::Result<T, E>, F1: FnMut(&Tree, Node) -> core::result::Result<T, E>,
F2: FnMut(&Tree, Node) -> core::result::Result<T, E>, F2: FnMut(&Tree, Node) -> core::result::Result<T, E>,

View file

@ -180,19 +180,14 @@ impl Display for KeyDisplay<'_> {
pointee, pointee,
flags, flags,
length, length,
} => write!( } => write!(f, "[{flags}{}; {length}]", self.ip.display_key(pointee))?,
f,
"[{flags}{}; {length}]",
self.ip.display_key(pointee)
)?,
Key::FunctionType { Key::FunctionType {
return_type, return_type,
ref parameters, ref parameters,
} => { } => {
write!(f, "fn (")?; write!(f, "fn (")?;
let mut iter = let mut iter = parameters.iter().map(|&ty| self.ip.display_key(ty));
parameters.iter().map(|&ty| self.ip.display_key(ty));
let Some(next) = iter.next() else { let Some(next) = iter.next() else {
return Ok(()); return Ok(());
}; };
@ -209,7 +204,10 @@ impl Display for KeyDisplay<'_> {
packed, packed,
c_like, c_like,
ref fields, ref fields,
} => todo!(), } => {
_ = (decl, name, packed, c_like, fields);
todo!()
}
Key::TrueValue => write!(f, "true")?, Key::TrueValue => write!(f, "true")?,
Key::FalseValue => write!(f, "false")?, Key::FalseValue => write!(f, "false")?,
} }
@ -293,9 +291,7 @@ impl PointerFlags {
} }
pub fn pack(self) -> u8 { pub fn pack(self) -> u8 {
(self.volatile as u8) << 0 (self.volatile as u8) << 0 | (self.is_const as u8) << 1 | (self.noalias as u8) << 2
| (self.is_const as u8) << 1
| (self.noalias as u8) << 2
} }
pub fn unpack(packed: u8) -> Self { pub fn unpack(packed: u8) -> Self {
Self { Self {
@ -325,9 +321,7 @@ impl StructFlags {
} }
pub fn pack(self) -> u32 { pub fn pack(self) -> u32 {
assert!(self.num_fields < (1 << 30)); assert!(self.num_fields < (1 << 30));
(self.packed as u32) << 31 (self.packed as u32) << 31 | (self.c_like as u32) << 30 | self.num_fields & Self::MASK
| (self.c_like as u32) << 30
| self.num_fields & Self::MASK
} }
pub fn unpack(packed: u32) -> Self { pub fn unpack(packed: u32) -> Self {
Self { Self {
@ -648,11 +642,7 @@ impl InternPool {
} }
} }
pub fn to_mir_type( pub fn to_mir_type(&self, index: Index, _ptr_size: TypeInfo) -> crate::mir::Type {
&self,
index: Index,
_ptr_size: TypeInfo,
) -> crate::mir::Type {
use crate::mir::Type; use crate::mir::Type;
match self.get_key(index) { match self.get_key(index) {
Key::UIntType { bit_width: bits } => { Key::UIntType { bit_width: bits } => {
@ -765,8 +755,7 @@ impl InternPool {
Key::FunctionType { .. } => ptr_size, Key::FunctionType { .. } => ptr_size,
Key::StructType { packed, fields, .. } => { Key::StructType { packed, fields, .. } => {
// TODO: c-like layout // TODO: c-like layout
let (size, align) = let (size, align) = fields.iter().fold((0, 0), |(size, align), (_name, ty)| {
fields.iter().fold((0, 0), |(size, align), (_name, ty)| {
let field_size = self.size_of_type(*ty, ptr_size); let field_size = self.size_of_type(*ty, ptr_size);
let size = size + field_size.bitsize; let size = size + field_size.bitsize;
@ -791,11 +780,7 @@ impl InternPool {
} }
} }
pub fn insert_ast1_type( pub fn insert_ast1_type(&mut self, pointer_bits: u16, ty: &crate::ast::Type) -> Index {
&mut self,
pointer_bits: u16,
ty: &crate::ast::Type,
) -> Index {
match ty { match ty {
crate::ast::Type::Bool => self.get_bool_type(), crate::ast::Type::Bool => self.get_bool_type(),
crate::ast::Type::ComptimeNumber => self.get_comptime_int_type(), crate::ast::Type::ComptimeNumber => self.get_comptime_int_type(),
@ -806,12 +791,8 @@ impl InternPool {
Key::UIntType { bit_width: i.bits } Key::UIntType { bit_width: i.bits }
} }
}), }),
crate::ast::Type::Floating(crate::ast::FloatingType::Binary32) => { crate::ast::Type::Floating(crate::ast::FloatingType::Binary32) => self.get_f32_type(),
self.get_f32_type() crate::ast::Type::Floating(crate::ast::FloatingType::Binary64) => self.get_f64_type(),
}
crate::ast::Type::Floating(crate::ast::FloatingType::Binary64) => {
self.get_f64_type()
}
crate::ast::Type::Pointer { constness, pointee } => { crate::ast::Type::Pointer { constness, pointee } => {
let pointee = self.insert_ast1_type(pointer_bits, &pointee); let pointee = self.insert_ast1_type(pointer_bits, &pointee);
self.get_or_insert(Key::PointerType { self.get_or_insert(Key::PointerType {
@ -827,8 +808,7 @@ impl InternPool {
.iter() .iter()
.map(|ty| self.insert_ast1_type(pointer_bits, ty)) .map(|ty| self.insert_ast1_type(pointer_bits, ty))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let return_type = let return_type = self.from_ast1_type(pointer_bits, &return_type);
self.from_ast1_type(pointer_bits, &return_type);
self.get_or_insert(Key::FunctionType { self.get_or_insert(Key::FunctionType {
return_type, return_type,
parameters, parameters,
@ -841,11 +821,7 @@ impl InternPool {
} }
} }
pub fn from_ast1_type( pub fn from_ast1_type(&self, pointer_bits: u16, ty: &crate::ast::Type) -> Index {
&self,
pointer_bits: u16,
ty: &crate::ast::Type,
) -> Index {
match ty { match ty {
crate::ast::Type::Bool => self.get_bool_type(), crate::ast::Type::Bool => self.get_bool_type(),
crate::ast::Type::ComptimeNumber => self.get_comptime_int_type(), crate::ast::Type::ComptimeNumber => self.get_comptime_int_type(),
@ -856,12 +832,8 @@ impl InternPool {
Key::UIntType { bit_width: i.bits } Key::UIntType { bit_width: i.bits }
} }
}), }),
crate::ast::Type::Floating(crate::ast::FloatingType::Binary32) => { crate::ast::Type::Floating(crate::ast::FloatingType::Binary32) => self.get_f32_type(),
self.get_f32_type() crate::ast::Type::Floating(crate::ast::FloatingType::Binary64) => self.get_f64_type(),
}
crate::ast::Type::Floating(crate::ast::FloatingType::Binary64) => {
self.get_f64_type()
}
crate::ast::Type::Pointer { constness, pointee } => { crate::ast::Type::Pointer { constness, pointee } => {
let pointee = self.from_ast1_type(pointer_bits, &pointee); let pointee = self.from_ast1_type(pointer_bits, &pointee);
self.get_assume_present(&Key::PointerType { self.get_assume_present(&Key::PointerType {
@ -877,8 +849,7 @@ impl InternPool {
.iter() .iter()
.map(|ty| self.from_ast1_type(pointer_bits, ty)) .map(|ty| self.from_ast1_type(pointer_bits, ty))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let return_type = let return_type = self.from_ast1_type(pointer_bits, &return_type);
self.from_ast1_type(pointer_bits, &return_type);
self.get_assume_present(&Key::FunctionType { self.get_assume_present(&Key::FunctionType {
return_type, return_type,
parameters, parameters,
@ -891,34 +862,18 @@ impl InternPool {
} }
} }
pub fn as_ast1_type( pub fn as_ast1_type(&self, pointer_bits: u16, index: Index) -> crate::ast::Type {
&self,
pointer_bits: u16,
index: Index,
) -> crate::ast::Type {
use crate::ast::Type; use crate::ast::Type;
match self.get_key(index) { match self.get_key(index) {
Key::UIntType { bit_width: bits } => { Key::UIntType { bit_width: bits } => Type::Integer(IntegralType::new(false, bits)),
Type::Integer(IntegralType::new(false, bits)) Key::SIntType { bit_width: bits } => Type::Integer(IntegralType::new(true, bits)),
}
Key::SIntType { bit_width: bits } => {
Type::Integer(IntegralType::new(true, bits))
}
Key::SimpleType { ty } => match ty { Key::SimpleType { ty } => match ty {
SimpleType::F32 => { SimpleType::F32 => Type::Floating(crate::ast::FloatingType::Binary32),
Type::Floating(crate::ast::FloatingType::Binary32) SimpleType::F64 => Type::Floating(crate::ast::FloatingType::Binary64),
}
SimpleType::F64 => {
Type::Floating(crate::ast::FloatingType::Binary64)
}
SimpleType::Bool => Type::Bool, SimpleType::Bool => Type::Bool,
SimpleType::Void => Type::Void, SimpleType::Void => Type::Void,
SimpleType::USize => { SimpleType::USize => Type::Integer(IntegralType::new(false, pointer_bits)),
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(),
}, },
Key::PointerType { pointee, flags } => Type::Pointer { Key::PointerType { pointee, flags } => Type::Pointer {
@ -933,9 +888,7 @@ impl InternPool {
.into_iter() .into_iter()
.map(|i| self.as_ast1_type(pointer_bits, i)) .map(|i| self.as_ast1_type(pointer_bits, i))
.collect(), .collect(),
return_type: Box::new( return_type: Box::new(self.as_ast1_type(pointer_bits, return_type)),
self.as_ast1_type(pointer_bits, return_type),
),
}, },
_ => unimplemented!(), _ => unimplemented!(),
} }
@ -1008,12 +961,8 @@ impl InternPool {
let words_idx = self.extend_words([start, len]); let words_idx = self.extend_words([start, len]);
self.create_item(Tag::String, words_idx) self.create_item(Tag::String, words_idx)
} }
Key::SIntSmall { bits } => { Key::SIntSmall { bits } => self.create_item(Tag::SIntSmall, bits as u32),
self.create_item(Tag::SIntSmall, bits as u32) Key::UIntSmall { bits } => self.create_item(Tag::UIntSmall, bits as u32),
}
Key::UIntSmall { bits } => {
self.create_item(Tag::UIntSmall, bits as u32)
}
Key::F32 { bits } => self.create_item(Tag::F32, bits as u32), Key::F32 { bits } => self.create_item(Tag::F32, bits as u32),
Key::F64 { bits } => { Key::F64 { bits } => {
let (lo, hi) = into_lo_hi_dwords(bits as u64); let (lo, hi) = into_lo_hi_dwords(bits as u64);
@ -1043,19 +992,12 @@ impl InternPool {
self.create_item(Tag::NegativeInt, i) self.create_item(Tag::NegativeInt, i)
} }
Key::UIntType { bit_width: bits } => { Key::UIntType { bit_width: bits } => self.create_item(Tag::UIntType, bits as u32),
self.create_item(Tag::UIntType, bits as u32) Key::SIntType { bit_width: bits } => self.create_item(Tag::SIntType, bits as u32),
} Key::SimpleType { ty } => self.create_item(Tag::SimpleType, ty as u8 as u32),
Key::SIntType { bit_width: bits } => {
self.create_item(Tag::SIntType, bits as u32)
}
Key::SimpleType { ty } => {
self.create_item(Tag::SimpleType, ty as u8 as u32)
}
Key::PointerType { pointee, flags } => { Key::PointerType { pointee, flags } => {
let flags = flags.pack(); let flags = flags.pack();
let i = let i = self.extend_words([pointee.index() as u32, flags as u32]);
self.extend_words([pointee.index() as u32, flags as u32]);
self.create_item(Tag::PointerType, i) self.create_item(Tag::PointerType, i)
} }
Key::ArrayType { Key::ArrayType {
@ -1064,11 +1006,7 @@ impl InternPool {
length, length,
} => { } => {
let flags = flags.pack(); let flags = flags.pack();
let i = self.extend_words([ let i = self.extend_words([pointee.index() as u32, flags as u32, length]);
pointee.index() as u32,
flags as u32,
length,
]);
self.create_item(Tag::ArrayType, i) self.create_item(Tag::ArrayType, i)
} }
Key::StructType { Key::StructType {
@ -1078,15 +1016,8 @@ impl InternPool {
c_like, c_like,
fields, fields,
} => { } => {
let flags = let flags = StructFlags::new(packed, c_like, fields.len() as u32).pack();
StructFlags::new(packed, c_like, fields.len() as u32) let i = self.extend_words([name.into_u32(), decl.into_u32(), flags, u32::MAX]);
.pack();
let i = self.extend_words([
name.into_u32(),
decl.into_u32(),
flags,
u32::MAX,
]);
if !fields.is_empty() { if !fields.is_empty() {
let fields_offset = self.extend_words( let fields_offset = self.extend_words(
fields fields
@ -1109,9 +1040,7 @@ impl InternPool {
let start = self.push_word(info.pack()); let start = self.push_word(info.pack());
self.extend_words([return_type.into_u32()]); self.extend_words([return_type.into_u32()]);
_ = self.extend_words( _ = self.extend_words(parameters.into_iter().map(|i| i.index() as u32));
parameters.into_iter().map(|i| i.index() as u32),
);
self.create_item(Tag::FunctionType, start) self.create_item(Tag::FunctionType, start)
} }
@ -1150,9 +1079,7 @@ impl InternPool {
let start = self.words[item.idx()]; let start = self.words[item.idx()];
let len = self.words[item.idx() + 1]; let len = self.words[item.idx() + 1];
let str = unsafe { let str = unsafe {
core::str::from_utf8_unchecked( core::str::from_utf8_unchecked(&self.strings[start as usize..][..len as usize])
&self.strings[start as usize..][..len as usize],
)
}; };
Key::String { str } Key::String { str }
} }
@ -1167,24 +1094,18 @@ impl InternPool {
}, },
Tag::F64 => { Tag::F64 => {
let idx = item.idx(); let idx = item.idx();
let bits = let bits = from_lo_hi_dwords(self.words[idx], self.words[idx + 1]);
from_lo_hi_dwords(self.words[idx], self.words[idx + 1]);
Key::F64 { Key::F64 {
bits: f64::from_le_bytes(bits.to_le_bytes()), bits: f64::from_le_bytes(bits.to_le_bytes()),
} }
} }
Tag::SInt64 => { Tag::SInt64 => {
let bits = from_lo_hi_dwords( let bits =
self.words[item.idx()], from_lo_hi_dwords(self.words[item.idx()], self.words[item.idx() + 1]) as i64;
self.words[item.idx() + 1],
) as i64;
Key::SInt64 { bits } Key::SInt64 { bits }
} }
Tag::UInt64 => { Tag::UInt64 => {
let bits = from_lo_hi_dwords( let bits = from_lo_hi_dwords(self.words[item.idx()], self.words[item.idx() + 1]);
self.words[item.idx()],
self.words[item.idx() + 1],
);
Key::UInt64 { bits } Key::UInt64 { bits }
} }
Tag::NegativeInt => { Tag::NegativeInt => {
@ -1218,15 +1139,13 @@ impl InternPool {
} }
Tag::PointerType => { Tag::PointerType => {
let pointee = Index::new(self.words[item.idx()]); let pointee = Index::new(self.words[item.idx()]);
let flags = let flags = PointerFlags::unpack(self.words[item.idx() + 1] as u8);
PointerFlags::unpack(self.words[item.idx() + 1] as u8);
Key::PointerType { pointee, flags } Key::PointerType { pointee, flags }
} }
Tag::ArrayType => { Tag::ArrayType => {
let pointee = Index::new(self.words[item.idx()]); let pointee = Index::new(self.words[item.idx()]);
let flags = let flags = PointerFlags::unpack(self.words[item.idx() + 1] as u8);
PointerFlags::unpack(self.words[item.idx() + 1] as u8);
let length = self.words[item.idx() + 2]; let length = self.words[item.idx() + 2];
Key::ArrayType { Key::ArrayType {
@ -1237,12 +1156,11 @@ impl InternPool {
} }
Tag::StructType => { Tag::StructType => {
let name = Index::new(self.words[item.idx()]); let name = Index::new(self.words[item.idx()]);
let decl = super::Index::new(self.words[item.idx() + 1]); let decl = super::Index::from_u32(self.words[item.idx() + 1]).unwrap();
let flags = StructFlags::unpack(self.words[item.idx() + 2]); let flags = StructFlags::unpack(self.words[item.idx() + 2]);
let fields = if flags.num_fields != 0 { let fields = if flags.num_fields != 0 {
let fields_offset = self.words[item.idx() + 3] as usize; let fields_offset = self.words[item.idx() + 3] as usize;
let fields_end = let fields_end = fields_offset + flags.num_fields as usize * 2;
fields_offset + flags.num_fields as usize * 2;
self.words[fields_offset..fields_end] self.words[fields_offset..fields_end]
.iter() .iter()
@ -1322,9 +1240,7 @@ impl InternPool {
pub fn get_unsigned_integer(&mut self, value: u64) -> Index { pub fn get_unsigned_integer(&mut self, value: u64) -> Index {
let key = match value { let key = match value {
_ if value <= u32::MAX as u64 => { _ if value <= u32::MAX as u64 => Key::UIntSmall { bits: value as u32 },
Key::UIntSmall { bits: value as u32 }
}
_ => Key::UInt64 { bits: value as u64 }, _ => Key::UInt64 { bits: value as u64 },
}; };
@ -1381,11 +1297,7 @@ impl InternPool {
}) })
} }
pub fn get_pointer_type( pub fn get_pointer_type(&mut self, pointee: Index, flags: Option<PointerFlags>) -> Index {
&mut self,
pointee: Index,
flags: Option<PointerFlags>,
) -> Index {
let key = Key::PointerType { let key = Key::PointerType {
pointee, pointee,
flags: flags.unwrap_or_default(), flags: flags.unwrap_or_default(),
@ -1405,9 +1317,7 @@ impl InternPool {
) )
} }
pub fn insert_or_replace_struct_type< pub fn insert_or_replace_struct_type<I: IntoIterator<Item = (Index, Index)>>(
I: IntoIterator<Item = (Index, Index)>,
>(
&mut self, &mut self,
name: Index, name: Index,
decl: super::Index, decl: super::Index,
@ -1422,8 +1332,7 @@ impl InternPool {
c_like, c_like,
fields: vec![], fields: vec![],
}; };
if let Some(i) = self.try_get_index(&key).and_then(|i| self.get_item(i)) if let Some(i) = self.try_get_index(&key).and_then(|i| self.get_item(i)) {
{
let fields_offset = self.extend_words( let fields_offset = self.extend_words(
fields fields
.into_iter() .into_iter()
@ -1439,11 +1348,7 @@ impl InternPool {
self.get_or_insert(key) self.get_or_insert(key)
} }
pub fn get_struct_type( pub fn get_struct_type(&mut self, name: Index, decl: super::Index) -> Index {
&mut self,
name: Index,
decl: super::Index,
) -> Index {
let key = Key::StructType { let key = Key::StructType {
name, name,
decl, decl,
@ -1453,11 +1358,7 @@ impl InternPool {
}; };
self.get_or_insert(key) self.get_or_insert(key)
} }
pub fn try_get_struct_type( pub fn try_get_struct_type(&self, name: Index, decl: super::Index) -> Option<Index> {
&self,
name: Index,
decl: super::Index,
) -> Option<Index> {
self.try_get_index(&Key::StructType { self.try_get_index(&Key::StructType {
name, name,
decl, decl,

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,7 @@
use std::{io::Read, path::PathBuf, sync::Arc}; use std::{io::Read, path::PathBuf};
use clap::Command; use clap::Command;
use compiler::{ use compiler::{
ast2::intern::InternPool,
lexer::Tokenizer, lexer::Tokenizer,
parser::Tree, parser::Tree,
triples::{MirBuilder, IR}, triples::{MirBuilder, IR},
@ -29,8 +28,7 @@ fn main() {
.subcommands([ .subcommands([
Command::new("ast").about("output AST."), Command::new("ast").about("output AST."),
Command::new("ast2").about("output AST."), Command::new("ast2").about("output AST."),
Command::new("mir") Command::new("mir").about("output machine-level intermediate representation."),
.about("output machine-level intermediate representation."),
Command::new("ir").about("output intermediate representation."), Command::new("ir").about("output intermediate representation."),
Command::new("asm").about("output x86-64 assembly (intel syntax)."), Command::new("asm").about("output x86-64 assembly (intel syntax)."),
]); ]);
@ -85,11 +83,7 @@ fn main() {
} = mir; } = mir;
for (name, mir) in functions { for (name, mir) in functions {
println!( println!("{}:\n{}", strings.get_str(name), mir.display(&strings));
"{}:\n{}",
strings.get_str(name),
mir.display(&strings)
);
} }
} }
"asm" => { "asm" => {

View file

@ -31,10 +31,7 @@ pub mod triples;
pub fn tokenize<'a>( pub fn tokenize<'a>(
bytes: &'a [u8], bytes: &'a [u8],
) -> Result< ) -> Result<lexer::Tokenizer<'a>, (lexer::Tokenizer<'a>, Vec<lexer::TokenizeError>)> {
lexer::Tokenizer<'a>,
(lexer::Tokenizer<'a>, Vec<lexer::TokenizeError>),
> {
lexer::Tokenizer::new_with_errors(bytes) lexer::Tokenizer::new_with_errors(bytes)
} }

1101
src/mir.rs

File diff suppressed because it is too large Load diff

View file

@ -2,10 +2,7 @@ use itertools::Itertools;
use num_bigint::{BigInt, BigUint}; use num_bigint::{BigInt, BigUint};
use crate::{ use crate::{
ast::{ ast::{self, FloatingType, IntegralType, LetOrVar, Node, Tag, Type},
self, FloatingType, IntegralType, LetOrVar, Node, PrimitiveType, Tag,
Type,
},
ast2::intern::{self, AMD64_POINTER_BITS}, ast2::intern::{self, AMD64_POINTER_BITS},
common::NextIf, common::NextIf,
comptime::{self, ComptimeNumber}, comptime::{self, ComptimeNumber},
@ -147,17 +144,13 @@ impl Tree {
.map(|decl| { .map(|decl| {
let name = match self.nodes.get_node(*decl) { let name = match self.nodes.get_node(*decl) {
Tag::FunctionDecl { proto, .. } => { Tag::FunctionDecl { proto, .. } => {
let Tag::FunctionProto { name, .. } = let Tag::FunctionProto { name, .. } = self.nodes.get_node(*proto) else {
self.nodes.get_node(*proto)
else {
unreachable!() unreachable!()
}; };
self.get_ident_str(*name).unwrap().to_owned() self.get_ident_str(*name).unwrap().to_owned()
} }
Tag::GlobalDecl { name, .. } => { Tag::GlobalDecl { name, .. } => self.get_ident_str(*name).unwrap().to_owned(),
self.get_ident_str(*name).unwrap().to_owned()
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -243,10 +236,7 @@ impl Tree {
IntegralType { signed, bits } IntegralType { signed, bits }
} }
fn parse_integral_constant( fn parse_integral_constant(token: Token, lexeme: &str) -> (BigInt, Option<IntegralType>) {
token: Token,
lexeme: &str,
) -> (BigInt, Option<IntegralType>) {
let radix = Radix::from_token(token).unwrap(); let radix = Radix::from_token(token).unwrap();
// TODO: figure out how to do this safely for bigger types, whether to // TODO: figure out how to do this safely for bigger types, whether to
@ -269,9 +259,9 @@ impl Tree {
let value = comptime::bigint::parse_bigint(digits.into_iter(), radix); let value = comptime::bigint::parse_bigint(digits.into_iter(), radix);
let ty = match iter.clone().next() { let ty = match iter.clone().next() {
Some((_, 'u')) | Some((_, 'i')) => Some(Self::parse_integral_type( Some((_, 'u')) | Some((_, 'i')) => {
&lexeme[iter.next().unwrap().0..], Some(Self::parse_integral_type(&lexeme[iter.next().unwrap().0..]))
)), }
_ => None, _ => None,
}; };
@ -281,10 +271,7 @@ impl Tree {
) )
} }
fn parse_floating_constant( fn parse_floating_constant(_token: Token, lexeme: &str) -> (u64, FloatingType) {
_token: Token,
lexeme: &str,
) -> (u64, FloatingType) {
// let (dot, exp) = match token { // let (dot, exp) = match token {
// Token::DotFloatingExpConstant => (true, true), // Token::DotFloatingExpConstant => (true, true),
// Token::DotFloatingConstant => (true, false), // Token::DotFloatingConstant => (true, false),
@ -304,12 +291,8 @@ impl Tree {
); );
let bits = match lexeme.1 { let bits = match lexeme.1 {
FloatingType::Binary32 => { FloatingType::Binary32 => lexeme.0.parse::<f32>().unwrap().to_bits() as u64,
lexeme.0.parse::<f32>().unwrap().to_bits() as u64 FloatingType::Binary64 => lexeme.0.parse::<f64>().unwrap().to_bits() as u64,
}
FloatingType::Binary64 => {
lexeme.0.parse::<f64>().unwrap().to_bits() as u64
}
}; };
(bits, lexeme.1) (bits, lexeme.1)
@ -328,10 +311,7 @@ impl Tree {
} }
} }
pub fn parse_primitive_type( pub fn parse_primitive_type(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
let token = tokens.next().ok_or(Error::UnexpectedEndOfTokens)?; let token = tokens.next().ok_or(Error::UnexpectedEndOfTokens)?;
let prim = match token.token() { let prim = match token.token() {
Token::Void => intern::Index::VOID, Token::Void => intern::Index::VOID,
@ -346,10 +326,7 @@ impl Tree {
Ok(self.nodes.push_tag(Tag::PrimitiveType(prim))) Ok(self.nodes.push_tag(Tag::PrimitiveType(prim)))
} }
pub fn parse_pointer( pub fn parse_pointer(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
tokens.expect_token(Token::Star)?; tokens.expect_token(Token::Star)?;
let _constness = tokens.eat_token(Token::Const); let _constness = tokens.eat_token(Token::Const);
let typename = self.parse_typename(tokens)?; let typename = self.parse_typename(tokens)?;
@ -357,24 +334,19 @@ impl Tree {
Ok(self.nodes.push_tag(Tag::Pointer { pointee: typename })) Ok(self.nodes.push_tag(Tag::Pointer { pointee: typename }))
} }
pub fn parse_typename( pub fn parse_typename(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
match tokens.peek_token_or_err()?.token() { match tokens.peek_token_or_err()?.token() {
Token::Star => self.parse_pointer(tokens), Token::Star => self.parse_pointer(tokens),
Token::Ident => { Token::Ident => {
let token = tokens.next().unwrap(); let token = tokens.next().unwrap();
match Self::try_parse_integral_type(token.lexeme())? { match Self::try_parse_integral_type(token.lexeme())? {
Some(int) => { Some(int) => {
let ty = let ty = self.intern_pool.get_int_type(int.signed, int.bits);
self.intern_pool.get_int_type(int.signed, int.bits);
Ok(self.nodes.push_tag(Tag::IntegralType(ty))) Ok(self.nodes.push_tag(Tag::IntegralType(ty)))
} }
None => { None => {
let name = let name = self.intern_pool.insert_string(token.lexeme());
self.intern_pool.insert_string(token.lexeme());
Ok(self.nodes.push_tag(Tag::Ident { name })) Ok(self.nodes.push_tag(Tag::Ident { name }))
} }
} }
@ -383,10 +355,7 @@ impl Tree {
} }
} }
pub fn parse_var_decl( pub fn parse_var_decl(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
let let_or_var = match tokens let let_or_var = match tokens
.eat_token(Token::Let) .eat_token(Token::Let)
.or_else(|| tokens.eat_token(Token::Var)) .or_else(|| tokens.eat_token(Token::Var))
@ -406,8 +375,7 @@ impl Tree {
None None
}; };
let name_str = let name_str = self.intern_pool.get_str(self.ident_index(name)).to_owned();
self.intern_pool.get_str(self.ident_index(name)).to_owned();
let decl = self.nodes.reserve_node(); let decl = self.nodes.reserve_node();
let assignment = if tokens.eat_token(Token::Equal).is_some() { let assignment = if tokens.eat_token(Token::Equal).is_some() {
@ -435,10 +403,7 @@ impl Tree {
/// GLOBAL_DECL <- /// GLOBAL_DECL <-
/// const IDENTIFIER (: TYPENAME)? = EXPR; /// const IDENTIFIER (: TYPENAME)? = EXPR;
pub fn parse_global_decl( pub fn parse_global_decl(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
_ = tokens.expect_token(Token::Const)?; _ = tokens.expect_token(Token::Const)?;
let name = self.parse_ident(tokens)?; let name = self.parse_ident(tokens)?;
@ -483,10 +448,7 @@ impl Tree {
/// PARAMETER <- /// PARAMETER <-
/// IDENTIFIER : TYPENAME /// IDENTIFIER : TYPENAME
pub fn parse_parameter( pub fn parse_parameter(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
let name = self.parse_ident(tokens)?; let name = self.parse_ident(tokens)?;
tokens.expect_token(Token::Colon)?; tokens.expect_token(Token::Colon)?;
let ty = self.parse_typename(tokens)?; let ty = self.parse_typename(tokens)?;
@ -505,10 +467,7 @@ impl Tree {
/// PARAMETER_LIST <- /// PARAMETER_LIST <-
/// PARAMETER /// PARAMETER
/// PARAMETER_LIST , PARAMETER /// PARAMETER_LIST , PARAMETER
pub fn parse_parameter_list( pub fn parse_parameter_list(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
let mut parameters = Vec::new(); let mut parameters = Vec::new();
loop { loop {
@ -533,10 +492,7 @@ impl Tree {
/// fn IDENTIFIER () -> TYPENAME /// fn IDENTIFIER () -> TYPENAME
/// fn IDENTIFIER ( PARAMETER_LIST ,? ) /// fn IDENTIFIER ( PARAMETER_LIST ,? )
/// fn IDENTIFIER ( PARAMETER_LIST ,? ) -> TYPENAME /// fn IDENTIFIER ( PARAMETER_LIST ,? ) -> TYPENAME
pub fn parse_fn_proto( pub fn parse_fn_proto(&mut self, tokens: &mut TokenIterator) -> Result<(Node, Node)> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<(Node, Node)> {
tokens.expect_token(Token::Fn)?; tokens.expect_token(Token::Fn)?;
let name = self.parse_ident(tokens)?; let name = self.parse_ident(tokens)?;
tokens.expect_token(Token::OpenParens)?; tokens.expect_token(Token::OpenParens)?;
@ -567,10 +523,7 @@ impl Tree {
/// FUNCTION_DECL <- /// FUNCTION_DECL <-
/// FUNCTION_PROTO BLOCK /// FUNCTION_PROTO BLOCK
pub fn parse_fn_decl( pub fn parse_fn_decl(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
let (proto, name) = self.parse_fn_proto(tokens)?; let (proto, name) = self.parse_fn_proto(tokens)?;
let decl = match self let decl = match self
@ -580,10 +533,8 @@ impl Tree {
Some(record) => record.node(), Some(record) => record.node(),
None => { None => {
let decl = self.nodes.reserve_node(); let decl = self.nodes.reserve_node();
self.st.insert_orderless_symbol( self.st
&self.get_ident_str(name).unwrap().to_owned(), .insert_orderless_symbol(&self.get_ident_str(name).unwrap().to_owned(), decl);
decl,
);
decl decl
} }
}; };
@ -593,9 +544,7 @@ impl Tree {
let body = self.parse_block(tokens, Some(block))?; let body = self.parse_block(tokens, Some(block))?;
let unresolved = self let unresolved = self
.st .st
.extract_orderless_if(|_, v| { .extract_orderless_if(|_, v| self.nodes.get_node(v.node()) == &Tag::Undefined)
self.nodes.get_node(v.node()) == &Tag::Undefined
})
.collect::<Vec<_>>(); .collect::<Vec<_>>();
self.st.into_parent(); self.st.into_parent();
self.st.extend_orderless(unresolved); self.st.extend_orderless(unresolved);
@ -669,10 +618,7 @@ impl Tree {
/// ASSIGNMENT_EXPR <- /// ASSIGNMENT_EXPR <-
/// BINARY_EXPRESSION /// BINARY_EXPRESSION
/// BINARY_EXPRESSION ASSIGNMENT_OP EXPRESSION /// BINARY_EXPRESSION ASSIGNMENT_OP EXPRESSION
pub fn parse_assignment_expr( pub fn parse_assignment_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
let lhs = self.parse_binary_expr(tokens, 0)?; let lhs = self.parse_binary_expr(tokens, 0)?;
Ok(self.try_parse_assignment(lhs, tokens)?.unwrap_or(lhs)) Ok(self.try_parse_assignment(lhs, tokens)?.unwrap_or(lhs))
@ -700,24 +646,12 @@ impl Tree {
Token::MinusEqual => self.nodes.push_tag(Tag::Sub { lhs, rhs }), Token::MinusEqual => self.nodes.push_tag(Tag::Sub { lhs, rhs }),
Token::StarEqual => self.nodes.push_tag(Tag::Mul { lhs, rhs }), Token::StarEqual => self.nodes.push_tag(Tag::Mul { lhs, rhs }),
Token::SlashEqual => self.nodes.push_tag(Tag::Sub { lhs, rhs }), Token::SlashEqual => self.nodes.push_tag(Tag::Sub { lhs, rhs }),
Token::PercentEqual => { Token::PercentEqual => self.nodes.push_tag(Tag::Rem { lhs, rhs }),
self.nodes.push_tag(Tag::Rem { lhs, rhs }) Token::PipeEqual => self.nodes.push_tag(Tag::BitOr { lhs, rhs }),
} Token::CaretEqual => self.nodes.push_tag(Tag::BitXOr { lhs, rhs }),
Token::PipeEqual => { Token::AmpersandEqual => self.nodes.push_tag(Tag::BitAnd { lhs, rhs }),
self.nodes.push_tag(Tag::BitOr { lhs, rhs }) Token::LessLessEqual => self.nodes.push_tag(Tag::Shl { lhs, rhs }),
} Token::GreaterGreaterEqual => self.nodes.push_tag(Tag::Shr { lhs, rhs }),
Token::CaretEqual => {
self.nodes.push_tag(Tag::BitXOr { lhs, rhs })
}
Token::AmpersandEqual => {
self.nodes.push_tag(Tag::BitAnd { lhs, rhs })
}
Token::LessLessEqual => {
self.nodes.push_tag(Tag::Shl { lhs, rhs })
}
Token::GreaterGreaterEqual => {
self.nodes.push_tag(Tag::Shr { lhs, rhs })
}
Token::Equal => rhs, Token::Equal => rhs,
_ => { _ => {
unreachable!() unreachable!()
@ -731,10 +665,7 @@ impl Tree {
/// RETURN_STATEMENT <- /// RETURN_STATEMENT <-
/// return EXPRESSION? ; /// return EXPRESSION? ;
pub fn try_parse_return_stmt( pub fn try_parse_return_stmt(&mut self, tokens: &mut TokenIterator) -> Result<Option<Node>> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Option<Node>> {
if tokens.eat_token(Token::Return).is_some() { if tokens.eat_token(Token::Return).is_some() {
let expr = if !tokens.is_next_token(Token::Semi) { let expr = if !tokens.is_next_token(Token::Semi) {
let expr = Some(self.parse_expr(tokens)?); let expr = Some(self.parse_expr(tokens)?);
@ -755,10 +686,7 @@ impl Tree {
/// RETURN_EXPRESSION /// RETURN_EXPRESSION
/// VAR_DECL ; /// VAR_DECL ;
/// EXPRESSION ; /// EXPRESSION ;
pub fn parse_statement( pub fn parse_statement(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
match tokens.peek_token_or_err()?.token() { match tokens.peek_token_or_err()?.token() {
Token::Return => Ok(self.try_parse_return_stmt(tokens)?.unwrap()), Token::Return => Ok(self.try_parse_return_stmt(tokens)?.unwrap()),
Token::Var | Token::Let => { Token::Var | Token::Let => {
@ -854,10 +782,7 @@ impl Tree {
/// - POSTFIX_EXPR /// - POSTFIX_EXPR
/// & POSTFIX_EXPR /// & POSTFIX_EXPR
/// * POSTFIX_EXPR /// * POSTFIX_EXPR
pub fn parse_prefix_expr( pub fn parse_prefix_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
match tokens.peek_token_or_err()?.token() { match tokens.peek_token_or_err()?.token() {
Token::Bang => { Token::Bang => {
_ = tokens.next(); _ = tokens.next();
@ -886,10 +811,7 @@ impl Tree {
/// AS_EXPR <- /// AS_EXPR <-
/// PREFIX_EXPR /// PREFIX_EXPR
/// PREFIX_EXPR as TYPENAME /// PREFIX_EXPR as TYPENAME
pub fn parse_as_expr( pub fn parse_as_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
let expr = self.parse_prefix_expr(tokens)?; let expr = self.parse_prefix_expr(tokens)?;
if tokens.eat_token(Token::As).is_some() { if tokens.eat_token(Token::As).is_some() {
@ -906,10 +828,7 @@ impl Tree {
/// ARGUMENT <- /// ARGUMENT <-
/// IDENT : EXPR /// IDENT : EXPR
/// EXPR /// EXPR
pub fn parse_argument( pub fn parse_argument(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
if tokens.is_next_token2(Token::Colon) { if tokens.is_next_token2(Token::Colon) {
let name = self.parse_ident(tokens)?; let name = self.parse_ident(tokens)?;
_ = tokens.expect_token(Token::Colon)?; _ = tokens.expect_token(Token::Colon)?;
@ -927,10 +846,7 @@ impl Tree {
/// ARGUMENT_LIST <- /// ARGUMENT_LIST <-
/// ARGUMENT /// ARGUMENT
/// ARGUMENT_LIST , ARGUMENT /// ARGUMENT_LIST , ARGUMENT
pub fn parse_argument_list( pub fn parse_argument_list(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
let mut arguments = Vec::new(); let mut arguments = Vec::new();
loop { loop {
@ -954,10 +870,7 @@ impl Tree {
/// PRIMARY_EXPR /// PRIMARY_EXPR
/// PRIMARY_EXPR ( ) /// PRIMARY_EXPR ( )
/// PRIMARY_EXPR ( ARGUMENT_LIST ) /// PRIMARY_EXPR ( ARGUMENT_LIST )
pub fn parse_postfix_expr( pub fn parse_postfix_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
let lhs = self.parse_primary_expr(tokens)?; let lhs = self.parse_primary_expr(tokens)?;
if tokens.eat_token(Token::OpenParens).is_some() { if tokens.eat_token(Token::OpenParens).is_some() {
@ -983,10 +896,7 @@ impl Tree {
/// FLOATING_CONSTANT /// FLOATING_CONSTANT
/// ( EXPRESSION ) /// ( EXPRESSION )
/// { STATEMENT* EXPRESSION? } /// { STATEMENT* EXPRESSION? }
pub fn parse_primary_expr( pub fn parse_primary_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
let token = tokens.peek_token_or_err()?; let token = tokens.peek_token_or_err()?;
match token.token() { match token.token() {
Token::Ident => { Token::Ident => {
@ -995,16 +905,12 @@ impl Tree {
let name = ident.lexeme(); let name = ident.lexeme();
if let Some(record) = self.st.find_ordered_symbol(name) { if let Some(record) = self.st.find_ordered_symbol(name) {
Ok(self.nodes.push_tag(Tag::DeclRef(record.node()))) Ok(self.nodes.push_tag(Tag::DeclRef(record.node())))
} else if let Some(record) = self.st.find_orderless_symbol(name) } else if let Some(record) = self.st.find_orderless_symbol(name) {
{
Ok(self.nodes.push_tag(Tag::GlobalRef(record.node()))) Ok(self.nodes.push_tag(Tag::GlobalRef(record.node())))
} else { } else {
let node = self let node = self
.st .st
.insert_orderless_symbol( .insert_orderless_symbol(name, self.nodes.reserve_node())
name,
self.nodes.reserve_node(),
)
.node(); .node();
Ok(self.nodes.push_tag(Tag::GlobalRef(node))) Ok(self.nodes.push_tag(Tag::GlobalRef(node)))
@ -1015,10 +921,7 @@ impl Tree {
| Token::IntegerOctConstant | Token::IntegerOctConstant
| Token::IntegerConstant => { | Token::IntegerConstant => {
_ = tokens.next(); _ = tokens.next();
let (bits, ty) = Self::parse_integral_constant( let (bits, ty) = Self::parse_integral_constant(token.token(), token.lexeme());
token.token(),
token.lexeme(),
);
let (_, bytes) = bits.to_bytes_le(); let (_, bytes) = bits.to_bytes_le();
const BUF_SIZE: usize = core::mem::size_of::<u64>(); const BUF_SIZE: usize = core::mem::size_of::<u64>();
@ -1027,18 +930,15 @@ impl Tree {
.copy_from_slice(&bytes[..bytes.len().min(BUF_SIZE)]); .copy_from_slice(&bytes[..bytes.len().min(BUF_SIZE)]);
let bytes = match bytes.len() { let bytes = match bytes.len() {
0..2 => { 0..2 => {
let (buf, _) = let (buf, _) = buf.split_at(core::mem::size_of::<u32>());
buf.split_at(core::mem::size_of::<u32>());
self.intern_pool.get_unsigned_integer( self.intern_pool.get_unsigned_integer(
u32::from_le_bytes(buf.try_into().unwrap()) as u64, u32::from_le_bytes(buf.try_into().unwrap()) as u64,
) )
} }
0..4 => { 0..4 => {
let (buf, _) = let (buf, _) = buf.split_at(core::mem::size_of::<u64>());
buf.split_at(core::mem::size_of::<u64>()); self.intern_pool
self.intern_pool.get_unsigned_integer( .get_unsigned_integer(u64::from_le_bytes(buf.try_into().unwrap()))
u64::from_le_bytes(buf.try_into().unwrap()),
)
} }
0.. => self.intern_pool.insert_bytes(&bytes), 0.. => self.intern_pool.insert_bytes(&bytes),
}; };
@ -1055,22 +955,15 @@ impl Tree {
| Token::DotFloatingConstant | Token::DotFloatingConstant
| Token::DotFloatingExpConstant => { | Token::DotFloatingExpConstant => {
_ = tokens.next(); _ = tokens.next();
let (bits, ty) = Self::parse_floating_constant( let (bits, ty) = Self::parse_floating_constant(token.token(), token.lexeme());
token.token(),
token.lexeme(),
);
let bytes = match ty { let bytes = match ty {
FloatingType::Binary32 => { FloatingType::Binary32 => self.intern_pool.get_or_insert(intern::Key::F32 {
self.intern_pool.get_or_insert(intern::Key::F32 {
bits: f32::from_bits(bits as u32), bits: f32::from_bits(bits as u32),
}) }),
} FloatingType::Binary64 => self.intern_pool.get_or_insert(intern::Key::F64 {
FloatingType::Binary64 => {
self.intern_pool.get_or_insert(intern::Key::F64 {
bits: f64::from_bits(bits), bits: f64::from_bits(bits),
}) }),
}
}; };
Ok(self.nodes.push_tag(Tag::Constant { Ok(self.nodes.push_tag(Tag::Constant {
@ -1096,10 +989,7 @@ impl Tree {
/// BLOCK /// BLOCK
/// EXPR /// EXPR
/// EXPR ; /// EXPR ;
pub fn parse_expr_or_stmt_or_block( pub fn parse_expr_or_stmt_or_block(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
let peek = tokens.peek_token_or_err()?; let peek = tokens.peek_token_or_err()?;
let body = match peek.token() { let body = match peek.token() {
// block // block
@ -1130,10 +1020,7 @@ impl Tree {
/// ELSE_EXPR <- /// ELSE_EXPR <-
/// 'else' (IF_EXPR | EXPR_OR_STATEMENT_OR_BLOCK) /// 'else' (IF_EXPR | EXPR_OR_STATEMENT_OR_BLOCK)
pub fn try_parse_else_expr( pub fn try_parse_else_expr(&mut self, tokens: &mut TokenIterator) -> Result<Option<Node>> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Option<Node>> {
if tokens.eat_token(Token::Else).is_none() { if tokens.eat_token(Token::Else).is_none() {
return Ok(None); return Ok(None);
} }
@ -1148,10 +1035,7 @@ impl Tree {
/// IF_EXPR <- /// IF_EXPR <-
/// 'if' ( EXPR ) EXPR_OR_STATEMENT_OR_BLOCK ELSE_EXPR? /// 'if' ( EXPR ) EXPR_OR_STATEMENT_OR_BLOCK ELSE_EXPR?
pub fn try_parse_if_expr( pub fn try_parse_if_expr(&mut self, tokens: &mut TokenIterator) -> Result<Option<Node>> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Option<Node>> {
if tokens.eat_token(Token::If).is_none() { if tokens.eat_token(Token::If).is_none() {
return Ok(None); return Ok(None);
} }
@ -1175,10 +1059,7 @@ impl Tree {
/// IF_EXPR <- /// IF_EXPR <-
/// 'if' ( EXPR ) EXPR_OR_STATEMENT_OR_BLOCK ELSE_EXPR? /// 'if' ( EXPR ) EXPR_OR_STATEMENT_OR_BLOCK ELSE_EXPR?
pub fn parse_if_expr( pub fn parse_if_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
&mut self,
tokens: &mut TokenIterator,
) -> Result<Node> {
self.try_parse_if_expr(tokens)? self.try_parse_if_expr(tokens)?
.ok_or(Error::ExpectedTokenNotFound(Token::If)) .ok_or(Error::ExpectedTokenNotFound(Token::If))
} }
@ -1228,9 +1109,7 @@ impl Tree {
fn get_typename_str(&self, node: Node) -> Option<String> { fn get_typename_str(&self, node: Node) -> Option<String> {
match self.nodes.get_node(node) { match self.nodes.get_node(node) {
Tag::IntegralType(i) => Some(i.to_string()), Tag::IntegralType(i) => Some(i.to_string()),
Tag::Ident { name } => { Tag::Ident { name } => Some(self.intern_pool.get_str(*name).to_owned()),
Some(self.intern_pool.get_str(*name).to_owned())
}
Tag::Pointer { pointee } => self.get_typename_str(*pointee), Tag::Pointer { pointee } => self.get_typename_str(*pointee),
Tag::PrimitiveType(prim) => Some(prim.to_string()), Tag::PrimitiveType(prim) => Some(prim.to_string()),
_ => None, _ => None,
@ -1272,9 +1151,7 @@ impl Tree {
} }
children children
} }
Tag::ReturnStmt { expr } => { Tag::ReturnStmt { expr } => expr.into_iter().cloned().collect::<Vec<_>>(),
expr.into_iter().cloned().collect::<Vec<_>>()
}
&Tag::ExprStmt { expr } => { &Tag::ExprStmt { expr } => {
vec![expr] vec![expr]
} }
@ -1321,10 +1198,7 @@ impl Tree {
&Tag::ExplicitCast { lhs, typename } => { &Tag::ExplicitCast { lhs, typename } => {
vec![lhs, typename] vec![lhs, typename]
} }
Tag::Deref { lhs } Tag::Deref { lhs } | Tag::Ref { lhs } | Tag::Not { lhs } | Tag::Negate { lhs } => {
| Tag::Ref { lhs }
| Tag::Not { lhs }
| Tag::Negate { lhs } => {
vec![*lhs] vec![*lhs]
} }
Tag::Or { lhs, rhs } Tag::Or { lhs, rhs }
@ -1371,17 +1245,8 @@ impl Tree {
if let Some(parameters) = parameters { if let Some(parameters) = parameters {
self.render_node(writer, parameters, indent)?; self.render_node(writer, parameters, indent)?;
} }
write_indented!( write_indented!(indent, writer, "%{} = function_proto: {{", node.get())?;
indent, write!(writer, "name: \"{}\"", self.get_ident_str(name).unwrap())?;
writer,
"%{} = function_proto: {{",
node.get()
)?;
write!(
writer,
"name: \"{}\"",
self.get_ident_str(name).unwrap()
)?;
if let Some(parameters) = parameters { if let Some(parameters) = parameters {
write!(writer, ", parameters: %{}", parameters.get())?; write!(writer, ", parameters: %{}", parameters.get())?;
} }
@ -1389,12 +1254,7 @@ impl Tree {
writeln!(writer, "}}") writeln!(writer, "}}")
} }
Tag::ParameterList { parameters } => { Tag::ParameterList { parameters } => {
writeln_indented!( writeln_indented!(indent, writer, "%{} = ParameterList [", node.get())?;
indent,
writer,
"%{} = ParameterList [",
node.get()
)?;
for param in parameters { for param in parameters {
self.render_node(writer, param, indent + 1)?; self.render_node(writer, param, indent + 1)?;
} }
@ -1410,9 +1270,7 @@ impl Tree {
self.get_typename_str(ty).unwrap() self.get_typename_str(ty).unwrap()
) )
} }
Tag::Pointer { .. } Tag::Pointer { .. } | Tag::IntegralType(_) | Tag::PrimitiveType(_) => {
| Tag::IntegralType(_)
| Tag::PrimitiveType(_) => {
writeln_indented!( writeln_indented!(
indent, indent,
writer, writer,
@ -1469,20 +1327,9 @@ impl Tree {
Tag::ReturnStmt { expr } => { Tag::ReturnStmt { expr } => {
if let Some(expr) = expr { if let Some(expr) = expr {
self.render_node(writer, expr, indent)?; self.render_node(writer, expr, indent)?;
writeln_indented!( writeln_indented!(indent, writer, "%{} = return %{};", node.get(), expr.get())
indent,
writer,
"%{} = return %{};",
node.get(),
expr.get()
)
} else { } else {
writeln_indented!( writeln_indented!(indent, writer, "%{} = return;", node.get())
indent,
writer,
"%{} = return;",
node.get()
)
} }
} }
Tag::ExprStmt { expr } => self.render_node(writer, expr, indent), Tag::ExprStmt { expr } => self.render_node(writer, expr, indent),
@ -1493,8 +1340,7 @@ impl Tree {
assignment, assignment,
} => { } => {
self.render_node(writer, name, indent)?; self.render_node(writer, name, indent)?;
explicit_type explicit_type.map(|node| self.render_node(writer, node, indent));
.map(|node| self.render_node(writer, node, indent));
assignment.map(|node| self.render_node(writer, node, indent)); assignment.map(|node| self.render_node(writer, node, indent));
write_indented!( write_indented!(
@ -1513,11 +1359,7 @@ impl Tree {
self.get_ident_str(name).unwrap() self.get_ident_str(name).unwrap()
)?; )?;
if let Some(ty) = explicit_type { if let Some(ty) = explicit_type {
write!( write!(writer, ", ty: {}", self.get_typename_str(ty).unwrap())?;
writer,
", ty: {}",
self.get_typename_str(ty).unwrap()
)?;
} }
if let Some(assignment) = assignment { if let Some(assignment) = assignment {
write!(writer, ", value: %{assignment}")?; write!(writer, ", value: %{assignment}")?;
@ -1541,11 +1383,7 @@ impl Tree {
self.get_ident_str(name).unwrap() self.get_ident_str(name).unwrap()
)?; )?;
if let Some(ty) = explicit_type { if let Some(ty) = explicit_type {
write!( write!(writer, ", ty: {}", self.get_typename_str(ty).unwrap())?;
writer,
", ty: {}",
self.get_typename_str(ty).unwrap()
)?;
} }
write!(writer, ", value: %{assignment}")?; write!(writer, ", value: %{assignment}")?;
writeln!(writer, ");")?; writeln!(writer, ");")?;
@ -1555,26 +1393,13 @@ impl Tree {
self.render_node(writer, lhs, indent)?; self.render_node(writer, lhs, indent)?;
if let Some(rhs) = rhs { if let Some(rhs) = rhs {
self.render_node(writer, rhs, indent)?; self.render_node(writer, rhs, indent)?;
writeln_indented!( writeln_indented!(indent, writer, "%{node} = call (%{lhs})(%{rhs})")
indent,
writer,
"%{node} = call (%{lhs})(%{rhs})"
)
} else { } else {
writeln_indented!( writeln_indented!(indent, writer, "%{node} = call (%{lhs})()")
indent,
writer,
"%{node} = call (%{lhs})()"
)
} }
} }
Tag::ArgumentList { arguments } => { Tag::ArgumentList { arguments } => {
writeln_indented!( writeln_indented!(indent, writer, "%{} = ArgumentList [", node.get())?;
indent,
writer,
"%{} = ArgumentList [",
node.get()
)?;
for args in arguments { for args in arguments {
self.render_node(writer, args, indent + 1)?; self.render_node(writer, args, indent + 1)?;
} }
@ -1590,12 +1415,7 @@ impl Tree {
self.get_ident_str(name).unwrap(), self.get_ident_str(name).unwrap(),
) )
} else { } else {
writeln_indented!( writeln_indented!(indent, writer, "%{} = %{expr},", node.get(),)
indent,
writer,
"%{} = %{expr},",
node.get(),
)
} }
} }
@ -1612,13 +1432,7 @@ impl Tree {
} }
Tag::Deref { lhs } => { Tag::Deref { lhs } => {
self.render_node(writer, lhs, indent)?; self.render_node(writer, lhs, indent)?;
writeln_indented!( writeln_indented!(indent, writer, "%{} = deref(%{})", node.get(), lhs.get())
indent,
writer,
"%{} = deref(%{})",
node.get(),
lhs.get()
)
} }
Tag::Ref { lhs } => { Tag::Ref { lhs } => {
self.render_node(writer, lhs, indent)?; self.render_node(writer, lhs, indent)?;
@ -1636,13 +1450,7 @@ impl Tree {
} }
Tag::Negate { lhs } => { Tag::Negate { lhs } => {
self.render_node(writer, lhs, indent)?; self.render_node(writer, lhs, indent)?;
writeln_indented!( writeln_indented!(indent, writer, "%{} = not(%{})", node.get(), lhs.get())
indent,
writer,
"%{} = not(%{})",
node.get(),
lhs.get()
)
} }
Tag::Or { lhs, rhs } => { Tag::Or { lhs, rhs } => {
self.render_node(writer, lhs, indent)?; self.render_node(writer, lhs, indent)?;
@ -1950,10 +1758,7 @@ impl Tree {
} }
} }
pub fn render<W: core::fmt::Write>( pub fn render<W: core::fmt::Write>(&mut self, writer: &mut W) -> core::fmt::Result {
&mut self,
writer: &mut W,
) -> core::fmt::Result {
for decl in &self.global_decls.clone() { for decl in &self.global_decls.clone() {
self.render_node(writer, *decl, 0)?; self.render_node(writer, *decl, 0)?;
} }
@ -1961,16 +1766,6 @@ impl Tree {
Ok(()) Ok(())
} }
fn render2<W: core::fmt::Write>(&mut self, w: &mut W) {
for decl in self.global_decls.clone().iter() {
ast::tree_visitor::Visitor::new(
*decl,
|_: &mut Tree, _: Node| {},
|_: &mut Tree, _: Node| {},
);
}
}
pub fn peer_type_of_nodes_unwrap(&self, lhs: Node, rhs: Node) -> Type { pub fn peer_type_of_nodes_unwrap(&self, lhs: Node, rhs: Node) -> Type {
self.peer_type_of_nodes(lhs, rhs).expect({ self.peer_type_of_nodes(lhs, rhs).expect({
let at = self.type_of_node(lhs); let at = self.type_of_node(lhs);
@ -2031,9 +1826,7 @@ impl Tree {
pointee: Box::new(self.type_of_node(*pointee)), pointee: Box::new(self.type_of_node(*pointee)),
}, },
Tag::Constant { ty, .. } => ty.clone(), Tag::Constant { ty, .. } => ty.clone(),
Tag::IntegralType(t) => { Tag::IntegralType(t) => self.intern_pool.as_ast1_type(AMD64_POINTER_BITS, *t),
self.intern_pool.as_ast1_type(AMD64_POINTER_BITS, *t)
}
Tag::PrimitiveType(t) => match *t { Tag::PrimitiveType(t) => match *t {
intern::Index::F32 => Type::Floating(FloatingType::Binary32), intern::Index::F32 => Type::Floating(FloatingType::Binary32),
intern::Index::F64 => Type::Floating(FloatingType::Binary64), intern::Index::F64 => Type::Floating(FloatingType::Binary64),
@ -2054,9 +1847,7 @@ impl Tree {
(Some(a), b) => self.peer_type_of_nodes(*a, *b).expect({ (Some(a), b) => self.peer_type_of_nodes(*a, *b).expect({
let at = self.type_of_node(*a); let at = self.type_of_node(*a);
let bt = self.type_of_node(*b); let bt = self.type_of_node(*b);
&format!( &format!("incompatible types for %{a}({at}) and %{b}({bt})")
"incompatible types for %{a}({at}) and %{b}({bt})"
)
}), }),
}; };
@ -2081,9 +1872,7 @@ impl Tree {
ty ty
} }
Tag::CallExpr { lhs, .. } => { Tag::CallExpr { lhs, .. } => self.type_of_node(*lhs).return_type().unwrap().clone(),
self.type_of_node(*lhs).return_type().unwrap().clone()
}
Tag::ExplicitCast { typename, .. } => self.type_of_node(*typename), Tag::ExplicitCast { typename, .. } => self.type_of_node(*typename),
Tag::Deref { lhs } => self.type_of_node(*lhs).remove_ptr().unwrap(), Tag::Deref { lhs } => self.type_of_node(*lhs).remove_ptr().unwrap(),
Tag::Ref { lhs } => self.type_of_node(*lhs).into_ptr(), Tag::Ref { lhs } => self.type_of_node(*lhs).into_ptr(),
@ -2099,15 +1888,11 @@ impl Tree {
| Tag::And { lhs, rhs } | Tag::And { lhs, rhs }
| Tag::BitOr { lhs, rhs } | Tag::BitOr { lhs, rhs }
| Tag::BitAnd { lhs, rhs } | Tag::BitAnd { lhs, rhs }
| Tag::BitXOr { lhs, rhs } => { | Tag::BitXOr { lhs, rhs } => self.peer_type_of_nodes(*lhs, *rhs).expect({
self.peer_type_of_nodes(*lhs, *rhs).expect({
let at = self.type_of_node(*lhs); let at = self.type_of_node(*lhs);
let bt = self.type_of_node(*rhs); let bt = self.type_of_node(*rhs);
&format!( &format!("incompatible types for %{lhs}({at}) and %{rhs}({bt})")
"incompatible types for %{lhs}({at}) and %{rhs}({bt})" }),
)
})
}
Tag::Shl { lhs, .. } => self.type_of_node(*lhs), Tag::Shl { lhs, .. } => self.type_of_node(*lhs),
Tag::Shr { lhs, .. } => self.type_of_node(*lhs), Tag::Shr { lhs, .. } => self.type_of_node(*lhs),
Tag::Eq { .. } => Type::bool(), Tag::Eq { .. } => Type::bool(),
@ -2181,9 +1966,7 @@ impl Tree {
is_comptime is_comptime
} }
Tag::Not { lhs } | Tag::Negate { lhs } => { Tag::Not { lhs } | Tag::Negate { lhs } => self.is_node_comptime(*lhs, true),
self.is_node_comptime(*lhs, true)
}
Tag::Or { lhs, rhs } Tag::Or { lhs, rhs }
| Tag::And { lhs, rhs } | Tag::And { lhs, rhs }
| Tag::BitOr { lhs, rhs } | Tag::BitOr { lhs, rhs }
@ -2202,8 +1985,7 @@ impl Tree {
| Tag::Mul { lhs, rhs } | Tag::Mul { lhs, rhs }
| Tag::Rem { lhs, rhs } | Tag::Rem { lhs, rhs }
| Tag::Div { lhs, rhs } => { | Tag::Div { lhs, rhs } => {
self.is_node_comptime(*lhs, true) self.is_node_comptime(*lhs, true) && self.is_node_comptime(*rhs, true)
&& self.is_node_comptime(*rhs, true)
} }
_ => false, _ => false,
} }
@ -2212,10 +1994,8 @@ impl Tree {
pub fn value_of_comptime_node(&self, node: Node) -> Option<ComptimeNumber> { pub fn value_of_comptime_node(&self, node: Node) -> Option<ComptimeNumber> {
match self.nodes.get_node(node) { match self.nodes.get_node(node) {
Tag::Constant { bytes, ty } => { Tag::Constant { bytes, ty } => {
let ty = let ty = self.intern_pool.from_ast1_type(AMD64_POINTER_BITS, ty);
self.intern_pool.from_ast1_type(AMD64_POINTER_BITS, ty); let number = crate::ast2::interned_type_and_value_to_comptime_number(
let number =
crate::ast2::interned_type_and_value_to_comptime_number(
&self.intern_pool, &self.intern_pool,
AMD64_POINTER_BITS, AMD64_POINTER_BITS,
ty, ty,
@ -2258,17 +2038,14 @@ impl Tree {
|_: &mut Tree, _| {}, |_: &mut Tree, _| {},
|tree: &mut Tree, node| { |tree: &mut Tree, node| {
if let Ok(value) = tree.fold_comptime_inner(node, false) { if let Ok(value) = tree.fold_comptime_inner(node, false) {
let (value, ty) = let (value, ty) = crate::ast2::comptime_number_to_interned_type_and_value(
crate::ast2::comptime_number_to_interned_type_and_value(
&mut tree.intern_pool, &mut tree.intern_pool,
AMD64_POINTER_BITS, AMD64_POINTER_BITS,
value, value,
); );
let ty = let ty = tree.intern_pool.as_ast1_type(AMD64_POINTER_BITS, ty);
tree.intern_pool.as_ast1_type(AMD64_POINTER_BITS, ty);
*tree.nodes.get_node_mut(node) = *tree.nodes.get_node_mut(node) = Tag::Constant { bytes: value, ty };
Tag::Constant { bytes: value, ty };
} }
}, },
) )
@ -2283,10 +2060,8 @@ impl Tree {
if self.is_node_comptime(decl, check_declrefs) { if self.is_node_comptime(decl, check_declrefs) {
match self.nodes.get_node(decl) { match self.nodes.get_node(decl) {
Tag::Constant { bytes, ty } => { Tag::Constant { bytes, ty } => {
let ty = let ty = self.intern_pool.from_ast1_type(AMD64_POINTER_BITS, ty);
self.intern_pool.from_ast1_type(AMD64_POINTER_BITS, ty); let number = crate::ast2::interned_type_and_value_to_comptime_number(
let number =
crate::ast2::interned_type_and_value_to_comptime_number(
&self.intern_pool, &self.intern_pool,
AMD64_POINTER_BITS, AMD64_POINTER_BITS,
ty, ty,
@ -2523,8 +2298,7 @@ impl Tree {
match self.nodes[node].clone() { match self.nodes[node].clone() {
Tag::FunctionProto { .. } => {} Tag::FunctionProto { .. } => {}
Tag::FunctionDecl { proto, body } => { Tag::FunctionDecl { proto, body } => {
let Tag::FunctionProto { return_type, .. } = self.nodes[proto] let Tag::FunctionProto { return_type, .. } = self.nodes[proto] else {
else {
unreachable!() unreachable!()
}; };
@ -2533,25 +2307,19 @@ impl Tree {
if let Some(peer_t) = body_t.equal_type(&ret_t) { if let Some(peer_t) = body_t.equal_type(&ret_t) {
if body_t == Type::comptime_number() { if body_t == Type::comptime_number() {
let Tag::Block { trailing_expr, .. } = self.nodes[body] let Tag::Block { trailing_expr, .. } = self.nodes[body] else {
else {
unreachable!() unreachable!()
}; };
if let Some(expr) = trailing_expr { if let Some(expr) = trailing_expr {
let ty = self.nodes.push_tag(Tag::PrimitiveType( let ty = self.nodes.push_tag(Tag::PrimitiveType(
self.intern_pool.from_ast1_type( self.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &peer_t),
AMD64_POINTER_BITS,
&peer_t,
),
)); ));
let expr = self.nodes.push_tag(Tag::ExplicitCast { let expr = self.nodes.push_tag(Tag::ExplicitCast {
lhs: expr, lhs: expr,
typename: ty, typename: ty,
}); });
let Tag::Block { trailing_expr, .. } = let Tag::Block { trailing_expr, .. } = &mut self.nodes[body] else {
&mut self.nodes[body]
else {
unreachable!() unreachable!()
}; };
*trailing_expr = Some(expr) *trailing_expr = Some(expr)
@ -2576,10 +2344,7 @@ impl Tree {
}; };
if bits < ty.bit_width() as u32 { if bits < ty.bit_width() as u32 {
errors.push(AnalysisError::new( errors.push(AnalysisError::new(
AnalysisErrorTag::InsufficientBitsInTypeForConstant( AnalysisErrorTag::InsufficientBitsInTypeForConstant(bits, ty.clone()),
bits,
ty.clone(),
),
)); ));
} }
} }

File diff suppressed because it is too large Load diff