Compare commits

..

14 commits

Author SHA1 Message Date
Janis d743292710 compile help script
fix issue where mir interpreted intern indices as data for constants
2024-12-23 03:08:13 +01:00
Janis 7c01afbf2f TOO MUCH!!!! InternPool use everywhere in old ast 2024-12-23 02:34:02 +01:00
Janis 7801fefa17 mir function type and using internpool 2024-12-23 02:33:43 +01:00
Janis 3be955aebf internpool helpers/ fixes 2024-12-23 02:32:43 +01:00
Janis d9e6d99286 bit-length helper for integers and byte slices 2024-12-23 00:55:19 +01:00
Janis 6ba146f565 intern/key display printing 2024-12-23 00:54:19 +01:00
Janis 632729af52 InternPool bytes
make intern::Index a bit safer/clearer to use
added bytes to internpool
more helper functions for interning numbers/bytes/strings
2024-12-22 23:55:58 +01:00
Janis a3bee90ac3 mir/triples use internpool now for types 2024-12-22 22:25:01 +01:00
Janis 0994f4b187 fix comptime eval 2024-12-22 19:12:15 +01:00
Janis 96863e0397 cargo fmt 2024-12-22 19:01:22 +01:00
Janis 30ce12988d insert symbol on functiondecl
return ident from parse_fn_proto
2024-12-22 19:00:29 +01:00
Janis 7cea2452d1 from none doesn't need data to be passed 2024-12-22 18:58:20 +01:00
Janis 1df5429eab extracting ast2::intern into its own file 2024-12-22 18:57:19 +01:00
Janis 6494e827fb nightly fixes 22.12.24 2024-12-22 18:21:23 +01:00
18 changed files with 5145 additions and 2498 deletions

View file

@ -220,27 +220,27 @@ impl Register {
const fn bit_size(self) -> u32 { const fn bit_size(self) -> u32 {
use Register::*; use Register::*;
match self { match self {
ah | bh | ch | dh | al | bl | cl | dl | sil | dil | spl | bpl | r8b | r9b | r10b ah | bh | ch | dh | al | bl | cl | dl | sil | dil | spl | bpl
| r11b | r12b | r13b | r14b | r15b => 8, | r8b | r9b | r10b | r11b | r12b | r13b | r14b | r15b => 8,
ax | bx | cx | dx | si | di | sp | bp | ip | r8w | r9w | r10w | r11w | r12w | r13w ax | bx | cx | dx | si | di | sp | bp | ip | r8w | r9w | r10w
| r14w | r15w => 16, | r11w | r12w | r13w | r14w | r15w => 16,
eax | ebx | ecx | edx | esi | edi | esp | ebp | eip | r8d | r9d | r10d | r11d eax | ebx | ecx | edx | esi | edi | esp | ebp | eip | r8d | r9d
| r12d | r13d | r14d | r15d => 32, | r10d | r11d | r12d | r13d | r14d | r15d => 32,
rax | rbx | rcx | rdx | rsi | rdi | rsp | rbp | rip | r8 | r9 | r10 | r11 | r12 rax | rbx | rcx | rdx | rsi | rdi | rsp | rbp | rip | r8 | r9
| r13 | r14 | r15 => 64, | r10 | r11 | r12 | r13 | r14 | r15 => 64,
mm0 | mm1 | mm2 | mm3 | mm4 | mm5 | mm6 | mm7 => 64, mm0 | mm1 | mm2 | mm3 | mm4 | mm5 | mm6 | mm7 => 64,
st0 | st1 | st2 | st3 | st4 | st5 | st6 | st7 => 80, st0 | st1 | st2 | st3 | st4 | st5 | st6 | st7 => 80,
xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 | xmm8 | xmm9 | xmm10 | xmm11 xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 | xmm8
| xmm12 | xmm13 | xmm14 | xmm15 => 128, | xmm9 | xmm10 | xmm11 | xmm12 | xmm13 | xmm14 | xmm15 => 128,
ymm0 | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 | ymm7 | ymm8 | ymm9 | ymm10 | ymm11 ymm0 | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 | ymm7 | ymm8
| ymm12 | ymm13 | ymm14 | ymm15 => 256, | ymm9 | ymm10 | ymm11 | ymm12 | ymm13 | ymm14 | ymm15 => 256,
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -338,28 +338,30 @@ impl Register {
pub const SSE: [Register; 16] = { pub const SSE: [Register; 16] = {
use Register::*; use Register::*;
[ [
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10,
xmm14, xmm15, xmm11, xmm12, xmm13, xmm14, xmm15,
] ]
}; };
pub const fn is_gp(self) -> bool { pub const fn is_gp(self) -> bool {
use Register::*; use Register::*;
match self { match self {
rax | eax | ax | ah | al | rbx | ebx | bx | bh | bl | rcx | ecx | cx | ch | cl rax | eax | ax | ah | al | rbx | ebx | bx | bh | bl | rcx | ecx
| rdx | edx | dx | dh | dl | rsi | esi | si | sil | rdi | edi | di | dil | r8 | r8d | cx | ch | cl | rdx | edx | dx | dh | dl | rsi | esi | si
| r8w | r8b | r9 | r9d | r9w | r9b | r10 | r10d | r10w | r10b | r11 | r11d | r11w | sil | rdi | edi | di | dil | r8 | r8d | r8w | r8b | r9 | r9d
| r11b | r12 | r12d | r12w | r12b | r13 | r13d | r13w | r13b | r14 | r14d | r14w | r9w | r9b | r10 | r10d | r10w | r10b | r11 | r11d | r11w
| r14b | r15 | r15d | r15w | r15b => true, | r11b | r12 | r12d | r12w | r12b | r13 | r13d | r13w | r13b
| r14 | r14d | r14w | r14b | r15 | r15d | r15w | r15b => true,
_ => false, _ => false,
} }
} }
pub const fn is_sse(self) -> bool { pub const fn is_sse(self) -> bool {
use Register::*; use Register::*;
match self { match self {
xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 | xmm8 | xmm9 | xmm10 | xmm11 xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 | xmm8
| xmm12 | xmm13 | xmm14 | xmm15 | ymm0 | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 | xmm9 | xmm10 | xmm11 | xmm12 | xmm13 | xmm14 | xmm15 | ymm0
| ymm7 | ymm8 | ymm9 | ymm10 | ymm11 | ymm12 | ymm13 | ymm14 | ymm15 => true, | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 | ymm7 | ymm8 | ymm9
| ymm10 | ymm11 | ymm12 | ymm13 | ymm14 | ymm15 => true,
_ => false, _ => false,
} }
} }

View file

@ -1,6 +1,9 @@
use std::num::NonZero; use std::num::NonZero;
use crate::string_table::{self, ImmOrIndex}; use crate::{
ast2::intern,
string_table::{self, ImmOrIndex},
};
pub type Node = NonZero<u32>; pub type Node = NonZero<u32>;
@ -33,8 +36,8 @@ pub enum Tag {
PointerQualifier { PointerQualifier {
constness: bool, constness: bool,
}, },
IntegralType(IntegralType), IntegralType(intern::Index),
PrimitiveType(PrimitiveType), PrimitiveType(intern::Index),
FunctionDecl { FunctionDecl {
/// FunctionProto /// FunctionProto
proto: Node, proto: Node,
@ -42,10 +45,11 @@ pub enum Tag {
body: Node, body: Node,
}, },
Ident { Ident {
name: string_table::Index, name: intern::Index,
}, },
/// bytes might be an integer, float, double, or Bytes
Constant { Constant {
bytes: ImmOrIndex, bytes: intern::Index,
ty: Type, ty: Type,
}, },
Block { Block {
@ -294,14 +298,21 @@ 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!(f, "*{}{}", if *constness { "const " } else { "" }, pointee) write!(
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 parameter_types.iter().map(|p| Some(p)).intersperse(None) { for param in
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, ", ")?,
@ -340,8 +351,13 @@ 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, ) => {
_ => 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> { pub fn as_primitive_type(&self) -> Option<PrimitiveType> {
@ -460,9 +476,10 @@ impl Type {
pub fn can_add_sub(&self) -> bool { pub fn can_add_sub(&self) -> bool {
match self { match self {
Type::ComptimeNumber | Type::Pointer { .. } | Type::Floating(_) | Type::Integer(_) => { Type::ComptimeNumber
true | Type::Pointer { .. }
} | Type::Floating(_)
| Type::Integer(_) => true,
_ => false, _ => false,
} }
} }
@ -484,9 +501,10 @@ impl Type {
} }
pub fn can_cmp(&self) -> bool { pub fn can_cmp(&self) -> bool {
match self { match self {
Type::ComptimeNumber | Type::Pointer { .. } | Type::Floating(_) | Type::Integer(_) => { Type::ComptimeNumber
true | Type::Pointer { .. }
} | Type::Floating(_)
| Type::Integer(_) => true,
_ => false, _ => false,
} }
} }
@ -595,7 +613,12 @@ 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(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) 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 {
@ -694,7 +717,10 @@ pub mod tree_visitor {
} }
/// short-circuits on the first E /// 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 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>,

1541
src/ast2/intern.rs Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,8 @@
use std::{io::Read, path::PathBuf}; use std::{io::Read, path::PathBuf, sync::Arc};
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},
@ -11,6 +12,7 @@ fn ast_tree(tokens: &Tokenizer) -> Tree {
let mut tree = Tree::new(); let mut tree = Tree::new();
tree.parse(tokens.iter()).unwrap(); tree.parse(tokens.iter()).unwrap();
tree.fold_comptime(); tree.fold_comptime();
tree.intern_types();
tree tree
} }
@ -27,7 +29,8 @@ 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").about("output machine-level intermediate representation."), Command::new("mir")
.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)."),
]); ]);
@ -72,28 +75,34 @@ fn main() {
let mut ir = IR::new(); let mut ir = IR::new();
ir.build(&mut tree); ir.build(&mut tree);
let mut mir = MirBuilder::new(&ir, tree.strings); let mut mir = MirBuilder::new(&ir, tree.intern_pool);
mir.build(); mir.build();
let MirBuilder { let MirBuilder {
strings, functions, .. intern_pool: strings,
functions,
..
} = mir; } = mir;
for (name, mir) in functions { for (name, mir) in functions {
println!("{}:\n{}", strings.get_str(name), mir.display(&strings)); println!(
"{}:\n{}",
strings.get_str(name),
mir.display(&strings)
);
} }
} }
"asm" => { "asm" => {
let mut tree = ast_tree(&tokens); let mut tree = ast_tree(&tokens);
let mut ir = IR::new(); let mut ir = IR::new();
ir.build(&mut tree); _ = ir.build(&mut tree);
let mut mir = MirBuilder::new(&ir, tree.strings); let mut mir = MirBuilder::new(&ir, tree.intern_pool);
mir.build(); mir.build();
let MirBuilder { let MirBuilder {
globals, globals,
strings, intern_pool: strings,
functions, functions,
.. ..
} = mir; } = mir;

View file

@ -41,7 +41,8 @@ fn main() {
} }
eprintln!(":"); eprintln!(":");
for error in &errors { for error in &errors {
let lines = tokens.src().get_lines(error.range.start, error.range.end); let lines =
tokens.src().get_lines(error.range.start, error.range.end);
let location = tokens let location = tokens
.src() .src()
.get_source_span(error.range.start, error.range.end); .get_source_span(error.range.start, error.range.end);

View file

@ -72,7 +72,9 @@ pub fn is_oct_digit(ch: char) -> bool {
} }
pub fn is_hex_digit(ch: char) -> bool { pub fn is_hex_digit(ch: char) -> bool {
('0'..='9').contains(&ch) || ('a'..='f').contains(&ch) || ('A'..='F').contains(&ch) ('0'..='9').contains(&ch)
|| ('a'..='f').contains(&ch)
|| ('A'..='F').contains(&ch)
} }
/// Trait for only yielding the next item in the Iterator if it tests true for some predicate /// Trait for only yielding the next item in the Iterator if it tests true for some predicate

View file

@ -12,7 +12,10 @@ pub mod bigint {
pub struct BigInt(Vec<u32>); pub struct BigInt(Vec<u32>);
impl BigInt { impl BigInt {
pub fn parse_digits<C: IntoIterator<Item = char>>(text: C, radix: Radix) -> BigInt { pub fn parse_digits<C: IntoIterator<Item = char>>(
text: C,
radix: Radix,
) -> BigInt {
Self(parse_bigint(text.into_iter(), radix)) Self(parse_bigint(text.into_iter(), radix))
} }
pub fn from_u32(v: u32) -> BigInt { pub fn from_u32(v: u32) -> BigInt {
@ -237,9 +240,13 @@ pub mod bigint {
fn sub(mut self, rhs: Self) -> Self::Output { fn sub(mut self, rhs: Self) -> Self::Output {
if self.0.len() < rhs.0.len() { if self.0.len() < rhs.0.len() {
println!("extending self by {} zeroes", rhs.0.len() - self.0.len()); println!(
self.0 "extending self by {} zeroes",
.extend(core::iter::repeat(0).take(rhs.0.len() - self.0.len())); rhs.0.len() - self.0.len()
);
self.0.extend(
core::iter::repeat(0).take(rhs.0.len() - self.0.len()),
);
println!("self: {self:?}"); println!("self: {self:?}");
} }
sub_bigint(&mut self.0, &rhs.0); sub_bigint(&mut self.0, &rhs.0);
@ -497,7 +504,10 @@ pub mod bigint {
_ => { _ => {
if scalar.is_power_of_two() { if scalar.is_power_of_two() {
lhs.push(0); lhs.push(0);
shl_bitint(lhs.as_mut_slice(), scalar.trailing_zeros() as usize); shl_bitint(
lhs.as_mut_slice(),
scalar.trailing_zeros() as usize,
);
} else { } else {
let mut carry = 0; let mut carry = 0;
for a in lhs.iter_mut() { for a in lhs.iter_mut() {
@ -583,7 +593,10 @@ pub mod bigint {
#[allow(dead_code)] #[allow(dead_code)]
/// divident must be at least as wide as divisor /// divident must be at least as wide as divisor
/// returns (quotient, remainder) /// returns (quotient, remainder)
pub fn div_rem_bigint_ref(divident: &BigInt, divisor: &BigInt) -> (BigInt, BigInt) { pub fn div_rem_bigint_ref(
divident: &BigInt,
divisor: &BigInt,
) -> (BigInt, BigInt) {
if bigint_is_zero(&divisor.0) { if bigint_is_zero(&divisor.0) {
panic!("divide by zero!"); panic!("divide by zero!");
} }
@ -601,7 +614,8 @@ pub mod bigint {
if divisor.is_power_of_two() { if divisor.is_power_of_two() {
let exp = divisor.trailing_zeros(); let exp = divisor.trailing_zeros();
let (div, rem) = divident.0.split_at(exp.div_floor(u32::BITS as usize)); let (div, rem) =
divident.0.split_at(exp.div_floor(u32::BITS as usize));
let (mut div, mut rem) = (div.to_vec(), rem.to_vec()); let (mut div, mut rem) = (div.to_vec(), rem.to_vec());
shr_bitint(&mut div, exp % u32::BITS as usize); shr_bitint(&mut div, exp % u32::BITS as usize);
@ -627,7 +641,10 @@ pub mod bigint {
if shift == 0 { if shift == 0 {
div_rem_core(divident.clone(), &divisor.0) div_rem_core(divident.clone(), &divisor.0)
} else { } else {
let (q, r) = div_rem_core(divident.clone() << shift, &(divisor.clone() << shift).0); let (q, r) = div_rem_core(
divident.clone() << shift,
&(divisor.clone() << shift).0,
);
(q, r >> shift) (q, r >> shift)
} }
@ -636,7 +653,10 @@ pub mod bigint {
#[allow(dead_code)] #[allow(dead_code)]
/// divident must be at least as wide as divisor /// divident must be at least as wide as divisor
/// returns (quotient, remainder) /// returns (quotient, remainder)
pub fn div_rem_bigint(divident: BigInt, divisor: BigInt) -> (BigInt, BigInt) { pub fn div_rem_bigint(
divident: BigInt,
divisor: BigInt,
) -> (BigInt, BigInt) {
let divident = divident.normalised(); let divident = divident.normalised();
let mut divisor = divisor.normalised(); let mut divisor = divisor.normalised();
@ -657,7 +677,8 @@ pub mod bigint {
if divisor.is_power_of_two() { if divisor.is_power_of_two() {
let exp = divisor.trailing_zeros(); let exp = divisor.trailing_zeros();
let (div, rem) = divident.0.split_at(exp.div_floor(u32::BITS as usize)); let (div, rem) =
divident.0.split_at(exp.div_floor(u32::BITS as usize));
let (mut div, mut rem) = (div.to_vec(), rem.to_vec()); let (mut div, mut rem) = (div.to_vec(), rem.to_vec());
shr_bitint(&mut div, exp % u32::BITS as usize); shr_bitint(&mut div, exp % u32::BITS as usize);
@ -789,7 +810,9 @@ pub mod bigint {
// q0 is too large if: // q0 is too large if:
// [a2,a1,a0] < q0 * [b1,b0] // [a2,a1,a0] < q0 * [b1,b0]
// (r << BITS) + a2 < q0 * b1 // (r << BITS) + a2 < q0 * b1
while r <= u32::MAX as u64 && from_lo_hi_dwords(r as u32, a2) < q0 as u64 * b1 as u64 { while r <= u32::MAX as u64
&& from_lo_hi_dwords(r as u32, a2) < q0 as u64 * b1 as u64
{
q0 -= 1; q0 -= 1;
r += b0 as u64; r += b0 as u64;
} }
@ -1018,7 +1041,10 @@ pub mod bigint {
carry carry
} }
pub fn parse_bigint(text: impl Iterator<Item = char>, radix: Radix) -> Vec<u32> { pub fn parse_bigint(
text: impl Iterator<Item = char>,
radix: Radix,
) -> Vec<u32> {
let digits = text let digits = text
.filter_map(|c| match c { .filter_map(|c| match c {
'_' => None, '_' => None,
@ -1086,14 +1112,20 @@ pub mod bigint {
#[test] #[test]
fn parse() { fn parse() {
let bigint = BigInt::parse_digits("2_cafe_babe_dead_beef".chars(), Radix::Hex); let bigint = BigInt::parse_digits(
"2_cafe_babe_dead_beef".chars(),
Radix::Hex,
);
println!("{:#x?}", bigint); println!("{:#x?}", bigint);
let bigint = BigInt::parse_digits("f".chars(), Radix::Hex); let bigint = BigInt::parse_digits("f".chars(), Radix::Hex);
println!("{:#x?}", bigint); println!("{:#x?}", bigint);
} }
#[test] #[test]
fn add() { fn add() {
let a = BigInt::parse_digits("2_0000_0000_0000_0000".chars(), Radix::Hex); let a = BigInt::parse_digits(
"2_0000_0000_0000_0000".chars(),
Radix::Hex,
);
println!("{:#x?}", a); println!("{:#x?}", a);
let b = BigInt::parse_digits("cafebabe".chars(), Radix::Hex); let b = BigInt::parse_digits("cafebabe".chars(), Radix::Hex);
println!("{:#x?}", b); println!("{:#x?}", b);
@ -1111,7 +1143,10 @@ pub mod bigint {
} }
#[test] #[test]
fn overflowing_sub() { fn overflowing_sub() {
let a = BigInt::parse_digits("2_0000_0000_0000_0000".chars(), Radix::Hex); let a = BigInt::parse_digits(
"2_0000_0000_0000_0000".chars(),
Radix::Hex,
);
println!("{:#x?}", a); println!("{:#x?}", a);
let b = BigInt::parse_digits("ffff_ffff".chars(), Radix::Hex); let b = BigInt::parse_digits("ffff_ffff".chars(), Radix::Hex);
println!("{:#x?}", b); println!("{:#x?}", b);
@ -1120,7 +1155,8 @@ pub mod bigint {
} }
#[test] #[test]
fn shr() { fn shr() {
let mut a = BigInt::parse_digits("cafe_babe_0000".chars(), Radix::Hex); let mut a =
BigInt::parse_digits("cafe_babe_0000".chars(), Radix::Hex);
print!("{:0>8x?} >> 32 ", a); print!("{:0>8x?} >> 32 ", a);
shr_bitint(&mut a.0, 32); shr_bitint(&mut a.0, 32);
println!("{:0>8x?}", a); println!("{:0>8x?}", a);
@ -1152,7 +1188,9 @@ pub mod bigint {
pub mod bigsint { pub mod bigsint {
use std::{ use std::{
cmp::Ordering, cmp::Ordering,
ops::{Add, AddAssign, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub, SubAssign}, ops::{
Add, AddAssign, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub, SubAssign,
},
}; };
use super::bigint::{self, *}; use super::bigint::{self, *};
@ -1295,11 +1333,13 @@ pub mod bigsint {
match (self.sign, rhs.sign) { match (self.sign, rhs.sign) {
(_, Sign::None) => self, (_, Sign::None) => self,
(Sign::None, _) => rhs, (Sign::None, _) => rhs,
(Sign::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => Self { (Sign::Positive, Sign::Positive)
| (Sign::Negative, Sign::Negative) => Self {
sign: self.sign, sign: self.sign,
bigint: self.bigint + rhs.bigint, bigint: self.bigint + rhs.bigint,
}, },
(Sign::Positive, Sign::Negative) | (Sign::Negative, Sign::Positive) => { (Sign::Positive, Sign::Negative)
| (Sign::Negative, Sign::Positive) => {
match self.bigint.cmp(&rhs.bigint) { match self.bigint.cmp(&rhs.bigint) {
Ordering::Less => Self { Ordering::Less => Self {
sign: rhs.sign, sign: rhs.sign,
@ -1321,11 +1361,13 @@ pub mod bigsint {
fn add(self, rhs: u32) -> Self::Output { fn add(self, rhs: u32) -> Self::Output {
match self.sign { match self.sign {
Sign::Negative => match self.bigint.partial_cmp(&rhs).unwrap() { Sign::Negative => {
Ordering::Less => Self::positive(rhs - self.bigint), match self.bigint.partial_cmp(&rhs).unwrap() {
Ordering::Equal => Self::zero(), Ordering::Less => Self::positive(rhs - self.bigint),
Ordering::Greater => -Self::positive(self.bigint - rhs), Ordering::Equal => Self::zero(),
}, Ordering::Greater => -Self::positive(self.bigint - rhs),
}
}
Sign::None => Self::from_u32(rhs), Sign::None => Self::from_u32(rhs),
Sign::Positive => Self::positive(self.bigint + rhs), Sign::Positive => Self::positive(self.bigint + rhs),
} }
@ -1337,11 +1379,13 @@ pub mod bigsint {
fn add(self, rhs: u64) -> Self::Output { fn add(self, rhs: u64) -> Self::Output {
match self.sign { match self.sign {
Sign::Negative => match self.bigint.partial_cmp(&rhs).unwrap() { Sign::Negative => {
Ordering::Less => Self::positive(rhs - self.bigint), match self.bigint.partial_cmp(&rhs).unwrap() {
Ordering::Equal => Self::zero(), Ordering::Less => Self::positive(rhs - self.bigint),
Ordering::Greater => -Self::positive(self.bigint - rhs), Ordering::Equal => Self::zero(),
}, Ordering::Greater => -Self::positive(self.bigint - rhs),
}
}
Sign::None => Self::from_u64(rhs), Sign::None => Self::from_u64(rhs),
Sign::Positive => Self::positive(self.bigint + rhs), Sign::Positive => Self::positive(self.bigint + rhs),
} }
@ -1362,11 +1406,13 @@ pub mod bigsint {
match (self.sign, rhs.sign) { match (self.sign, rhs.sign) {
(_, Sign::None) => self, (_, Sign::None) => self,
(Sign::None, _) => -rhs, (Sign::None, _) => -rhs,
(Sign::Positive, Sign::Negative) | (Sign::Negative, Sign::Positive) => Self { (Sign::Positive, Sign::Negative)
| (Sign::Negative, Sign::Positive) => Self {
sign: self.sign, sign: self.sign,
bigint: self.bigint + rhs.bigint, bigint: self.bigint + rhs.bigint,
}, },
(Sign::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => { (Sign::Positive, Sign::Positive)
| (Sign::Negative, Sign::Negative) => {
match self.bigint.cmp(&rhs.bigint) { match self.bigint.cmp(&rhs.bigint) {
Ordering::Less => Self { Ordering::Less => Self {
sign: -self.sign, sign: -self.sign,
@ -1539,14 +1585,20 @@ impl ComptimeInt {
pub fn add(self, other: Self) -> Result<Self> { pub fn add(self, other: Self) -> Result<Self> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
match (a, b) { match (a, b) {
(ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => { (
ComptimeInt::Native { bits: a, ty },
ComptimeInt::Native { bits: b, .. },
) => {
let bits = a.checked_add(b).ok_or(Error::IntegerOverflow)?; let bits = a.checked_add(b).ok_or(Error::IntegerOverflow)?;
if bits & !ty.u128_bitmask() != 0 { if bits & !ty.u128_bitmask() != 0 {
return Err(Error::IntegerOverflow); return Err(Error::IntegerOverflow);
} }
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
} }
(ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => { (
ComptimeInt::BigInt { bits: a, ty },
ComptimeInt::BigInt { bits: b, .. },
) => {
let width = ty.bits - ty.signed as u16; let width = ty.bits - ty.signed as u16;
let bits = a + b; let bits = a + b;
if bits.bits() > width as u64 { if bits.bits() > width as u64 {
@ -1555,7 +1607,9 @@ impl ComptimeInt {
Ok(Self::BigInt { bits, ty }) Ok(Self::BigInt { bits, ty })
} }
} }
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a + b)), (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => {
Ok(Self::Comptime(a + b))
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -1565,14 +1619,20 @@ impl ComptimeInt {
pub fn sub(self, other: Self) -> Result<Self> { pub fn sub(self, other: Self) -> Result<Self> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
match (a, b) { match (a, b) {
(ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => { (
ComptimeInt::Native { bits: a, ty },
ComptimeInt::Native { bits: b, .. },
) => {
let bits = a.checked_sub(b).ok_or(Error::IntegerOverflow)?; let bits = a.checked_sub(b).ok_or(Error::IntegerOverflow)?;
if bits & !ty.u128_bitmask() != 0 { if bits & !ty.u128_bitmask() != 0 {
return Err(Error::IntegerOverflow); return Err(Error::IntegerOverflow);
} }
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
} }
(ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => { (
ComptimeInt::BigInt { bits: a, ty },
ComptimeInt::BigInt { bits: b, .. },
) => {
let width = ty.bits - ty.signed as u16; let width = ty.bits - ty.signed as u16;
let bits = a - b; let bits = a - b;
if bits.bits() > width as u64 { if bits.bits() > width as u64 {
@ -1581,7 +1641,9 @@ impl ComptimeInt {
Ok(Self::BigInt { bits, ty }) Ok(Self::BigInt { bits, ty })
} }
} }
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a - b)), (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => {
Ok(Self::Comptime(a - b))
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -1591,14 +1653,20 @@ impl ComptimeInt {
pub fn mul(self, other: Self) -> Result<Self> { pub fn mul(self, other: Self) -> Result<Self> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
match (a, b) { match (a, b) {
(ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => { (
ComptimeInt::Native { bits: a, ty },
ComptimeInt::Native { bits: b, .. },
) => {
let bits = a.checked_mul(b).ok_or(Error::IntegerOverflow)?; let bits = a.checked_mul(b).ok_or(Error::IntegerOverflow)?;
if bits & !ty.u128_bitmask() != 0 { if bits & !ty.u128_bitmask() != 0 {
return Err(Error::IntegerOverflow); return Err(Error::IntegerOverflow);
} }
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
} }
(ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => { (
ComptimeInt::BigInt { bits: a, ty },
ComptimeInt::BigInt { bits: b, .. },
) => {
let width = ty.bits - ty.signed as u16; let width = ty.bits - ty.signed as u16;
let bits = a * b; let bits = a * b;
if bits.bits() > width as u64 { if bits.bits() > width as u64 {
@ -1607,7 +1675,9 @@ impl ComptimeInt {
Ok(Self::BigInt { bits, ty }) Ok(Self::BigInt { bits, ty })
} }
} }
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a * b)), (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => {
Ok(Self::Comptime(a * b))
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -1617,14 +1687,20 @@ impl ComptimeInt {
pub fn div(self, other: Self) -> Result<Self> { pub fn div(self, other: Self) -> Result<Self> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
match (a, b) { match (a, b) {
(ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => { (
ComptimeInt::Native { bits: a, ty },
ComptimeInt::Native { bits: b, .. },
) => {
let bits = a.checked_div(b).ok_or(Error::IntegerOverflow)?; let bits = a.checked_div(b).ok_or(Error::IntegerOverflow)?;
if bits & !ty.u128_bitmask() != 0 { if bits & !ty.u128_bitmask() != 0 {
return Err(Error::IntegerOverflow); return Err(Error::IntegerOverflow);
} }
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
} }
(ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => { (
ComptimeInt::BigInt { bits: a, ty },
ComptimeInt::BigInt { bits: b, .. },
) => {
let width = ty.bits - ty.signed as u16; let width = ty.bits - ty.signed as u16;
let bits = a / b; let bits = a / b;
if bits.bits() > width as u64 { if bits.bits() > width as u64 {
@ -1633,7 +1709,9 @@ impl ComptimeInt {
Ok(Self::BigInt { bits, ty }) Ok(Self::BigInt { bits, ty })
} }
} }
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a / b)), (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => {
Ok(Self::Comptime(a / b))
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -1643,14 +1721,20 @@ impl ComptimeInt {
pub fn rem(self, other: Self) -> Result<Self> { pub fn rem(self, other: Self) -> Result<Self> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
match (a, b) { match (a, b) {
(ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => { (
ComptimeInt::Native { bits: a, ty },
ComptimeInt::Native { bits: b, .. },
) => {
let bits = a.checked_rem(b).ok_or(Error::IntegerOverflow)?; let bits = a.checked_rem(b).ok_or(Error::IntegerOverflow)?;
if bits & !ty.u128_bitmask() != 0 { if bits & !ty.u128_bitmask() != 0 {
return Err(Error::IntegerOverflow); return Err(Error::IntegerOverflow);
} }
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
} }
(ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => { (
ComptimeInt::BigInt { bits: a, ty },
ComptimeInt::BigInt { bits: b, .. },
) => {
let width = ty.bits - ty.signed as u16; let width = ty.bits - ty.signed as u16;
let bits = a % b; let bits = a % b;
if bits.bits() > width as u64 { if bits.bits() > width as u64 {
@ -1659,7 +1743,9 @@ impl ComptimeInt {
Ok(Self::BigInt { bits, ty }) Ok(Self::BigInt { bits, ty })
} }
} }
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a % b)), (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => {
Ok(Self::Comptime(a % b))
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -1669,15 +1755,23 @@ impl ComptimeInt {
pub fn bitand(self, other: Self) -> Result<Self> { pub fn bitand(self, other: Self) -> Result<Self> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
match (a, b) { match (a, b) {
(ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => { (
ComptimeInt::Native { bits: a, ty },
ComptimeInt::Native { bits: b, .. },
) => {
let bits = a.bitand(b); let bits = a.bitand(b);
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
} }
(ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => { (
ComptimeInt::BigInt { bits: a, ty },
ComptimeInt::BigInt { bits: b, .. },
) => {
let bits = a & b; let bits = a & b;
Ok(Self::BigInt { bits, ty }) Ok(Self::BigInt { bits, ty })
} }
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a & b)), (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => {
Ok(Self::Comptime(a & b))
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -1687,15 +1781,23 @@ impl ComptimeInt {
pub fn bitor(self, other: Self) -> Result<Self> { pub fn bitor(self, other: Self) -> Result<Self> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
match (a, b) { match (a, b) {
(ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => { (
ComptimeInt::Native { bits: a, ty },
ComptimeInt::Native { bits: b, .. },
) => {
let bits = a.bitor(b); let bits = a.bitor(b);
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
} }
(ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => { (
ComptimeInt::BigInt { bits: a, ty },
ComptimeInt::BigInt { bits: b, .. },
) => {
let bits = a | b; let bits = a | b;
Ok(Self::BigInt { bits, ty }) Ok(Self::BigInt { bits, ty })
} }
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a | b)), (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => {
Ok(Self::Comptime(a | b))
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -1705,15 +1807,23 @@ impl ComptimeInt {
pub fn bitxor(self, other: Self) -> Result<Self> { pub fn bitxor(self, other: Self) -> Result<Self> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
match (a, b) { match (a, b) {
(ComptimeInt::Native { bits: a, ty }, ComptimeInt::Native { bits: b, .. }) => { (
ComptimeInt::Native { bits: a, ty },
ComptimeInt::Native { bits: b, .. },
) => {
let bits = a.bitxor(b); let bits = a.bitxor(b);
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
} }
(ComptimeInt::BigInt { bits: a, ty }, ComptimeInt::BigInt { bits: b, .. }) => { (
ComptimeInt::BigInt { bits: a, ty },
ComptimeInt::BigInt { bits: b, .. },
) => {
let bits = a ^ b; let bits = a ^ b;
Ok(Self::BigInt { bits, ty }) Ok(Self::BigInt { bits, ty })
} }
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a ^ b)), (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => {
Ok(Self::Comptime(a ^ b))
}
_ => { _ => {
unreachable!() unreachable!()
} }
@ -1722,8 +1832,14 @@ impl ComptimeInt {
pub fn cmp(self, other: Self) -> Result<Ordering> { pub fn cmp(self, other: Self) -> Result<Ordering> {
let (a, b) = self.coalesce(other)?; let (a, b) = self.coalesce(other)?;
let ord = match (a, b) { let ord = match (a, b) {
(ComptimeInt::Native { bits: a, .. }, ComptimeInt::Native { bits: b, .. }) => a.cmp(&b), (
(ComptimeInt::BigInt { bits: a, .. }, ComptimeInt::BigInt { bits: b, .. }) => a.cmp(&b), ComptimeInt::Native { bits: a, .. },
ComptimeInt::Native { bits: b, .. },
) => a.cmp(&b),
(
ComptimeInt::BigInt { bits: a, .. },
ComptimeInt::BigInt { bits: b, .. },
) => a.cmp(&b),
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => a.cmp(&b), (ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => a.cmp(&b),
_ => { _ => {
unreachable!() unreachable!()
@ -1741,11 +1857,13 @@ impl ComptimeInt {
let bits = if ty.signed { let bits = if ty.signed {
(bits as i128) (bits as i128)
.checked_shl(shift) .checked_shl(shift)
.ok_or(Error::IntegerOverflow)? as u128 .ok_or(Error::IntegerOverflow)?
as u128
} else { } else {
(bits as u128) (bits as u128)
.checked_shl(shift) .checked_shl(shift)
.ok_or(Error::IntegerOverflow)? as u128 .ok_or(Error::IntegerOverflow)?
as u128
} & ty.u128_bitmask(); } & ty.u128_bitmask();
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
@ -1770,11 +1888,13 @@ impl ComptimeInt {
let bits = if ty.signed { let bits = if ty.signed {
(bits as i128) (bits as i128)
.checked_shr(shift) .checked_shr(shift)
.ok_or(Error::IntegerOverflow)? as u128 .ok_or(Error::IntegerOverflow)?
as u128
} else { } else {
(bits as u128) (bits as u128)
.checked_shr(shift) .checked_shr(shift)
.ok_or(Error::IntegerOverflow)? as u128 .ok_or(Error::IntegerOverflow)?
as u128
}; };
Ok(Self::Native { bits, ty }) Ok(Self::Native { bits, ty })
@ -1793,7 +1913,9 @@ impl ComptimeInt {
if ty.signed { if ty.signed {
return Err(Error::UnsignedNegation); return Err(Error::UnsignedNegation);
} }
let bits = (a as i128).checked_neg().ok_or(Error::IntegerOverflow)? as u128; let bits =
(a as i128).checked_neg().ok_or(Error::IntegerOverflow)?
as u128;
if bits & !ty.u128_bitmask() != 0 { if bits & !ty.u128_bitmask() != 0 {
return Err(Error::IntegerOverflow); return Err(Error::IntegerOverflow);
@ -1811,7 +1933,9 @@ impl ComptimeInt {
bits: !bits | ty.u128_bitmask(), bits: !bits | ty.u128_bitmask(),
ty, ty,
}), }),
ComptimeInt::BigInt { bits, ty } => Ok(Self::BigInt { bits: !bits, ty }), ComptimeInt::BigInt { bits, ty } => {
Ok(Self::BigInt { bits: !bits, ty })
}
ComptimeInt::Comptime(bigint) => Ok(Self::Comptime(!bigint)), ComptimeInt::Comptime(bigint) => Ok(Self::Comptime(!bigint)),
} }
} }
@ -1827,8 +1951,14 @@ impl ComptimeInt {
fn coalesce(self, other: Self) -> Result<(ComptimeInt, ComptimeInt)> { fn coalesce(self, other: Self) -> Result<(ComptimeInt, ComptimeInt)> {
match (self, other) { match (self, other) {
(lhs @ ComptimeInt::Native { ty: a_ty, .. }, ComptimeInt::Comptime(b)) (
| (lhs @ ComptimeInt::Native { ty: a_ty, .. }, ComptimeInt::BigInt { bits: b, .. }) => { lhs @ ComptimeInt::Native { ty: a_ty, .. },
ComptimeInt::Comptime(b),
)
| (
lhs @ ComptimeInt::Native { ty: a_ty, .. },
ComptimeInt::BigInt { bits: b, .. },
) => {
let b_signed = b.sign() == Sign::Minus; let b_signed = b.sign() == Sign::Minus;
if !a_ty.signed && b_signed { if !a_ty.signed && b_signed {
return Err(Error::IncompatibleTypes); return Err(Error::IncompatibleTypes);
@ -1845,8 +1975,14 @@ impl ComptimeInt {
}; };
Ok((lhs, Self::Native { bits: b, ty: a_ty })) Ok((lhs, Self::Native { bits: b, ty: a_ty }))
} }
(ComptimeInt::Comptime(b), rhs @ ComptimeInt::Native { ty: a_ty, .. }) (
| (ComptimeInt::BigInt { bits: b, .. }, rhs @ ComptimeInt::Native { ty: a_ty, .. }) => { ComptimeInt::Comptime(b),
rhs @ ComptimeInt::Native { ty: a_ty, .. },
)
| (
ComptimeInt::BigInt { bits: b, .. },
rhs @ ComptimeInt::Native { ty: a_ty, .. },
) => {
let b_signed = b.sign() == Sign::Minus; let b_signed = b.sign() == Sign::Minus;
if !a_ty.signed && b_signed { if !a_ty.signed && b_signed {
return Err(Error::IncompatibleTypes); return Err(Error::IncompatibleTypes);
@ -1863,7 +1999,10 @@ impl ComptimeInt {
}; };
Ok((Self::Native { bits: b, ty: a_ty }, rhs)) Ok((Self::Native { bits: b, ty: a_ty }, rhs))
} }
(lhs @ ComptimeInt::BigInt { ty, .. }, ComptimeInt::Comptime(b)) => { (
lhs @ ComptimeInt::BigInt { ty, .. },
ComptimeInt::Comptime(b),
) => {
let b_signed = b.sign() == Sign::Minus; let b_signed = b.sign() == Sign::Minus;
if !ty.signed && b_signed { if !ty.signed && b_signed {
return Err(Error::IncompatibleTypes); return Err(Error::IncompatibleTypes);
@ -1875,7 +2014,10 @@ impl ComptimeInt {
} }
Ok((lhs, Self::BigInt { bits: b, ty })) Ok((lhs, Self::BigInt { bits: b, ty }))
} }
(ComptimeInt::Comptime(b), rhs @ ComptimeInt::BigInt { ty, .. }) => { (
ComptimeInt::Comptime(b),
rhs @ ComptimeInt::BigInt { ty, .. },
) => {
let b_signed = b.sign() == Sign::Minus; let b_signed = b.sign() == Sign::Minus;
if !ty.signed && b_signed { if !ty.signed && b_signed {
return Err(Error::IncompatibleTypes); return Err(Error::IncompatibleTypes);
@ -1887,14 +2029,20 @@ impl ComptimeInt {
} }
Ok((Self::BigInt { bits: b, ty }, rhs)) Ok((Self::BigInt { bits: b, ty }, rhs))
} }
(lhs @ ComptimeInt::Native { ty: a, .. }, rhs @ ComptimeInt::Native { ty: b, .. }) => { (
lhs @ ComptimeInt::Native { ty: a, .. },
rhs @ ComptimeInt::Native { ty: b, .. },
) => {
if a == b { if a == b {
Ok((lhs, rhs)) Ok((lhs, rhs))
} else { } else {
Err(Error::IncompatibleTypes) Err(Error::IncompatibleTypes)
} }
} }
(lhs @ ComptimeInt::BigInt { ty: a, .. }, rhs @ ComptimeInt::BigInt { ty: b, .. }) => { (
lhs @ ComptimeInt::BigInt { ty: a, .. },
rhs @ ComptimeInt::BigInt { ty: b, .. },
) => {
if a == b { if a == b {
Ok((lhs, rhs)) Ok((lhs, rhs))
} else { } else {
@ -1915,36 +2063,56 @@ pub enum ComptimeFloat {
impl ComptimeFloat { impl ComptimeFloat {
pub fn add(self, other: Self) -> Result<ComptimeFloat> { pub fn add(self, other: Self) -> Result<ComptimeFloat> {
match (self, other) { match (self, other) {
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a + b)), (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => {
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a + b)), Ok(Self::Binary32(a + b))
}
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
Ok(Self::Binary64(a + b))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
pub fn sub(self, other: Self) -> Result<ComptimeFloat> { pub fn sub(self, other: Self) -> Result<ComptimeFloat> {
match (self, other) { match (self, other) {
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a - b)), (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => {
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a - b)), Ok(Self::Binary32(a - b))
}
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
Ok(Self::Binary64(a - b))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
pub fn mul(self, other: Self) -> Result<ComptimeFloat> { pub fn mul(self, other: Self) -> Result<ComptimeFloat> {
match (self, other) { match (self, other) {
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a * b)), (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => {
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a * b)), Ok(Self::Binary32(a * b))
}
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
Ok(Self::Binary64(a * b))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
pub fn div(self, other: Self) -> Result<ComptimeFloat> { pub fn div(self, other: Self) -> Result<ComptimeFloat> {
match (self, other) { match (self, other) {
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a / b)), (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => {
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a / b)), Ok(Self::Binary32(a / b))
}
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
Ok(Self::Binary64(a / b))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
pub fn rem(self, other: Self) -> Result<ComptimeFloat> { pub fn rem(self, other: Self) -> Result<ComptimeFloat> {
match (self, other) { match (self, other) {
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a % b)), (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => {
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a % b)), Ok(Self::Binary32(a % b))
}
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
Ok(Self::Binary64(a % b))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
@ -1956,8 +2124,12 @@ impl ComptimeFloat {
} }
pub fn cmp(self, other: Self) -> Result<Ordering> { pub fn cmp(self, other: Self) -> Result<Ordering> {
let ord = match (self, other) { let ord = match (self, other) {
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => a.partial_cmp(&b), (ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => {
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => a.partial_cmp(&b), a.partial_cmp(&b)
}
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
a.partial_cmp(&b)
}
_ => { _ => {
return Err(Error::IncompatibleTypes); return Err(Error::IncompatibleTypes);
} }
@ -2109,7 +2281,9 @@ impl ComptimeNumber {
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { // (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
// Ok(Self::Floating(a.sub(b)?)) // Ok(Self::Floating(a.sub(b)?))
// } // }
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a.bitand(b))), (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => {
Ok(Self::Bool(a.bitand(b)))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
@ -2121,7 +2295,9 @@ impl ComptimeNumber {
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { // (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
// Ok(Self::Floating(a.bitor(b)?)) // Ok(Self::Floating(a.bitor(b)?))
// } // }
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a.bitor(b))), (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => {
Ok(Self::Bool(a.bitor(b)))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
@ -2133,7 +2309,9 @@ impl ComptimeNumber {
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { // (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
// Ok(Self::Floating(a.bitxor(b)?)) // Ok(Self::Floating(a.bitxor(b)?))
// } // }
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a.bitxor(b))), (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => {
Ok(Self::Bool(a.bitxor(b)))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
@ -2169,7 +2347,9 @@ impl ComptimeNumber {
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { // (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
// Ok(Self::Floating(a.bitxor(b)?)) // Ok(Self::Floating(a.bitxor(b)?))
// } // }
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a || b)), (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => {
Ok(Self::Bool(a || b))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
@ -2181,23 +2361,35 @@ impl ComptimeNumber {
// (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => { // (ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
// Ok(Self::Floating(a.bitxor(b)?)) // Ok(Self::Floating(a.bitxor(b)?))
// } // }
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a && b)), (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => {
Ok(Self::Bool(a && b))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
pub fn eq(self, other: Self) -> Result<Self> { pub fn eq(self, other: Self) -> Result<Self> {
match (self, other) { match (self, other) {
(ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => Ok(Self::Bool(a == b)), (ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => {
(ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => Ok(Self::Bool(a == b)), Ok(Self::Bool(a == b))
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a == b)), }
(ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
Ok(Self::Bool(a == b))
}
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => {
Ok(Self::Bool(a == b))
}
_ => Err(Error::IncompatibleTypes), _ => Err(Error::IncompatibleTypes),
} }
} }
pub fn cmp(self, other: Self) -> Result<Ordering> { pub fn cmp(self, other: Self) -> Result<Ordering> {
let ord = match (self, other) { let ord = match (self, other) {
(ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => a.cmp(b)?, (ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => {
(ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => a.cmp(b)?, a.cmp(b)?
}
(ComptimeNumber::Floating(a), ComptimeNumber::Floating(b)) => {
a.cmp(b)?
}
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => a.cmp(&b), (ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => a.cmp(&b),
_ => { _ => {
return Err(Error::IncompatibleTypes); return Err(Error::IncompatibleTypes);
@ -2237,12 +2429,17 @@ impl ComptimeNumber {
match self { match self {
ComptimeNumber::Integral(i) => match i { ComptimeNumber::Integral(i) => match i {
ComptimeInt::Native { bits, .. } => Ok((bits != 0).into()), ComptimeInt::Native { bits, .. } => Ok((bits != 0).into()),
ComptimeInt::Comptime(bits) | ComptimeInt::BigInt { bits, .. } => { ComptimeInt::Comptime(bits)
| ComptimeInt::BigInt { bits, .. } => {
Ok((bits.sign() != Sign::NoSign).into()) Ok((bits.sign() != Sign::NoSign).into())
} }
}, },
ComptimeNumber::Floating(ComptimeFloat::Binary32(f)) => Ok((f != 0.0).into()), ComptimeNumber::Floating(ComptimeFloat::Binary32(f)) => {
ComptimeNumber::Floating(ComptimeFloat::Binary64(f)) => Ok((f != 0.0).into()), Ok((f != 0.0).into())
}
ComptimeNumber::Floating(ComptimeFloat::Binary64(f)) => {
Ok((f != 0.0).into())
}
a => Ok(a), a => Ok(a),
} }
} }
@ -2250,19 +2447,29 @@ impl ComptimeNumber {
pub fn into_int(self, ty: IntegralType) -> Result<Self> { pub fn into_int(self, ty: IntegralType) -> Result<Self> {
match self { match self {
ComptimeNumber::Integral(i) => match i { ComptimeNumber::Integral(i) => match i {
ComptimeInt::Native { bits, .. } => Ok((bits & ty.u128_bitmask(), ty).into()), ComptimeInt::Native { bits, .. } => {
ComptimeInt::Comptime(bits) | ComptimeInt::BigInt { bits, .. } => { Ok((bits & ty.u128_bitmask(), ty).into())
let max = BigUint::from(2u32).pow((ty.bits - ty.signed as u16) as u32); }
ComptimeInt::Comptime(bits)
| ComptimeInt::BigInt { bits, .. } => {
let max = BigUint::from(2u32)
.pow((ty.bits - ty.signed as u16) as u32);
let (sign, data) = bits.into_parts(); let (sign, data) = bits.into_parts();
let data = data.clamp(BigUint::ZERO, max); let data = data.clamp(BigUint::ZERO, max);
Ok((BigInt::from_biguint(sign, data), ty).into()) Ok((BigInt::from_biguint(sign, data), ty).into())
} }
}, },
ComptimeNumber::Bool(b) => Ok((b as u128 & ty.u128_bitmask(), ty).into()), ComptimeNumber::Bool(b) => {
Ok((b as u128 & ty.u128_bitmask(), ty).into())
}
ComptimeNumber::Floating(f) => match f { ComptimeNumber::Floating(f) => match f {
ComptimeFloat::Binary32(f) => Ok((f as u128 & ty.u128_bitmask(), ty).into()), ComptimeFloat::Binary32(f) => {
ComptimeFloat::Binary64(f) => Ok((f as u128 & ty.u128_bitmask(), ty).into()), Ok((f as u128 & ty.u128_bitmask(), ty).into())
}
ComptimeFloat::Binary64(f) => {
Ok((f as u128 & ty.u128_bitmask(), ty).into())
}
}, },
ComptimeNumber::Void => { ComptimeNumber::Void => {
return Err(Error::VoidConversion); return Err(Error::VoidConversion);
@ -2273,7 +2480,8 @@ impl ComptimeNumber {
let f = match self { let f = match self {
ComptimeNumber::Integral(i) => match i { ComptimeNumber::Integral(i) => match i {
ComptimeInt::Native { bits, .. } => bits as f64, ComptimeInt::Native { bits, .. } => bits as f64,
ComptimeInt::Comptime(bits) | ComptimeInt::BigInt { bits, .. } => { ComptimeInt::Comptime(bits)
| ComptimeInt::BigInt { bits, .. } => {
bits.to_f64().unwrap_or(f64::NAN) bits.to_f64().unwrap_or(f64::NAN)
} }
}, },

View file

@ -83,7 +83,11 @@ impl<'a> Chars<'a> {
SourceLocation::new(start_l, start_c) SourceLocation::new(start_l, start_c)
} }
pub fn get_source_span(&self, start: u32, end: u32) -> std::ops::Range<SourceLocation> { pub fn get_source_span(
&self,
start: u32,
end: u32,
) -> std::ops::Range<SourceLocation> {
let (start_l, start_c) = { let (start_l, start_c) = {
let range = self.get_from_to(0, start); let range = self.get_from_to(0, start);
range.chars().fold((1u32, 0u32), |(line, col), c| { range.chars().fold((1u32, 0u32), |(line, col), c| {
@ -134,12 +138,18 @@ impl<'a> Chars<'a> {
pub fn get_range(&self, range: core::ops::Range<u32>) -> &str { pub fn get_range(&self, range: core::ops::Range<u32>) -> &str {
unsafe { unsafe {
core::str::from_utf8_unchecked(&self.bytes[range.start as usize..range.end as usize]) core::str::from_utf8_unchecked(
&self.bytes[range.start as usize..range.end as usize],
)
} }
} }
pub fn get_from_to(&self, start: u32, end: u32) -> &str { pub fn get_from_to(&self, start: u32, end: u32) -> &str {
unsafe { core::str::from_utf8_unchecked(&self.bytes[start as usize..end as usize]) } unsafe {
core::str::from_utf8_unchecked(
&self.bytes[start as usize..end as usize],
)
}
} }
fn next_char(&mut self) -> Option<char> { fn next_char(&mut self) -> Option<char> {
@ -205,7 +215,12 @@ impl DelimitorConditions {
|| self.semis > cond.semis || self.semis > cond.semis
} }
fn from_i32s(braces: i32, parens: i32, brackets: i32, semis: Option<u32>) -> Self { fn from_i32s(
braces: i32,
parens: i32,
brackets: i32,
semis: Option<u32>,
) -> Self {
Self { Self {
braces: DelimitorCondition::from_i32(braces), braces: DelimitorCondition::from_i32(braces),
parens: DelimitorCondition::from_i32(parens), parens: DelimitorCondition::from_i32(parens),
@ -216,7 +231,10 @@ impl DelimitorConditions {
} }
impl<'a> TokenIterator<'a> { impl<'a> TokenIterator<'a> {
pub fn advance_until_before_token(&mut self, token: Token) -> Option<Token> { pub fn advance_until_before_token(
&mut self,
token: Token,
) -> Option<Token> {
while let Some(next) = self.peek_token() { while let Some(next) = self.peek_token() {
if next.token() == token { if next.token() == token {
return Some(token); return Some(token);
@ -226,7 +244,10 @@ impl<'a> TokenIterator<'a> {
None None
} }
pub fn advance_until_before_one_of(&mut self, tokens: &[Token]) -> Option<Token> { pub fn advance_until_before_one_of(
&mut self,
tokens: &[Token],
) -> Option<Token> {
while let Some(next) = self.peek_token() { while let Some(next) = self.peek_token() {
if tokens.contains(&next.token()) { if tokens.contains(&next.token()) {
return Some(next.token()); return Some(next.token());
@ -304,13 +325,19 @@ impl<'a> TokenIterator<'a> {
}) })
} }
fn advance_until_condition(&mut self, cond: DelimitorConditions) -> Option<()> { fn advance_until_condition(
&mut self,
cond: DelimitorConditions,
) -> Option<()> {
self.advance_past_condition(cond)?; self.advance_past_condition(cond)?;
_ = self.offset.saturating_sub(1); _ = self.offset.saturating_sub(1);
Some(()) Some(())
} }
fn advance_past_condition(&mut self, cond: DelimitorConditions) -> Option<()> { fn advance_past_condition(
&mut self,
cond: DelimitorConditions,
) -> Option<()> {
let mut braces = 0; let mut braces = 0;
let mut parens = 0; let mut parens = 0;
let mut brackets = 0; let mut brackets = 0;
@ -341,8 +368,12 @@ impl<'a> TokenIterator<'a> {
_ => { /* nada */ } _ => { /* nada */ }
} }
let current = let current = DelimitorConditions::from_i32s(
DelimitorConditions::from_i32s(braces, parens, brackets, cond.semis.map(|_| semis)); braces,
parens,
brackets,
cond.semis.map(|_| semis),
);
if cond == current { if cond == current {
return Some(()); return Some(());
} }
@ -377,13 +408,16 @@ impl<'a> TokenIterator<'a> {
.next() .next()
.map(|i| i.source_location()) .map(|i| i.source_location())
.unwrap_or_else(|| { .unwrap_or_else(|| {
self.tokenizer self.tokenizer.source.offset_to_source_location(
.source self.tokenizer.source.num_bytes() as u32,
.offset_to_source_location(self.tokenizer.source.num_bytes() as u32) )
}) })
} }
pub fn expect_token(&mut self, token: Token) -> crate::parser::Result<TokenItem<'a>> { pub fn expect_token(
&mut self,
token: Token,
) -> crate::parser::Result<TokenItem<'a>> {
self.next_if(|item| item.token() == token) self.next_if(|item| item.token() == token)
.ok_or(crate::parser::Error::ExpectedTokenNotFound(token)) .ok_or(crate::parser::Error::ExpectedTokenNotFound(token))
} }
@ -395,13 +429,18 @@ impl<'a> TokenIterator<'a> {
pub fn peek_token(&mut self) -> Option<TokenItem<'a>> { pub fn peek_token(&mut self) -> Option<TokenItem<'a>> {
self.clone().next() self.clone().next()
} }
pub fn peek_token_or_err(&mut self) -> crate::parser::Result<TokenItem<'a>> { pub fn peek_token_or_err(
&mut self,
) -> crate::parser::Result<TokenItem<'a>> {
self.clone() self.clone()
.next() .next()
.ok_or(crate::parser::Error::UnexpectedEndOfTokens) .ok_or(crate::parser::Error::UnexpectedEndOfTokens)
} }
pub fn peek_expect_token(&mut self, token: Token) -> crate::parser::Result<TokenItem<'a>> { pub fn peek_expect_token(
&mut self,
token: Token,
) -> crate::parser::Result<TokenItem<'a>> {
self.clone() self.clone()
.next() .next()
.ok_or(crate::parser::Error::ExpectedTokenNotFound(token)) .ok_or(crate::parser::Error::ExpectedTokenNotFound(token))
@ -644,9 +683,16 @@ impl<'a> Tokenizer<'a> {
// .unwrap_or(false); // .unwrap_or(false);
let end = this.source.position(); let end = this.source.position();
if this.source.peek().map(|c| crate::common::is_whitespace(c)) != Some(true) { if this
.source
.peek()
.map(|c| crate::common::is_whitespace(c))
!= Some(true)
{
this.source this.source
.take_while_ref(|&c| !crate::common::is_whitespace(c)) .take_while_ref(|&c| {
!crate::common::is_whitespace(c)
})
.count(); .count();
} }
@ -713,7 +759,10 @@ impl<'a> Tokenizer<'a> {
let mut peeking = self.source.clone(); let mut peeking = self.source.clone();
match peeking.next() { match peeking.next() {
Some('0'..='9') => Some(parse_constant(&mut self.source)?), Some('0'..='9') => Some(parse_constant(&mut self.source)?),
Some('.') if peeking.next().map(|c| crate::common::is_digit(c)) == Some(true) => { Some('.')
if peeking.next().map(|c| crate::common::is_digit(c))
== Some(true) =>
{
Some(parse_constant(&mut self.source)?) Some(parse_constant(&mut self.source)?)
} }
_ => None, _ => None,
@ -796,7 +845,11 @@ impl<'a> Tokenizer<'a> {
.count() .count()
.gt(&0) .gt(&0)
{ {
return self.push_token(Token::Ident, start, self.source.position()); return self.push_token(
Token::Ident,
start,
self.source.position(),
);
} }
} }
@ -1046,7 +1099,9 @@ fn parse_constant_inner(source: &mut Chars) -> Result<Token> {
Err(e) => Err(e), Err(e) => Err(e),
}?; }?;
if let Some(_) = source.try_parse_result(|source| try_parse_integral_type(source))? { if let Some(_) =
source.try_parse_result(|source| try_parse_integral_type(source))?
{
return Ok(Token::IntegerConstant); return Ok(Token::IntegerConstant);
} }

View file

@ -9,7 +9,8 @@
iter_array_chunks, iter_array_chunks,
int_roundings, int_roundings,
if_let_guard, if_let_guard,
debug_closure_helpers debug_closure_helpers,
macro_metavar_expr
)] )]
#![allow(unused_macros)] #![allow(unused_macros)]
@ -30,6 +31,45 @@ pub mod triples;
pub fn tokenize<'a>( pub fn tokenize<'a>(
bytes: &'a [u8], 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) lexer::Tokenizer::new_with_errors(bytes)
} }
trait BitSize {
fn bits(&self) -> u32;
}
macro_rules! impl_bitsize_int {
($($ty:ty)*) => {
$(
impl BitSize for $ty {
fn bits(&self) -> u32 {
Self::BITS as u32 - self.trailing_zeros() as u32
}
})*
};
}
impl_bitsize_int!(u8 u16 u32 u64 u128);
impl BitSize for &[u8] {
fn bits(&self) -> u32 {
let bytes = self.as_ref();
let mut bits = bytes.len() * u8::BITS as usize;
for &d in bytes.iter().rev() {
if d == 0 {
bits -= u8::BITS as usize;
} else {
bits -= d.leading_zeros() as usize;
break;
}
}
bits as u32
}
}

1218
src/mir.rs

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -55,7 +55,10 @@ impl StringTable {
ImmOrIndex::Index(idx) => { ImmOrIndex::Index(idx) => {
let bytes = self.get_bytes(idx); let bytes = self.get_bytes(idx);
let ints = unsafe { let ints = unsafe {
core::slice::from_raw_parts(bytes.as_ptr().cast::<u32>(), bytes.len() / 4) core::slice::from_raw_parts(
bytes.as_ptr().cast::<u32>(),
bytes.len() / 4,
)
}; };
bigint::count_bits(ints) as u32 bigint::count_bits(ints) as u32
} }
@ -117,7 +120,10 @@ mod display {
str: Option<&'a str>, str: Option<&'a str>,
} }
impl<'a> Debug for Test<'a> { impl<'a> Debug for Test<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
write!(f, "{{ bytes: {:x?}", self.bytes)?; write!(f, "{{ bytes: {:x?}", self.bytes)?;
if let Some(str) = self.str { if let Some(str) = self.str {
write!(f, ", str: {}", str)?; write!(f, ", str: {}", str)?;

View file

@ -35,13 +35,25 @@ impl SymbolPath {
for node in self.0.iter().skip(1).rev() { for node in self.0.iter().skip(1).rev() {
match tree.nodes.get_node(node.unwrap()) { match tree.nodes.get_node(node.unwrap()) {
Tag::VarDecl { name, .. } => { Tag::VarDecl { name, .. } => {
_ = write!(&mut buf, "V{}::", tree.get_ident_str(*name).unwrap()); _ = write!(
&mut buf,
"V{}::",
tree.get_ident_str(*name).unwrap()
);
} }
Tag::GlobalDecl { name, .. } => { Tag::GlobalDecl { name, .. } => {
_ = write!(&mut buf, "G{}::", tree.get_ident_str(*name).unwrap()); _ = write!(
&mut buf,
"G{}::",
tree.get_ident_str(*name).unwrap()
);
} }
Tag::FunctionProto { name, .. } => { Tag::FunctionProto { name, .. } => {
_ = write!(&mut buf, "F{}::", tree.get_ident_str(*name).unwrap()); _ = write!(
&mut buf,
"F{}::",
tree.get_ident_str(*name).unwrap()
);
} }
_ => {} _ => {}
} }
@ -130,7 +142,12 @@ impl Drop for InnerSymbolTable {
} }
impl InnerSymbolTable { impl InnerSymbolTable {
fn insert_symbol(&mut self, name: &str, node: AstNode, kind: SymbolKind) -> &SymbolRecord { fn insert_symbol(
&mut self,
name: &str,
node: AstNode,
kind: SymbolKind,
) -> &SymbolRecord {
match kind { match kind {
SymbolKind::Var => { SymbolKind::Var => {
self.ordered_identifiers.push(SymbolRecord { self.ordered_identifiers.push(SymbolRecord {
@ -143,7 +160,11 @@ impl InnerSymbolTable {
} }
} }
fn insert_orderless_symbol(&mut self, name: &str, node: AstNode) -> &SymbolRecord { fn insert_orderless_symbol(
&mut self,
name: &str,
node: AstNode,
) -> &SymbolRecord {
self.orderless_identifiers.insert( self.orderless_identifiers.insert(
name.to_owned(), name.to_owned(),
SymbolRecord { SymbolRecord {
@ -154,7 +175,11 @@ impl InnerSymbolTable {
self.orderless_identifiers.get(name).unwrap() self.orderless_identifiers.get(name).unwrap()
} }
fn find_symbol_or_insert_with<'a, F>(&'a mut self, name: &str, cb: F) -> &'a SymbolRecord fn find_symbol_or_insert_with<'a, F>(
&'a mut self,
name: &str,
cb: F,
) -> &'a SymbolRecord
where where
F: FnOnce() -> (AstNode, SymbolKind), F: FnOnce() -> (AstNode, SymbolKind),
{ {
@ -177,7 +202,9 @@ impl InnerSymbolTable {
.find(|(_, v)| v.decl == decl) .find(|(_, v)| v.decl == decl)
.map(|(_, v)| v) .map(|(_, v)| v)
}) })
.or_else(|| self.parent_ref().and_then(|p| p.find_symbol_by_decl(decl))) .or_else(|| {
self.parent_ref().and_then(|p| p.find_symbol_by_decl(decl))
})
} }
fn find_any_symbol(&self, name: &str) -> Option<&SymbolRecord> { fn find_any_symbol(&self, name: &str) -> Option<&SymbolRecord> {
@ -192,7 +219,9 @@ impl InnerSymbolTable {
self.ordered_identifiers self.ordered_identifiers
.iter() .iter()
.find(|r| r.name.as_str() == name) .find(|r| r.name.as_str() == name)
.or_else(|| self.parent_ref().and_then(|p| p.find_ordered_symbol(name))) .or_else(|| {
self.parent_ref().and_then(|p| p.find_ordered_symbol(name))
})
} }
fn find_orderless_symbol(&self, name: &str) -> Option<&SymbolRecord> { fn find_orderless_symbol(&self, name: &str) -> Option<&SymbolRecord> {
@ -286,7 +315,12 @@ impl SymbolTableWrapper {
} }
impl SymbolTableWrapper { impl SymbolTableWrapper {
pub fn insert_symbol(&mut self, name: &str, node: AstNode, kind: SymbolKind) -> &SymbolRecord { pub fn insert_symbol(
&mut self,
name: &str,
node: AstNode,
kind: SymbolKind,
) -> &SymbolRecord {
self.current_mut().insert_symbol(name, node, kind) self.current_mut().insert_symbol(name, node, kind)
} }
@ -294,15 +328,27 @@ impl SymbolTableWrapper {
self.root_mut().find_orderless_symbol(name) self.root_mut().find_orderless_symbol(name)
} }
pub fn insert_root_symbol(&mut self, name: &str, node: AstNode) -> &SymbolRecord { pub fn insert_root_symbol(
&mut self,
name: &str,
node: AstNode,
) -> &SymbolRecord {
self.root_mut().insert_orderless_symbol(name, node) self.root_mut().insert_orderless_symbol(name, node)
} }
pub fn insert_orderless_symbol(&mut self, name: &str, node: AstNode) -> &SymbolRecord { pub fn insert_orderless_symbol(
&mut self,
name: &str,
node: AstNode,
) -> &SymbolRecord {
self.current_mut().insert_orderless_symbol(name, node) self.current_mut().insert_orderless_symbol(name, node)
} }
pub fn find_symbol_or_insert_with<'a, F>(&'a mut self, name: &str, cb: F) -> &'a SymbolRecord pub fn find_symbol_or_insert_with<'a, F>(
&'a mut self,
name: &str,
cb: F,
) -> &'a SymbolRecord
where where
F: FnOnce() -> (AstNode, SymbolKind), F: FnOnce() -> (AstNode, SymbolKind),
{ {
@ -480,7 +526,9 @@ pub mod syms2 {
} }
let entries = self.inner.iter().map(|(key, val)| { let entries = self.inner.iter().map(|(key, val)| {
let payload = match key { let payload = match key {
Key::ScopeByIndex { .. } => ExpandedPayload::Intern(val.as_intern()), Key::ScopeByIndex { .. } => {
ExpandedPayload::Intern(val.as_intern())
}
_ => ExpandedPayload::Ast(val.as_ast()), _ => ExpandedPayload::Ast(val.as_ast()),
}; };
@ -589,8 +637,10 @@ pub mod syms2 {
kind: SymbolKind, kind: SymbolKind,
ast: AstIndex, ast: AstIndex,
) { ) {
self.inner self.inner.insert(
.insert(Key::Symbol { scope, name, kind }, Payload::new_ast(ast)); Key::Symbol { scope, name, kind },
Payload::new_ast(ast),
);
} }
} }
} }

View file

@ -172,7 +172,11 @@ impl Token {
} }
pub fn is_unary_op(self) -> bool { pub fn is_unary_op(self) -> bool {
match self { match self {
Token::Plus | Token::Minus | Token::Star | Token::Ampersand | Token::Bang => true, Token::Plus
| Token::Minus
| Token::Star
| Token::Ampersand
| Token::Bang => true,
_ => false, _ => false,
} }
} }
@ -264,15 +268,16 @@ impl LexemeParser {
// them is represented by a single byte and we know they must be // them is represented by a single byte and we know they must be
// utf8/ascii. // utf8/ascii.
unsafe { unsafe {
char::from_u32_unchecked(tok.lexeme().unwrap().as_bytes()[self.len - 1] as u32) char::from_u32_unchecked(
== ch tok.lexeme().unwrap().as_bytes()[self.len - 1] as u32,
) == ch
} }
}); });
// A token has been successfully matched completely if it has not yet // A token has been successfully matched completely if it has not yet
// been removed from the lexeme list but the length of it's lexeme is no // been removed from the lexeme list but the length of it's lexeme is no
// greater than the number of chars we've received. // greater than the number of chars we've received.
self.candidates.extend(self.lexemes.extract_if(|tok| { self.candidates.extend(self.lexemes.extract_if(.., |tok| {
// SAFETY: as above, all of the tokens in self.lexemes are // SAFETY: as above, all of the tokens in self.lexemes are
// lexical and are all single byte characters. // lexical and are all single byte characters.
tok.lexeme().unwrap().as_bytes().len() <= self.len tok.lexeme().unwrap().as_bytes().len() <= self.len

File diff suppressed because it is too large Load diff

4
test.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
cargo run --bin main -- -i "$1" asm > asm.S
clang asm.S -c && clang asm.o -o asm && ./asm; echo $?

View file

@ -2,4 +2,4 @@ fn main() -> i32 {
return RANDOM; return RANDOM;
} }
const RANDOM: i32 = 4 + (1 << 3); const RANDOM: i32 = 4i32 + (1i32 << 3i32);