split ast tag arrays

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

View file

@ -1,9 +1,6 @@
use std::num::NonZero;
use 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>,

View file

@ -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,

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,7 @@
use std::{io::Read, path::PathBuf, sync::Arc};
use std::{io::Read, path::PathBuf};
use clap::Command;
use 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" => {

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -2,10 +2,7 @@ use itertools::Itertools;
use num_bigint::{BigInt, BigUint};
use 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()),
));
}
}

File diff suppressed because it is too large Load diff