split ast tag arrays
This commit is contained in:
parent
43c828d96f
commit
379769bc59
51
src/ast.rs
51
src/ast.rs
|
@ -1,9 +1,6 @@
|
|||
use std::num::NonZero;
|
||||
|
||||
use crate::{
|
||||
ast2::intern,
|
||||
string_table::{self, ImmOrIndex},
|
||||
};
|
||||
use crate::ast2::intern;
|
||||
|
||||
pub type Node = NonZero<u32>;
|
||||
|
||||
|
@ -298,21 +295,14 @@ impl core::fmt::Display for Type {
|
|||
Type::Integer(t) => t.fmt(f),
|
||||
Type::Floating(t) => t.fmt(f),
|
||||
Type::Pointer { constness, pointee } => {
|
||||
write!(
|
||||
f,
|
||||
"*{}{}",
|
||||
if *constness { "const " } else { "" },
|
||||
pointee
|
||||
)
|
||||
write!(f, "*{}{}", if *constness { "const " } else { "" }, pointee)
|
||||
}
|
||||
Type::Fn {
|
||||
parameter_types,
|
||||
return_type,
|
||||
} => {
|
||||
write!(f, "fn (")?;
|
||||
for param in
|
||||
parameter_types.iter().map(|p| Some(p)).intersperse(None)
|
||||
{
|
||||
for param in parameter_types.iter().map(|p| Some(p)).intersperse(None) {
|
||||
match param {
|
||||
Some(param) => param.fmt(f)?,
|
||||
None => write!(f, ", ")?,
|
||||
|
@ -351,13 +341,8 @@ impl Type {
|
|||
parameter_types: r_parameter_types,
|
||||
return_type: r_return_type,
|
||||
},
|
||||
) => {
|
||||
l_parameter_types == r_parameter_types
|
||||
&& l_return_type == r_return_type
|
||||
}
|
||||
_ => {
|
||||
core::mem::discriminant(self) == core::mem::discriminant(other)
|
||||
}
|
||||
) => l_parameter_types == r_parameter_types && l_return_type == r_return_type,
|
||||
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
|
||||
}
|
||||
}
|
||||
pub fn as_primitive_type(&self) -> Option<PrimitiveType> {
|
||||
|
@ -476,10 +461,9 @@ impl Type {
|
|||
|
||||
pub fn can_add_sub(&self) -> bool {
|
||||
match self {
|
||||
Type::ComptimeNumber
|
||||
| Type::Pointer { .. }
|
||||
| Type::Floating(_)
|
||||
| Type::Integer(_) => true,
|
||||
Type::ComptimeNumber | Type::Pointer { .. } | Type::Floating(_) | Type::Integer(_) => {
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -501,10 +485,9 @@ impl Type {
|
|||
}
|
||||
pub fn can_cmp(&self) -> bool {
|
||||
match self {
|
||||
Type::ComptimeNumber
|
||||
| Type::Pointer { .. }
|
||||
| Type::Floating(_)
|
||||
| Type::Integer(_) => true,
|
||||
Type::ComptimeNumber | Type::Pointer { .. } | Type::Floating(_) | Type::Integer(_) => {
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -613,12 +596,7 @@ pub mod tree_visitor {
|
|||
pub fn new_range(start: Node, end: Node, pre: F1, post: F2) -> Self {
|
||||
Self::new_inner(start, End::Exclusive(end), pre, post)
|
||||
}
|
||||
pub fn new_range_inclusive(
|
||||
start: Node,
|
||||
end: Node,
|
||||
pre: F1,
|
||||
post: F2,
|
||||
) -> Self {
|
||||
pub fn new_range_inclusive(start: Node, end: Node, pre: F1, post: F2) -> Self {
|
||||
Self::new_inner(start, End::Inclusive(end), pre, post)
|
||||
}
|
||||
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
|
||||
pub fn visit_ok<T, E>(
|
||||
mut self,
|
||||
tree: &Tree,
|
||||
) -> core::result::Result<T, E>
|
||||
pub fn visit_ok<T, E>(mut self, tree: &Tree) -> core::result::Result<T, E>
|
||||
where
|
||||
F1: FnMut(&Tree, Node) -> core::result::Result<T, E>,
|
||||
F2: FnMut(&Tree, Node) -> core::result::Result<T, E>,
|
||||
|
|
|
@ -180,19 +180,14 @@ impl Display for KeyDisplay<'_> {
|
|||
pointee,
|
||||
flags,
|
||||
length,
|
||||
} => write!(
|
||||
f,
|
||||
"[{flags}{}; {length}]",
|
||||
self.ip.display_key(pointee)
|
||||
)?,
|
||||
} => write!(f, "[{flags}{}; {length}]", self.ip.display_key(pointee))?,
|
||||
Key::FunctionType {
|
||||
return_type,
|
||||
ref parameters,
|
||||
} => {
|
||||
write!(f, "fn (")?;
|
||||
|
||||
let mut iter =
|
||||
parameters.iter().map(|&ty| self.ip.display_key(ty));
|
||||
let mut iter = parameters.iter().map(|&ty| self.ip.display_key(ty));
|
||||
let Some(next) = iter.next() else {
|
||||
return Ok(());
|
||||
};
|
||||
|
@ -209,7 +204,10 @@ impl Display for KeyDisplay<'_> {
|
|||
packed,
|
||||
c_like,
|
||||
ref fields,
|
||||
} => todo!(),
|
||||
} => {
|
||||
_ = (decl, name, packed, c_like, fields);
|
||||
todo!()
|
||||
}
|
||||
Key::TrueValue => write!(f, "true")?,
|
||||
Key::FalseValue => write!(f, "false")?,
|
||||
}
|
||||
|
@ -293,9 +291,7 @@ impl PointerFlags {
|
|||
}
|
||||
|
||||
pub fn pack(self) -> u8 {
|
||||
(self.volatile as u8) << 0
|
||||
| (self.is_const as u8) << 1
|
||||
| (self.noalias as u8) << 2
|
||||
(self.volatile as u8) << 0 | (self.is_const as u8) << 1 | (self.noalias as u8) << 2
|
||||
}
|
||||
pub fn unpack(packed: u8) -> Self {
|
||||
Self {
|
||||
|
@ -325,9 +321,7 @@ impl StructFlags {
|
|||
}
|
||||
pub fn pack(self) -> u32 {
|
||||
assert!(self.num_fields < (1 << 30));
|
||||
(self.packed as u32) << 31
|
||||
| (self.c_like as u32) << 30
|
||||
| self.num_fields & Self::MASK
|
||||
(self.packed as u32) << 31 | (self.c_like as u32) << 30 | self.num_fields & Self::MASK
|
||||
}
|
||||
pub fn unpack(packed: u32) -> Self {
|
||||
Self {
|
||||
|
@ -648,11 +642,7 @@ impl InternPool {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn to_mir_type(
|
||||
&self,
|
||||
index: Index,
|
||||
_ptr_size: TypeInfo,
|
||||
) -> crate::mir::Type {
|
||||
pub fn to_mir_type(&self, index: Index, _ptr_size: TypeInfo) -> crate::mir::Type {
|
||||
use crate::mir::Type;
|
||||
match self.get_key(index) {
|
||||
Key::UIntType { bit_width: bits } => {
|
||||
|
@ -765,8 +755,7 @@ impl InternPool {
|
|||
Key::FunctionType { .. } => ptr_size,
|
||||
Key::StructType { packed, fields, .. } => {
|
||||
// TODO: c-like layout
|
||||
let (size, align) =
|
||||
fields.iter().fold((0, 0), |(size, align), (_name, ty)| {
|
||||
let (size, align) = fields.iter().fold((0, 0), |(size, align), (_name, ty)| {
|
||||
let field_size = self.size_of_type(*ty, ptr_size);
|
||||
let size = size + field_size.bitsize;
|
||||
|
||||
|
@ -791,11 +780,7 @@ impl InternPool {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn insert_ast1_type(
|
||||
&mut self,
|
||||
pointer_bits: u16,
|
||||
ty: &crate::ast::Type,
|
||||
) -> Index {
|
||||
pub fn insert_ast1_type(&mut self, pointer_bits: u16, ty: &crate::ast::Type) -> Index {
|
||||
match ty {
|
||||
crate::ast::Type::Bool => self.get_bool_type(),
|
||||
crate::ast::Type::ComptimeNumber => self.get_comptime_int_type(),
|
||||
|
@ -806,12 +791,8 @@ impl InternPool {
|
|||
Key::UIntType { bit_width: i.bits }
|
||||
}
|
||||
}),
|
||||
crate::ast::Type::Floating(crate::ast::FloatingType::Binary32) => {
|
||||
self.get_f32_type()
|
||||
}
|
||||
crate::ast::Type::Floating(crate::ast::FloatingType::Binary64) => {
|
||||
self.get_f64_type()
|
||||
}
|
||||
crate::ast::Type::Floating(crate::ast::FloatingType::Binary32) => self.get_f32_type(),
|
||||
crate::ast::Type::Floating(crate::ast::FloatingType::Binary64) => self.get_f64_type(),
|
||||
crate::ast::Type::Pointer { constness, pointee } => {
|
||||
let pointee = self.insert_ast1_type(pointer_bits, &pointee);
|
||||
self.get_or_insert(Key::PointerType {
|
||||
|
@ -827,8 +808,7 @@ impl InternPool {
|
|||
.iter()
|
||||
.map(|ty| self.insert_ast1_type(pointer_bits, ty))
|
||||
.collect::<Vec<_>>();
|
||||
let return_type =
|
||||
self.from_ast1_type(pointer_bits, &return_type);
|
||||
let return_type = self.from_ast1_type(pointer_bits, &return_type);
|
||||
self.get_or_insert(Key::FunctionType {
|
||||
return_type,
|
||||
parameters,
|
||||
|
@ -841,11 +821,7 @@ impl InternPool {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn from_ast1_type(
|
||||
&self,
|
||||
pointer_bits: u16,
|
||||
ty: &crate::ast::Type,
|
||||
) -> Index {
|
||||
pub fn from_ast1_type(&self, pointer_bits: u16, ty: &crate::ast::Type) -> Index {
|
||||
match ty {
|
||||
crate::ast::Type::Bool => self.get_bool_type(),
|
||||
crate::ast::Type::ComptimeNumber => self.get_comptime_int_type(),
|
||||
|
@ -856,12 +832,8 @@ impl InternPool {
|
|||
Key::UIntType { bit_width: i.bits }
|
||||
}
|
||||
}),
|
||||
crate::ast::Type::Floating(crate::ast::FloatingType::Binary32) => {
|
||||
self.get_f32_type()
|
||||
}
|
||||
crate::ast::Type::Floating(crate::ast::FloatingType::Binary64) => {
|
||||
self.get_f64_type()
|
||||
}
|
||||
crate::ast::Type::Floating(crate::ast::FloatingType::Binary32) => self.get_f32_type(),
|
||||
crate::ast::Type::Floating(crate::ast::FloatingType::Binary64) => self.get_f64_type(),
|
||||
crate::ast::Type::Pointer { constness, pointee } => {
|
||||
let pointee = self.from_ast1_type(pointer_bits, &pointee);
|
||||
self.get_assume_present(&Key::PointerType {
|
||||
|
@ -877,8 +849,7 @@ impl InternPool {
|
|||
.iter()
|
||||
.map(|ty| self.from_ast1_type(pointer_bits, ty))
|
||||
.collect::<Vec<_>>();
|
||||
let return_type =
|
||||
self.from_ast1_type(pointer_bits, &return_type);
|
||||
let return_type = self.from_ast1_type(pointer_bits, &return_type);
|
||||
self.get_assume_present(&Key::FunctionType {
|
||||
return_type,
|
||||
parameters,
|
||||
|
@ -891,34 +862,18 @@ impl InternPool {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn as_ast1_type(
|
||||
&self,
|
||||
pointer_bits: u16,
|
||||
index: Index,
|
||||
) -> crate::ast::Type {
|
||||
pub fn as_ast1_type(&self, pointer_bits: u16, index: Index) -> crate::ast::Type {
|
||||
use crate::ast::Type;
|
||||
match self.get_key(index) {
|
||||
Key::UIntType { bit_width: bits } => {
|
||||
Type::Integer(IntegralType::new(false, bits))
|
||||
}
|
||||
Key::SIntType { bit_width: bits } => {
|
||||
Type::Integer(IntegralType::new(true, bits))
|
||||
}
|
||||
Key::UIntType { bit_width: bits } => Type::Integer(IntegralType::new(false, bits)),
|
||||
Key::SIntType { bit_width: bits } => Type::Integer(IntegralType::new(true, bits)),
|
||||
Key::SimpleType { ty } => match ty {
|
||||
SimpleType::F32 => {
|
||||
Type::Floating(crate::ast::FloatingType::Binary32)
|
||||
}
|
||||
SimpleType::F64 => {
|
||||
Type::Floating(crate::ast::FloatingType::Binary64)
|
||||
}
|
||||
SimpleType::F32 => Type::Floating(crate::ast::FloatingType::Binary32),
|
||||
SimpleType::F64 => Type::Floating(crate::ast::FloatingType::Binary64),
|
||||
SimpleType::Bool => Type::Bool,
|
||||
SimpleType::Void => Type::Void,
|
||||
SimpleType::USize => {
|
||||
Type::Integer(IntegralType::new(false, pointer_bits))
|
||||
}
|
||||
SimpleType::ISize => {
|
||||
Type::Integer(IntegralType::new(true, pointer_bits))
|
||||
}
|
||||
SimpleType::USize => Type::Integer(IntegralType::new(false, pointer_bits)),
|
||||
SimpleType::ISize => Type::Integer(IntegralType::new(true, pointer_bits)),
|
||||
SimpleType::ComptimeInt => Type::comptime_number(),
|
||||
},
|
||||
Key::PointerType { pointee, flags } => Type::Pointer {
|
||||
|
@ -933,9 +888,7 @@ impl InternPool {
|
|||
.into_iter()
|
||||
.map(|i| self.as_ast1_type(pointer_bits, i))
|
||||
.collect(),
|
||||
return_type: Box::new(
|
||||
self.as_ast1_type(pointer_bits, return_type),
|
||||
),
|
||||
return_type: Box::new(self.as_ast1_type(pointer_bits, return_type)),
|
||||
},
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
|
@ -1008,12 +961,8 @@ impl InternPool {
|
|||
let words_idx = self.extend_words([start, len]);
|
||||
self.create_item(Tag::String, words_idx)
|
||||
}
|
||||
Key::SIntSmall { bits } => {
|
||||
self.create_item(Tag::SIntSmall, bits as u32)
|
||||
}
|
||||
Key::UIntSmall { bits } => {
|
||||
self.create_item(Tag::UIntSmall, bits as u32)
|
||||
}
|
||||
Key::SIntSmall { bits } => self.create_item(Tag::SIntSmall, 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::F64 { bits } => {
|
||||
let (lo, hi) = into_lo_hi_dwords(bits as u64);
|
||||
|
@ -1043,19 +992,12 @@ impl InternPool {
|
|||
self.create_item(Tag::NegativeInt, i)
|
||||
}
|
||||
|
||||
Key::UIntType { bit_width: bits } => {
|
||||
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::UIntType { bit_width: bits } => 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::PointerType { pointee, flags } => {
|
||||
let flags = flags.pack();
|
||||
let i =
|
||||
self.extend_words([pointee.index() as u32, flags as u32]);
|
||||
let i = self.extend_words([pointee.index() as u32, flags as u32]);
|
||||
self.create_item(Tag::PointerType, i)
|
||||
}
|
||||
Key::ArrayType {
|
||||
|
@ -1064,11 +1006,7 @@ impl InternPool {
|
|||
length,
|
||||
} => {
|
||||
let flags = flags.pack();
|
||||
let i = self.extend_words([
|
||||
pointee.index() as u32,
|
||||
flags as u32,
|
||||
length,
|
||||
]);
|
||||
let i = self.extend_words([pointee.index() as u32, flags as u32, length]);
|
||||
self.create_item(Tag::ArrayType, i)
|
||||
}
|
||||
Key::StructType {
|
||||
|
@ -1078,15 +1016,8 @@ impl InternPool {
|
|||
c_like,
|
||||
fields,
|
||||
} => {
|
||||
let flags =
|
||||
StructFlags::new(packed, c_like, fields.len() as u32)
|
||||
.pack();
|
||||
let i = self.extend_words([
|
||||
name.into_u32(),
|
||||
decl.into_u32(),
|
||||
flags,
|
||||
u32::MAX,
|
||||
]);
|
||||
let flags = StructFlags::new(packed, c_like, fields.len() as u32).pack();
|
||||
let i = self.extend_words([name.into_u32(), decl.into_u32(), flags, u32::MAX]);
|
||||
if !fields.is_empty() {
|
||||
let fields_offset = self.extend_words(
|
||||
fields
|
||||
|
@ -1109,9 +1040,7 @@ impl InternPool {
|
|||
|
||||
let start = self.push_word(info.pack());
|
||||
self.extend_words([return_type.into_u32()]);
|
||||
_ = self.extend_words(
|
||||
parameters.into_iter().map(|i| i.index() as u32),
|
||||
);
|
||||
_ = self.extend_words(parameters.into_iter().map(|i| i.index() as u32));
|
||||
|
||||
self.create_item(Tag::FunctionType, start)
|
||||
}
|
||||
|
@ -1150,9 +1079,7 @@ impl InternPool {
|
|||
let start = self.words[item.idx()];
|
||||
let len = self.words[item.idx() + 1];
|
||||
let str = unsafe {
|
||||
core::str::from_utf8_unchecked(
|
||||
&self.strings[start as usize..][..len as usize],
|
||||
)
|
||||
core::str::from_utf8_unchecked(&self.strings[start as usize..][..len as usize])
|
||||
};
|
||||
Key::String { str }
|
||||
}
|
||||
|
@ -1167,24 +1094,18 @@ impl InternPool {
|
|||
},
|
||||
Tag::F64 => {
|
||||
let idx = item.idx();
|
||||
let bits =
|
||||
from_lo_hi_dwords(self.words[idx], self.words[idx + 1]);
|
||||
let bits = from_lo_hi_dwords(self.words[idx], self.words[idx + 1]);
|
||||
Key::F64 {
|
||||
bits: f64::from_le_bytes(bits.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
Tag::SInt64 => {
|
||||
let bits = from_lo_hi_dwords(
|
||||
self.words[item.idx()],
|
||||
self.words[item.idx() + 1],
|
||||
) as i64;
|
||||
let bits =
|
||||
from_lo_hi_dwords(self.words[item.idx()], self.words[item.idx() + 1]) as i64;
|
||||
Key::SInt64 { bits }
|
||||
}
|
||||
Tag::UInt64 => {
|
||||
let bits = from_lo_hi_dwords(
|
||||
self.words[item.idx()],
|
||||
self.words[item.idx() + 1],
|
||||
);
|
||||
let bits = from_lo_hi_dwords(self.words[item.idx()], self.words[item.idx() + 1]);
|
||||
Key::UInt64 { bits }
|
||||
}
|
||||
Tag::NegativeInt => {
|
||||
|
@ -1218,15 +1139,13 @@ impl InternPool {
|
|||
}
|
||||
Tag::PointerType => {
|
||||
let pointee = Index::new(self.words[item.idx()]);
|
||||
let flags =
|
||||
PointerFlags::unpack(self.words[item.idx() + 1] as u8);
|
||||
let flags = PointerFlags::unpack(self.words[item.idx() + 1] as u8);
|
||||
|
||||
Key::PointerType { pointee, flags }
|
||||
}
|
||||
Tag::ArrayType => {
|
||||
let pointee = Index::new(self.words[item.idx()]);
|
||||
let flags =
|
||||
PointerFlags::unpack(self.words[item.idx() + 1] as u8);
|
||||
let flags = PointerFlags::unpack(self.words[item.idx() + 1] as u8);
|
||||
let length = self.words[item.idx() + 2];
|
||||
|
||||
Key::ArrayType {
|
||||
|
@ -1237,12 +1156,11 @@ impl InternPool {
|
|||
}
|
||||
Tag::StructType => {
|
||||
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 fields = if flags.num_fields != 0 {
|
||||
let fields_offset = self.words[item.idx() + 3] as usize;
|
||||
let fields_end =
|
||||
fields_offset + flags.num_fields as usize * 2;
|
||||
let fields_end = fields_offset + flags.num_fields as usize * 2;
|
||||
|
||||
self.words[fields_offset..fields_end]
|
||||
.iter()
|
||||
|
@ -1322,9 +1240,7 @@ impl InternPool {
|
|||
|
||||
pub fn get_unsigned_integer(&mut self, value: u64) -> Index {
|
||||
let key = match value {
|
||||
_ if value <= u32::MAX as u64 => {
|
||||
Key::UIntSmall { bits: value as u32 }
|
||||
}
|
||||
_ if value <= u32::MAX as u64 => Key::UIntSmall { bits: value as u32 },
|
||||
_ => Key::UInt64 { bits: value as u64 },
|
||||
};
|
||||
|
||||
|
@ -1381,11 +1297,7 @@ impl InternPool {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn get_pointer_type(
|
||||
&mut self,
|
||||
pointee: Index,
|
||||
flags: Option<PointerFlags>,
|
||||
) -> Index {
|
||||
pub fn get_pointer_type(&mut self, pointee: Index, flags: Option<PointerFlags>) -> Index {
|
||||
let key = Key::PointerType {
|
||||
pointee,
|
||||
flags: flags.unwrap_or_default(),
|
||||
|
@ -1405,9 +1317,7 @@ impl InternPool {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn insert_or_replace_struct_type<
|
||||
I: IntoIterator<Item = (Index, Index)>,
|
||||
>(
|
||||
pub fn insert_or_replace_struct_type<I: IntoIterator<Item = (Index, Index)>>(
|
||||
&mut self,
|
||||
name: Index,
|
||||
decl: super::Index,
|
||||
|
@ -1422,8 +1332,7 @@ impl InternPool {
|
|||
c_like,
|
||||
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(
|
||||
fields
|
||||
.into_iter()
|
||||
|
@ -1439,11 +1348,7 @@ impl InternPool {
|
|||
self.get_or_insert(key)
|
||||
}
|
||||
|
||||
pub fn get_struct_type(
|
||||
&mut self,
|
||||
name: Index,
|
||||
decl: super::Index,
|
||||
) -> Index {
|
||||
pub fn get_struct_type(&mut self, name: Index, decl: super::Index) -> Index {
|
||||
let key = Key::StructType {
|
||||
name,
|
||||
decl,
|
||||
|
@ -1453,11 +1358,7 @@ impl InternPool {
|
|||
};
|
||||
self.get_or_insert(key)
|
||||
}
|
||||
pub fn try_get_struct_type(
|
||||
&self,
|
||||
name: Index,
|
||||
decl: super::Index,
|
||||
) -> Option<Index> {
|
||||
pub fn try_get_struct_type(&self, name: Index, decl: super::Index) -> Option<Index> {
|
||||
self.try_get_index(&Key::StructType {
|
||||
name,
|
||||
decl,
|
||||
|
|
1533
src/ast2/mod.rs
1533
src/ast2/mod.rs
File diff suppressed because it is too large
Load diff
|
@ -1,8 +1,7 @@
|
|||
use std::{io::Read, path::PathBuf, sync::Arc};
|
||||
use std::{io::Read, path::PathBuf};
|
||||
|
||||
use clap::Command;
|
||||
use compiler::{
|
||||
ast2::intern::InternPool,
|
||||
lexer::Tokenizer,
|
||||
parser::Tree,
|
||||
triples::{MirBuilder, IR},
|
||||
|
@ -29,8 +28,7 @@ fn main() {
|
|||
.subcommands([
|
||||
Command::new("ast").about("output AST."),
|
||||
Command::new("ast2").about("output AST."),
|
||||
Command::new("mir")
|
||||
.about("output machine-level intermediate representation."),
|
||||
Command::new("mir").about("output machine-level intermediate representation."),
|
||||
Command::new("ir").about("output intermediate representation."),
|
||||
Command::new("asm").about("output x86-64 assembly (intel syntax)."),
|
||||
]);
|
||||
|
@ -85,11 +83,7 @@ fn main() {
|
|||
} = mir;
|
||||
|
||||
for (name, mir) in functions {
|
||||
println!(
|
||||
"{}:\n{}",
|
||||
strings.get_str(name),
|
||||
mir.display(&strings)
|
||||
);
|
||||
println!("{}:\n{}", strings.get_str(name), mir.display(&strings));
|
||||
}
|
||||
}
|
||||
"asm" => {
|
||||
|
|
|
@ -31,10 +31,7 @@ pub mod triples;
|
|||
|
||||
pub fn tokenize<'a>(
|
||||
bytes: &'a [u8],
|
||||
) -> Result<
|
||||
lexer::Tokenizer<'a>,
|
||||
(lexer::Tokenizer<'a>, Vec<lexer::TokenizeError>),
|
||||
> {
|
||||
) -> Result<lexer::Tokenizer<'a>, (lexer::Tokenizer<'a>, Vec<lexer::TokenizeError>)> {
|
||||
lexer::Tokenizer::new_with_errors(bytes)
|
||||
}
|
||||
|
||||
|
|
1101
src/mir.rs
1101
src/mir.rs
File diff suppressed because it is too large
Load diff
425
src/parser.rs
425
src/parser.rs
|
@ -2,10 +2,7 @@ use itertools::Itertools;
|
|||
use num_bigint::{BigInt, BigUint};
|
||||
|
||||
use crate::{
|
||||
ast::{
|
||||
self, FloatingType, IntegralType, LetOrVar, Node, PrimitiveType, Tag,
|
||||
Type,
|
||||
},
|
||||
ast::{self, FloatingType, IntegralType, LetOrVar, Node, Tag, Type},
|
||||
ast2::intern::{self, AMD64_POINTER_BITS},
|
||||
common::NextIf,
|
||||
comptime::{self, ComptimeNumber},
|
||||
|
@ -147,17 +144,13 @@ impl Tree {
|
|||
.map(|decl| {
|
||||
let name = match self.nodes.get_node(*decl) {
|
||||
Tag::FunctionDecl { proto, .. } => {
|
||||
let Tag::FunctionProto { name, .. } =
|
||||
self.nodes.get_node(*proto)
|
||||
else {
|
||||
let Tag::FunctionProto { name, .. } = self.nodes.get_node(*proto) else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
self.get_ident_str(*name).unwrap().to_owned()
|
||||
}
|
||||
Tag::GlobalDecl { name, .. } => {
|
||||
self.get_ident_str(*name).unwrap().to_owned()
|
||||
}
|
||||
Tag::GlobalDecl { name, .. } => self.get_ident_str(*name).unwrap().to_owned(),
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
|
@ -243,10 +236,7 @@ impl Tree {
|
|||
IntegralType { signed, bits }
|
||||
}
|
||||
|
||||
fn parse_integral_constant(
|
||||
token: Token,
|
||||
lexeme: &str,
|
||||
) -> (BigInt, Option<IntegralType>) {
|
||||
fn parse_integral_constant(token: Token, lexeme: &str) -> (BigInt, Option<IntegralType>) {
|
||||
let radix = Radix::from_token(token).unwrap();
|
||||
|
||||
// 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 ty = match iter.clone().next() {
|
||||
Some((_, 'u')) | Some((_, 'i')) => Some(Self::parse_integral_type(
|
||||
&lexeme[iter.next().unwrap().0..],
|
||||
)),
|
||||
Some((_, 'u')) | Some((_, 'i')) => {
|
||||
Some(Self::parse_integral_type(&lexeme[iter.next().unwrap().0..]))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
|
@ -281,10 +271,7 @@ impl Tree {
|
|||
)
|
||||
}
|
||||
|
||||
fn parse_floating_constant(
|
||||
_token: Token,
|
||||
lexeme: &str,
|
||||
) -> (u64, FloatingType) {
|
||||
fn parse_floating_constant(_token: Token, lexeme: &str) -> (u64, FloatingType) {
|
||||
// let (dot, exp) = match token {
|
||||
// Token::DotFloatingExpConstant => (true, true),
|
||||
// Token::DotFloatingConstant => (true, false),
|
||||
|
@ -304,12 +291,8 @@ impl Tree {
|
|||
);
|
||||
|
||||
let bits = match lexeme.1 {
|
||||
FloatingType::Binary32 => {
|
||||
lexeme.0.parse::<f32>().unwrap().to_bits() as u64
|
||||
}
|
||||
FloatingType::Binary64 => {
|
||||
lexeme.0.parse::<f64>().unwrap().to_bits() as u64
|
||||
}
|
||||
FloatingType::Binary32 => lexeme.0.parse::<f32>().unwrap().to_bits() as u64,
|
||||
FloatingType::Binary64 => lexeme.0.parse::<f64>().unwrap().to_bits() as u64,
|
||||
};
|
||||
|
||||
(bits, lexeme.1)
|
||||
|
@ -328,10 +311,7 @@ impl Tree {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse_primitive_type(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_primitive_type(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
let token = tokens.next().ok_or(Error::UnexpectedEndOfTokens)?;
|
||||
let prim = match token.token() {
|
||||
Token::Void => intern::Index::VOID,
|
||||
|
@ -346,10 +326,7 @@ impl Tree {
|
|||
Ok(self.nodes.push_tag(Tag::PrimitiveType(prim)))
|
||||
}
|
||||
|
||||
pub fn parse_pointer(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_pointer(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
tokens.expect_token(Token::Star)?;
|
||||
let _constness = tokens.eat_token(Token::Const);
|
||||
let typename = self.parse_typename(tokens)?;
|
||||
|
@ -357,24 +334,19 @@ impl Tree {
|
|||
Ok(self.nodes.push_tag(Tag::Pointer { pointee: typename }))
|
||||
}
|
||||
|
||||
pub fn parse_typename(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_typename(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
match tokens.peek_token_or_err()?.token() {
|
||||
Token::Star => self.parse_pointer(tokens),
|
||||
Token::Ident => {
|
||||
let token = tokens.next().unwrap();
|
||||
match Self::try_parse_integral_type(token.lexeme())? {
|
||||
Some(int) => {
|
||||
let ty =
|
||||
self.intern_pool.get_int_type(int.signed, int.bits);
|
||||
let ty = self.intern_pool.get_int_type(int.signed, int.bits);
|
||||
|
||||
Ok(self.nodes.push_tag(Tag::IntegralType(ty)))
|
||||
}
|
||||
None => {
|
||||
let name =
|
||||
self.intern_pool.insert_string(token.lexeme());
|
||||
let name = self.intern_pool.insert_string(token.lexeme());
|
||||
Ok(self.nodes.push_tag(Tag::Ident { name }))
|
||||
}
|
||||
}
|
||||
|
@ -383,10 +355,7 @@ impl Tree {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse_var_decl(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_var_decl(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
let let_or_var = match tokens
|
||||
.eat_token(Token::Let)
|
||||
.or_else(|| tokens.eat_token(Token::Var))
|
||||
|
@ -406,8 +375,7 @@ impl Tree {
|
|||
None
|
||||
};
|
||||
|
||||
let name_str =
|
||||
self.intern_pool.get_str(self.ident_index(name)).to_owned();
|
||||
let name_str = self.intern_pool.get_str(self.ident_index(name)).to_owned();
|
||||
let decl = self.nodes.reserve_node();
|
||||
|
||||
let assignment = if tokens.eat_token(Token::Equal).is_some() {
|
||||
|
@ -435,10 +403,7 @@ impl Tree {
|
|||
|
||||
/// GLOBAL_DECL <-
|
||||
/// const IDENTIFIER (: TYPENAME)? = EXPR;
|
||||
pub fn parse_global_decl(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_global_decl(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
_ = tokens.expect_token(Token::Const)?;
|
||||
|
||||
let name = self.parse_ident(tokens)?;
|
||||
|
@ -483,10 +448,7 @@ impl Tree {
|
|||
|
||||
/// PARAMETER <-
|
||||
/// IDENTIFIER : TYPENAME
|
||||
pub fn parse_parameter(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_parameter(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
let name = self.parse_ident(tokens)?;
|
||||
tokens.expect_token(Token::Colon)?;
|
||||
let ty = self.parse_typename(tokens)?;
|
||||
|
@ -505,10 +467,7 @@ impl Tree {
|
|||
/// PARAMETER_LIST <-
|
||||
/// PARAMETER
|
||||
/// PARAMETER_LIST , PARAMETER
|
||||
pub fn parse_parameter_list(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_parameter_list(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
let mut parameters = Vec::new();
|
||||
|
||||
loop {
|
||||
|
@ -533,10 +492,7 @@ impl Tree {
|
|||
/// fn IDENTIFIER () -> TYPENAME
|
||||
/// fn IDENTIFIER ( PARAMETER_LIST ,? )
|
||||
/// fn IDENTIFIER ( PARAMETER_LIST ,? ) -> TYPENAME
|
||||
pub fn parse_fn_proto(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<(Node, Node)> {
|
||||
pub fn parse_fn_proto(&mut self, tokens: &mut TokenIterator) -> Result<(Node, Node)> {
|
||||
tokens.expect_token(Token::Fn)?;
|
||||
let name = self.parse_ident(tokens)?;
|
||||
tokens.expect_token(Token::OpenParens)?;
|
||||
|
@ -567,10 +523,7 @@ impl Tree {
|
|||
|
||||
/// FUNCTION_DECL <-
|
||||
/// FUNCTION_PROTO BLOCK
|
||||
pub fn parse_fn_decl(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_fn_decl(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
let (proto, name) = self.parse_fn_proto(tokens)?;
|
||||
|
||||
let decl = match self
|
||||
|
@ -580,10 +533,8 @@ impl Tree {
|
|||
Some(record) => record.node(),
|
||||
None => {
|
||||
let decl = self.nodes.reserve_node();
|
||||
self.st.insert_orderless_symbol(
|
||||
&self.get_ident_str(name).unwrap().to_owned(),
|
||||
decl,
|
||||
);
|
||||
self.st
|
||||
.insert_orderless_symbol(&self.get_ident_str(name).unwrap().to_owned(), decl);
|
||||
decl
|
||||
}
|
||||
};
|
||||
|
@ -593,9 +544,7 @@ impl Tree {
|
|||
let body = self.parse_block(tokens, Some(block))?;
|
||||
let unresolved = self
|
||||
.st
|
||||
.extract_orderless_if(|_, v| {
|
||||
self.nodes.get_node(v.node()) == &Tag::Undefined
|
||||
})
|
||||
.extract_orderless_if(|_, v| self.nodes.get_node(v.node()) == &Tag::Undefined)
|
||||
.collect::<Vec<_>>();
|
||||
self.st.into_parent();
|
||||
self.st.extend_orderless(unresolved);
|
||||
|
@ -669,10 +618,7 @@ impl Tree {
|
|||
/// ASSIGNMENT_EXPR <-
|
||||
/// BINARY_EXPRESSION
|
||||
/// BINARY_EXPRESSION ASSIGNMENT_OP EXPRESSION
|
||||
pub fn parse_assignment_expr(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_assignment_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
let lhs = self.parse_binary_expr(tokens, 0)?;
|
||||
|
||||
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::StarEqual => self.nodes.push_tag(Tag::Mul { lhs, rhs }),
|
||||
Token::SlashEqual => self.nodes.push_tag(Tag::Sub { lhs, rhs }),
|
||||
Token::PercentEqual => {
|
||||
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::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::PercentEqual => 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::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,
|
||||
_ => {
|
||||
unreachable!()
|
||||
|
@ -731,10 +665,7 @@ impl Tree {
|
|||
|
||||
/// RETURN_STATEMENT <-
|
||||
/// return EXPRESSION? ;
|
||||
pub fn try_parse_return_stmt(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Option<Node>> {
|
||||
pub fn try_parse_return_stmt(&mut self, tokens: &mut TokenIterator) -> Result<Option<Node>> {
|
||||
if tokens.eat_token(Token::Return).is_some() {
|
||||
let expr = if !tokens.is_next_token(Token::Semi) {
|
||||
let expr = Some(self.parse_expr(tokens)?);
|
||||
|
@ -755,10 +686,7 @@ impl Tree {
|
|||
/// RETURN_EXPRESSION
|
||||
/// VAR_DECL ;
|
||||
/// EXPRESSION ;
|
||||
pub fn parse_statement(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_statement(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
match tokens.peek_token_or_err()?.token() {
|
||||
Token::Return => Ok(self.try_parse_return_stmt(tokens)?.unwrap()),
|
||||
Token::Var | Token::Let => {
|
||||
|
@ -854,10 +782,7 @@ impl Tree {
|
|||
/// - POSTFIX_EXPR
|
||||
/// & POSTFIX_EXPR
|
||||
/// * POSTFIX_EXPR
|
||||
pub fn parse_prefix_expr(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_prefix_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
match tokens.peek_token_or_err()?.token() {
|
||||
Token::Bang => {
|
||||
_ = tokens.next();
|
||||
|
@ -886,10 +811,7 @@ impl Tree {
|
|||
/// AS_EXPR <-
|
||||
/// PREFIX_EXPR
|
||||
/// PREFIX_EXPR as TYPENAME
|
||||
pub fn parse_as_expr(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_as_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
let expr = self.parse_prefix_expr(tokens)?;
|
||||
|
||||
if tokens.eat_token(Token::As).is_some() {
|
||||
|
@ -906,10 +828,7 @@ impl Tree {
|
|||
/// ARGUMENT <-
|
||||
/// IDENT : EXPR
|
||||
/// EXPR
|
||||
pub fn parse_argument(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_argument(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
if tokens.is_next_token2(Token::Colon) {
|
||||
let name = self.parse_ident(tokens)?;
|
||||
_ = tokens.expect_token(Token::Colon)?;
|
||||
|
@ -927,10 +846,7 @@ impl Tree {
|
|||
/// ARGUMENT_LIST <-
|
||||
/// ARGUMENT
|
||||
/// ARGUMENT_LIST , ARGUMENT
|
||||
pub fn parse_argument_list(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_argument_list(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
let mut arguments = Vec::new();
|
||||
|
||||
loop {
|
||||
|
@ -954,10 +870,7 @@ impl Tree {
|
|||
/// PRIMARY_EXPR
|
||||
/// PRIMARY_EXPR ( )
|
||||
/// PRIMARY_EXPR ( ARGUMENT_LIST )
|
||||
pub fn parse_postfix_expr(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_postfix_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
let lhs = self.parse_primary_expr(tokens)?;
|
||||
|
||||
if tokens.eat_token(Token::OpenParens).is_some() {
|
||||
|
@ -983,10 +896,7 @@ impl Tree {
|
|||
/// FLOATING_CONSTANT
|
||||
/// ( EXPRESSION )
|
||||
/// { STATEMENT* EXPRESSION? }
|
||||
pub fn parse_primary_expr(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_primary_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
let token = tokens.peek_token_or_err()?;
|
||||
match token.token() {
|
||||
Token::Ident => {
|
||||
|
@ -995,16 +905,12 @@ impl Tree {
|
|||
let name = ident.lexeme();
|
||||
if let Some(record) = self.st.find_ordered_symbol(name) {
|
||||
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())))
|
||||
} else {
|
||||
let node = self
|
||||
.st
|
||||
.insert_orderless_symbol(
|
||||
name,
|
||||
self.nodes.reserve_node(),
|
||||
)
|
||||
.insert_orderless_symbol(name, self.nodes.reserve_node())
|
||||
.node();
|
||||
|
||||
Ok(self.nodes.push_tag(Tag::GlobalRef(node)))
|
||||
|
@ -1015,10 +921,7 @@ impl Tree {
|
|||
| Token::IntegerOctConstant
|
||||
| Token::IntegerConstant => {
|
||||
_ = tokens.next();
|
||||
let (bits, ty) = Self::parse_integral_constant(
|
||||
token.token(),
|
||||
token.lexeme(),
|
||||
);
|
||||
let (bits, ty) = Self::parse_integral_constant(token.token(), token.lexeme());
|
||||
let (_, bytes) = bits.to_bytes_le();
|
||||
|
||||
const BUF_SIZE: usize = core::mem::size_of::<u64>();
|
||||
|
@ -1027,18 +930,15 @@ impl Tree {
|
|||
.copy_from_slice(&bytes[..bytes.len().min(BUF_SIZE)]);
|
||||
let bytes = match bytes.len() {
|
||||
0..2 => {
|
||||
let (buf, _) =
|
||||
buf.split_at(core::mem::size_of::<u32>());
|
||||
let (buf, _) = buf.split_at(core::mem::size_of::<u32>());
|
||||
self.intern_pool.get_unsigned_integer(
|
||||
u32::from_le_bytes(buf.try_into().unwrap()) as u64,
|
||||
)
|
||||
}
|
||||
0..4 => {
|
||||
let (buf, _) =
|
||||
buf.split_at(core::mem::size_of::<u64>());
|
||||
self.intern_pool.get_unsigned_integer(
|
||||
u64::from_le_bytes(buf.try_into().unwrap()),
|
||||
)
|
||||
let (buf, _) = buf.split_at(core::mem::size_of::<u64>());
|
||||
self.intern_pool
|
||||
.get_unsigned_integer(u64::from_le_bytes(buf.try_into().unwrap()))
|
||||
}
|
||||
0.. => self.intern_pool.insert_bytes(&bytes),
|
||||
};
|
||||
|
@ -1055,22 +955,15 @@ impl Tree {
|
|||
| Token::DotFloatingConstant
|
||||
| Token::DotFloatingExpConstant => {
|
||||
_ = tokens.next();
|
||||
let (bits, ty) = Self::parse_floating_constant(
|
||||
token.token(),
|
||||
token.lexeme(),
|
||||
);
|
||||
let (bits, ty) = Self::parse_floating_constant(token.token(), token.lexeme());
|
||||
|
||||
let bytes = match ty {
|
||||
FloatingType::Binary32 => {
|
||||
self.intern_pool.get_or_insert(intern::Key::F32 {
|
||||
FloatingType::Binary32 => self.intern_pool.get_or_insert(intern::Key::F32 {
|
||||
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),
|
||||
})
|
||||
}
|
||||
}),
|
||||
};
|
||||
|
||||
Ok(self.nodes.push_tag(Tag::Constant {
|
||||
|
@ -1096,10 +989,7 @@ impl Tree {
|
|||
/// BLOCK
|
||||
/// EXPR
|
||||
/// EXPR ;
|
||||
pub fn parse_expr_or_stmt_or_block(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_expr_or_stmt_or_block(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
let peek = tokens.peek_token_or_err()?;
|
||||
let body = match peek.token() {
|
||||
// block
|
||||
|
@ -1130,10 +1020,7 @@ impl Tree {
|
|||
|
||||
/// ELSE_EXPR <-
|
||||
/// 'else' (IF_EXPR | EXPR_OR_STATEMENT_OR_BLOCK)
|
||||
pub fn try_parse_else_expr(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Option<Node>> {
|
||||
pub fn try_parse_else_expr(&mut self, tokens: &mut TokenIterator) -> Result<Option<Node>> {
|
||||
if tokens.eat_token(Token::Else).is_none() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
@ -1148,10 +1035,7 @@ impl Tree {
|
|||
|
||||
/// IF_EXPR <-
|
||||
/// 'if' ( EXPR ) EXPR_OR_STATEMENT_OR_BLOCK ELSE_EXPR?
|
||||
pub fn try_parse_if_expr(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Option<Node>> {
|
||||
pub fn try_parse_if_expr(&mut self, tokens: &mut TokenIterator) -> Result<Option<Node>> {
|
||||
if tokens.eat_token(Token::If).is_none() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
@ -1175,10 +1059,7 @@ impl Tree {
|
|||
|
||||
/// IF_EXPR <-
|
||||
/// 'if' ( EXPR ) EXPR_OR_STATEMENT_OR_BLOCK ELSE_EXPR?
|
||||
pub fn parse_if_expr(
|
||||
&mut self,
|
||||
tokens: &mut TokenIterator,
|
||||
) -> Result<Node> {
|
||||
pub fn parse_if_expr(&mut self, tokens: &mut TokenIterator) -> Result<Node> {
|
||||
self.try_parse_if_expr(tokens)?
|
||||
.ok_or(Error::ExpectedTokenNotFound(Token::If))
|
||||
}
|
||||
|
@ -1228,9 +1109,7 @@ impl Tree {
|
|||
fn get_typename_str(&self, node: Node) -> Option<String> {
|
||||
match self.nodes.get_node(node) {
|
||||
Tag::IntegralType(i) => Some(i.to_string()),
|
||||
Tag::Ident { name } => {
|
||||
Some(self.intern_pool.get_str(*name).to_owned())
|
||||
}
|
||||
Tag::Ident { name } => Some(self.intern_pool.get_str(*name).to_owned()),
|
||||
Tag::Pointer { pointee } => self.get_typename_str(*pointee),
|
||||
Tag::PrimitiveType(prim) => Some(prim.to_string()),
|
||||
_ => None,
|
||||
|
@ -1272,9 +1151,7 @@ impl Tree {
|
|||
}
|
||||
children
|
||||
}
|
||||
Tag::ReturnStmt { expr } => {
|
||||
expr.into_iter().cloned().collect::<Vec<_>>()
|
||||
}
|
||||
Tag::ReturnStmt { expr } => expr.into_iter().cloned().collect::<Vec<_>>(),
|
||||
&Tag::ExprStmt { expr } => {
|
||||
vec![expr]
|
||||
}
|
||||
|
@ -1321,10 +1198,7 @@ impl Tree {
|
|||
&Tag::ExplicitCast { lhs, typename } => {
|
||||
vec![lhs, typename]
|
||||
}
|
||||
Tag::Deref { lhs }
|
||||
| Tag::Ref { lhs }
|
||||
| Tag::Not { lhs }
|
||||
| Tag::Negate { lhs } => {
|
||||
Tag::Deref { lhs } | Tag::Ref { lhs } | Tag::Not { lhs } | Tag::Negate { lhs } => {
|
||||
vec![*lhs]
|
||||
}
|
||||
Tag::Or { lhs, rhs }
|
||||
|
@ -1371,17 +1245,8 @@ impl Tree {
|
|||
if let Some(parameters) = parameters {
|
||||
self.render_node(writer, parameters, indent)?;
|
||||
}
|
||||
write_indented!(
|
||||
indent,
|
||||
writer,
|
||||
"%{} = function_proto: {{",
|
||||
node.get()
|
||||
)?;
|
||||
write!(
|
||||
writer,
|
||||
"name: \"{}\"",
|
||||
self.get_ident_str(name).unwrap()
|
||||
)?;
|
||||
write_indented!(indent, writer, "%{} = function_proto: {{", node.get())?;
|
||||
write!(writer, "name: \"{}\"", self.get_ident_str(name).unwrap())?;
|
||||
if let Some(parameters) = parameters {
|
||||
write!(writer, ", parameters: %{}", parameters.get())?;
|
||||
}
|
||||
|
@ -1389,12 +1254,7 @@ impl Tree {
|
|||
writeln!(writer, "}}")
|
||||
}
|
||||
Tag::ParameterList { parameters } => {
|
||||
writeln_indented!(
|
||||
indent,
|
||||
writer,
|
||||
"%{} = ParameterList [",
|
||||
node.get()
|
||||
)?;
|
||||
writeln_indented!(indent, writer, "%{} = ParameterList [", node.get())?;
|
||||
for param in parameters {
|
||||
self.render_node(writer, param, indent + 1)?;
|
||||
}
|
||||
|
@ -1410,9 +1270,7 @@ impl Tree {
|
|||
self.get_typename_str(ty).unwrap()
|
||||
)
|
||||
}
|
||||
Tag::Pointer { .. }
|
||||
| Tag::IntegralType(_)
|
||||
| Tag::PrimitiveType(_) => {
|
||||
Tag::Pointer { .. } | Tag::IntegralType(_) | Tag::PrimitiveType(_) => {
|
||||
writeln_indented!(
|
||||
indent,
|
||||
writer,
|
||||
|
@ -1469,20 +1327,9 @@ impl Tree {
|
|||
Tag::ReturnStmt { expr } => {
|
||||
if let Some(expr) = expr {
|
||||
self.render_node(writer, expr, indent)?;
|
||||
writeln_indented!(
|
||||
indent,
|
||||
writer,
|
||||
"%{} = return %{};",
|
||||
node.get(),
|
||||
expr.get()
|
||||
)
|
||||
writeln_indented!(indent, writer, "%{} = return %{};", node.get(), expr.get())
|
||||
} else {
|
||||
writeln_indented!(
|
||||
indent,
|
||||
writer,
|
||||
"%{} = return;",
|
||||
node.get()
|
||||
)
|
||||
writeln_indented!(indent, writer, "%{} = return;", node.get())
|
||||
}
|
||||
}
|
||||
Tag::ExprStmt { expr } => self.render_node(writer, expr, indent),
|
||||
|
@ -1493,8 +1340,7 @@ impl Tree {
|
|||
assignment,
|
||||
} => {
|
||||
self.render_node(writer, name, indent)?;
|
||||
explicit_type
|
||||
.map(|node| self.render_node(writer, node, indent));
|
||||
explicit_type.map(|node| self.render_node(writer, node, indent));
|
||||
assignment.map(|node| self.render_node(writer, node, indent));
|
||||
|
||||
write_indented!(
|
||||
|
@ -1513,11 +1359,7 @@ impl Tree {
|
|||
self.get_ident_str(name).unwrap()
|
||||
)?;
|
||||
if let Some(ty) = explicit_type {
|
||||
write!(
|
||||
writer,
|
||||
", ty: {}",
|
||||
self.get_typename_str(ty).unwrap()
|
||||
)?;
|
||||
write!(writer, ", ty: {}", self.get_typename_str(ty).unwrap())?;
|
||||
}
|
||||
if let Some(assignment) = assignment {
|
||||
write!(writer, ", value: %{assignment}")?;
|
||||
|
@ -1541,11 +1383,7 @@ impl Tree {
|
|||
self.get_ident_str(name).unwrap()
|
||||
)?;
|
||||
if let Some(ty) = explicit_type {
|
||||
write!(
|
||||
writer,
|
||||
", ty: {}",
|
||||
self.get_typename_str(ty).unwrap()
|
||||
)?;
|
||||
write!(writer, ", ty: {}", self.get_typename_str(ty).unwrap())?;
|
||||
}
|
||||
write!(writer, ", value: %{assignment}")?;
|
||||
writeln!(writer, ");")?;
|
||||
|
@ -1555,26 +1393,13 @@ impl Tree {
|
|||
self.render_node(writer, lhs, indent)?;
|
||||
if let Some(rhs) = rhs {
|
||||
self.render_node(writer, rhs, indent)?;
|
||||
writeln_indented!(
|
||||
indent,
|
||||
writer,
|
||||
"%{node} = call (%{lhs})(%{rhs})"
|
||||
)
|
||||
writeln_indented!(indent, writer, "%{node} = call (%{lhs})(%{rhs})")
|
||||
} else {
|
||||
writeln_indented!(
|
||||
indent,
|
||||
writer,
|
||||
"%{node} = call (%{lhs})()"
|
||||
)
|
||||
writeln_indented!(indent, writer, "%{node} = call (%{lhs})()")
|
||||
}
|
||||
}
|
||||
Tag::ArgumentList { arguments } => {
|
||||
writeln_indented!(
|
||||
indent,
|
||||
writer,
|
||||
"%{} = ArgumentList [",
|
||||
node.get()
|
||||
)?;
|
||||
writeln_indented!(indent, writer, "%{} = ArgumentList [", node.get())?;
|
||||
for args in arguments {
|
||||
self.render_node(writer, args, indent + 1)?;
|
||||
}
|
||||
|
@ -1590,12 +1415,7 @@ impl Tree {
|
|||
self.get_ident_str(name).unwrap(),
|
||||
)
|
||||
} else {
|
||||
writeln_indented!(
|
||||
indent,
|
||||
writer,
|
||||
"%{} = %{expr},",
|
||||
node.get(),
|
||||
)
|
||||
writeln_indented!(indent, writer, "%{} = %{expr},", node.get(),)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1612,13 +1432,7 @@ impl Tree {
|
|||
}
|
||||
Tag::Deref { lhs } => {
|
||||
self.render_node(writer, lhs, indent)?;
|
||||
writeln_indented!(
|
||||
indent,
|
||||
writer,
|
||||
"%{} = deref(%{})",
|
||||
node.get(),
|
||||
lhs.get()
|
||||
)
|
||||
writeln_indented!(indent, writer, "%{} = deref(%{})", node.get(), lhs.get())
|
||||
}
|
||||
Tag::Ref { lhs } => {
|
||||
self.render_node(writer, lhs, indent)?;
|
||||
|
@ -1636,13 +1450,7 @@ impl Tree {
|
|||
}
|
||||
Tag::Negate { lhs } => {
|
||||
self.render_node(writer, lhs, indent)?;
|
||||
writeln_indented!(
|
||||
indent,
|
||||
writer,
|
||||
"%{} = not(%{})",
|
||||
node.get(),
|
||||
lhs.get()
|
||||
)
|
||||
writeln_indented!(indent, writer, "%{} = not(%{})", node.get(), lhs.get())
|
||||
}
|
||||
Tag::Or { lhs, rhs } => {
|
||||
self.render_node(writer, lhs, indent)?;
|
||||
|
@ -1950,10 +1758,7 @@ impl Tree {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn render<W: core::fmt::Write>(
|
||||
&mut self,
|
||||
writer: &mut W,
|
||||
) -> core::fmt::Result {
|
||||
pub fn render<W: core::fmt::Write>(&mut self, writer: &mut W) -> core::fmt::Result {
|
||||
for decl in &self.global_decls.clone() {
|
||||
self.render_node(writer, *decl, 0)?;
|
||||
}
|
||||
|
@ -1961,16 +1766,6 @@ impl Tree {
|
|||
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 {
|
||||
self.peer_type_of_nodes(lhs, rhs).expect({
|
||||
let at = self.type_of_node(lhs);
|
||||
|
@ -2031,9 +1826,7 @@ impl Tree {
|
|||
pointee: Box::new(self.type_of_node(*pointee)),
|
||||
},
|
||||
Tag::Constant { ty, .. } => ty.clone(),
|
||||
Tag::IntegralType(t) => {
|
||||
self.intern_pool.as_ast1_type(AMD64_POINTER_BITS, *t)
|
||||
}
|
||||
Tag::IntegralType(t) => self.intern_pool.as_ast1_type(AMD64_POINTER_BITS, *t),
|
||||
Tag::PrimitiveType(t) => match *t {
|
||||
intern::Index::F32 => Type::Floating(FloatingType::Binary32),
|
||||
intern::Index::F64 => Type::Floating(FloatingType::Binary64),
|
||||
|
@ -2054,9 +1847,7 @@ impl Tree {
|
|||
(Some(a), b) => self.peer_type_of_nodes(*a, *b).expect({
|
||||
let at = self.type_of_node(*a);
|
||||
let bt = self.type_of_node(*b);
|
||||
&format!(
|
||||
"incompatible types for %{a}({at}) and %{b}({bt})"
|
||||
)
|
||||
&format!("incompatible types for %{a}({at}) and %{b}({bt})")
|
||||
}),
|
||||
};
|
||||
|
||||
|
@ -2081,9 +1872,7 @@ impl Tree {
|
|||
|
||||
ty
|
||||
}
|
||||
Tag::CallExpr { lhs, .. } => {
|
||||
self.type_of_node(*lhs).return_type().unwrap().clone()
|
||||
}
|
||||
Tag::CallExpr { lhs, .. } => self.type_of_node(*lhs).return_type().unwrap().clone(),
|
||||
Tag::ExplicitCast { typename, .. } => self.type_of_node(*typename),
|
||||
Tag::Deref { lhs } => self.type_of_node(*lhs).remove_ptr().unwrap(),
|
||||
Tag::Ref { lhs } => self.type_of_node(*lhs).into_ptr(),
|
||||
|
@ -2099,15 +1888,11 @@ impl Tree {
|
|||
| Tag::And { lhs, rhs }
|
||||
| Tag::BitOr { lhs, rhs }
|
||||
| Tag::BitAnd { lhs, rhs }
|
||||
| Tag::BitXOr { lhs, rhs } => {
|
||||
self.peer_type_of_nodes(*lhs, *rhs).expect({
|
||||
| Tag::BitXOr { lhs, rhs } => self.peer_type_of_nodes(*lhs, *rhs).expect({
|
||||
let at = self.type_of_node(*lhs);
|
||||
let bt = self.type_of_node(*rhs);
|
||||
&format!(
|
||||
"incompatible types for %{lhs}({at}) and %{rhs}({bt})"
|
||||
)
|
||||
})
|
||||
}
|
||||
&format!("incompatible types for %{lhs}({at}) and %{rhs}({bt})")
|
||||
}),
|
||||
Tag::Shl { lhs, .. } => self.type_of_node(*lhs),
|
||||
Tag::Shr { lhs, .. } => self.type_of_node(*lhs),
|
||||
Tag::Eq { .. } => Type::bool(),
|
||||
|
@ -2181,9 +1966,7 @@ impl Tree {
|
|||
|
||||
is_comptime
|
||||
}
|
||||
Tag::Not { lhs } | Tag::Negate { lhs } => {
|
||||
self.is_node_comptime(*lhs, true)
|
||||
}
|
||||
Tag::Not { lhs } | Tag::Negate { lhs } => self.is_node_comptime(*lhs, true),
|
||||
Tag::Or { lhs, rhs }
|
||||
| Tag::And { lhs, rhs }
|
||||
| Tag::BitOr { lhs, rhs }
|
||||
|
@ -2202,8 +1985,7 @@ impl Tree {
|
|||
| Tag::Mul { lhs, rhs }
|
||||
| Tag::Rem { lhs, rhs }
|
||||
| Tag::Div { lhs, rhs } => {
|
||||
self.is_node_comptime(*lhs, true)
|
||||
&& self.is_node_comptime(*rhs, true)
|
||||
self.is_node_comptime(*lhs, true) && self.is_node_comptime(*rhs, true)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
|
@ -2212,10 +1994,8 @@ impl Tree {
|
|||
pub fn value_of_comptime_node(&self, node: Node) -> Option<ComptimeNumber> {
|
||||
match self.nodes.get_node(node) {
|
||||
Tag::Constant { bytes, ty } => {
|
||||
let ty =
|
||||
self.intern_pool.from_ast1_type(AMD64_POINTER_BITS, ty);
|
||||
let number =
|
||||
crate::ast2::interned_type_and_value_to_comptime_number(
|
||||
let ty = self.intern_pool.from_ast1_type(AMD64_POINTER_BITS, ty);
|
||||
let number = crate::ast2::interned_type_and_value_to_comptime_number(
|
||||
&self.intern_pool,
|
||||
AMD64_POINTER_BITS,
|
||||
ty,
|
||||
|
@ -2258,17 +2038,14 @@ impl Tree {
|
|||
|_: &mut Tree, _| {},
|
||||
|tree: &mut Tree, node| {
|
||||
if let Ok(value) = tree.fold_comptime_inner(node, false) {
|
||||
let (value, ty) =
|
||||
crate::ast2::comptime_number_to_interned_type_and_value(
|
||||
let (value, ty) = crate::ast2::comptime_number_to_interned_type_and_value(
|
||||
&mut tree.intern_pool,
|
||||
AMD64_POINTER_BITS,
|
||||
value,
|
||||
);
|
||||
let ty =
|
||||
tree.intern_pool.as_ast1_type(AMD64_POINTER_BITS, ty);
|
||||
let ty = tree.intern_pool.as_ast1_type(AMD64_POINTER_BITS, ty);
|
||||
|
||||
*tree.nodes.get_node_mut(node) =
|
||||
Tag::Constant { bytes: value, ty };
|
||||
*tree.nodes.get_node_mut(node) = Tag::Constant { bytes: value, ty };
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@ -2283,10 +2060,8 @@ impl Tree {
|
|||
if self.is_node_comptime(decl, check_declrefs) {
|
||||
match self.nodes.get_node(decl) {
|
||||
Tag::Constant { bytes, ty } => {
|
||||
let ty =
|
||||
self.intern_pool.from_ast1_type(AMD64_POINTER_BITS, ty);
|
||||
let number =
|
||||
crate::ast2::interned_type_and_value_to_comptime_number(
|
||||
let ty = self.intern_pool.from_ast1_type(AMD64_POINTER_BITS, ty);
|
||||
let number = crate::ast2::interned_type_and_value_to_comptime_number(
|
||||
&self.intern_pool,
|
||||
AMD64_POINTER_BITS,
|
||||
ty,
|
||||
|
@ -2523,8 +2298,7 @@ impl Tree {
|
|||
match self.nodes[node].clone() {
|
||||
Tag::FunctionProto { .. } => {}
|
||||
Tag::FunctionDecl { proto, body } => {
|
||||
let Tag::FunctionProto { return_type, .. } = self.nodes[proto]
|
||||
else {
|
||||
let Tag::FunctionProto { return_type, .. } = self.nodes[proto] else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
|
@ -2533,25 +2307,19 @@ impl Tree {
|
|||
|
||||
if let Some(peer_t) = body_t.equal_type(&ret_t) {
|
||||
if body_t == Type::comptime_number() {
|
||||
let Tag::Block { trailing_expr, .. } = self.nodes[body]
|
||||
else {
|
||||
let Tag::Block { trailing_expr, .. } = self.nodes[body] else {
|
||||
unreachable!()
|
||||
};
|
||||
if let Some(expr) = trailing_expr {
|
||||
let ty = self.nodes.push_tag(Tag::PrimitiveType(
|
||||
self.intern_pool.from_ast1_type(
|
||||
AMD64_POINTER_BITS,
|
||||
&peer_t,
|
||||
),
|
||||
self.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &peer_t),
|
||||
));
|
||||
let expr = self.nodes.push_tag(Tag::ExplicitCast {
|
||||
lhs: expr,
|
||||
typename: ty,
|
||||
});
|
||||
|
||||
let Tag::Block { trailing_expr, .. } =
|
||||
&mut self.nodes[body]
|
||||
else {
|
||||
let Tag::Block { trailing_expr, .. } = &mut self.nodes[body] else {
|
||||
unreachable!()
|
||||
};
|
||||
*trailing_expr = Some(expr)
|
||||
|
@ -2576,10 +2344,7 @@ impl Tree {
|
|||
};
|
||||
if bits < ty.bit_width() as u32 {
|
||||
errors.push(AnalysisError::new(
|
||||
AnalysisErrorTag::InsufficientBitsInTypeForConstant(
|
||||
bits,
|
||||
ty.clone(),
|
||||
),
|
||||
AnalysisErrorTag::InsufficientBitsInTypeForConstant(bits, ty.clone()),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
700
src/triples.rs
700
src/triples.rs
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue