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 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>,
|
||||||
|
|
|
@ -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,19 +755,18 @@ 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;
|
|
||||||
|
|
||||||
let size = if packed {
|
let size = if packed {
|
||||||
size.next_multiple_of(field_size.bitalign)
|
size.next_multiple_of(field_size.bitalign)
|
||||||
} else {
|
} else {
|
||||||
size
|
size
|
||||||
};
|
};
|
||||||
let align = align.max(field_size.bitalign);
|
let align = align.max(field_size.bitalign);
|
||||||
(size, align)
|
(size, align)
|
||||||
});
|
});
|
||||||
|
|
||||||
TypeInfo {
|
TypeInfo {
|
||||||
bitsize: size,
|
bitsize: size,
|
||||||
|
@ -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,
|
||||||
|
|
1737
src/ast2/mod.rs
1737
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 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" => {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1105
src/mir.rs
1105
src/mir.rs
File diff suppressed because it is too large
Load diff
461
src/parser.rs
461
src/parser.rs
|
@ -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 {
|
||||||
}
|
bits: f64::from_bits(bits),
|
||||||
FloatingType::Binary64 => {
|
}),
|
||||||
self.intern_pool.get_or_insert(intern::Key::F64 {
|
|
||||||
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!("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::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,15 +1994,13 @@ 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 =
|
&self.intern_pool,
|
||||||
crate::ast2::interned_type_and_value_to_comptime_number(
|
AMD64_POINTER_BITS,
|
||||||
&self.intern_pool,
|
ty,
|
||||||
AMD64_POINTER_BITS,
|
*bytes,
|
||||||
ty,
|
);
|
||||||
*bytes,
|
|
||||||
);
|
|
||||||
|
|
||||||
Some(number)
|
Some(number)
|
||||||
}
|
}
|
||||||
|
@ -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 = 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) =
|
*tree.nodes.get_node_mut(node) = Tag::Constant { bytes: value, ty };
|
||||||
Tag::Constant { bytes: value, ty };
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -2283,15 +2060,13 @@ 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 =
|
&self.intern_pool,
|
||||||
crate::ast2::interned_type_and_value_to_comptime_number(
|
AMD64_POINTER_BITS,
|
||||||
&self.intern_pool,
|
ty,
|
||||||
AMD64_POINTER_BITS,
|
*bytes,
|
||||||
ty,
|
);
|
||||||
*bytes,
|
|
||||||
);
|
|
||||||
|
|
||||||
return Ok(number);
|
return Ok(number);
|
||||||
}
|
}
|
||||||
|
@ -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(),
|
|
||||||
),
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
748
src/triples.rs
748
src/triples.rs
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue