Compare commits
No commits in common. "d743292710bf0aaea0ca94776b0be70dfadfdf96" and "006e982cde51080b2513cb81170fb3bcd92b8527" have entirely different histories.
d743292710
...
006e982cde
|
@ -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
|
ah | bh | ch | dh | al | bl | cl | dl | sil | dil | spl | bpl | r8b | r9b | r10b
|
||||||
| r8b | r9b | r10b | r11b | r12b | r13b | r14b | r15b => 8,
|
| r11b | r12b | r13b | r14b | r15b => 8,
|
||||||
|
|
||||||
ax | bx | cx | dx | si | di | sp | bp | ip | r8w | r9w | r10w
|
ax | bx | cx | dx | si | di | sp | bp | ip | r8w | r9w | r10w | r11w | r12w | r13w
|
||||||
| r11w | r12w | r13w | r14w | r15w => 16,
|
| r14w | r15w => 16,
|
||||||
|
|
||||||
eax | ebx | ecx | edx | esi | edi | esp | ebp | eip | r8d | r9d
|
eax | ebx | ecx | edx | esi | edi | esp | ebp | eip | r8d | r9d | r10d | r11d
|
||||||
| r10d | r11d | r12d | r13d | r14d | r15d => 32,
|
| r12d | r13d | r14d | r15d => 32,
|
||||||
|
|
||||||
rax | rbx | rcx | rdx | rsi | rdi | rsp | rbp | rip | r8 | r9
|
rax | rbx | rcx | rdx | rsi | rdi | rsp | rbp | rip | r8 | r9 | r10 | r11 | r12
|
||||||
| r10 | r11 | r12 | r13 | r14 | r15 => 64,
|
| 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
|
xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 | xmm8 | xmm9 | xmm10 | xmm11
|
||||||
| xmm9 | xmm10 | xmm11 | xmm12 | xmm13 | xmm14 | xmm15 => 128,
|
| xmm12 | xmm13 | xmm14 | xmm15 => 128,
|
||||||
|
|
||||||
ymm0 | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 | ymm7 | ymm8
|
ymm0 | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 | ymm7 | ymm8 | ymm9 | ymm10 | ymm11
|
||||||
| ymm9 | ymm10 | ymm11 | ymm12 | ymm13 | ymm14 | ymm15 => 256,
|
| ymm12 | ymm13 | ymm14 | ymm15 => 256,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,30 +338,28 @@ 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,
|
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13,
|
||||||
xmm11, xmm12, xmm13, xmm14, xmm15,
|
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
|
rax | eax | ax | ah | al | rbx | ebx | bx | bh | bl | rcx | ecx | cx | ch | cl
|
||||||
| cx | ch | cl | rdx | edx | dx | dh | dl | rsi | esi | si
|
| rdx | edx | dx | dh | dl | rsi | esi | si | sil | rdi | edi | di | dil | r8 | r8d
|
||||||
| sil | rdi | edi | di | dil | r8 | r8d | r8w | r8b | r9 | r9d
|
| r8w | r8b | r9 | r9d | r9w | r9b | r10 | r10d | r10w | r10b | r11 | r11d | r11w
|
||||||
| r9w | r9b | r10 | r10d | r10w | r10b | r11 | r11d | r11w
|
| r11b | r12 | r12d | r12w | r12b | r13 | r13d | r13w | r13b | r14 | r14d | r14w
|
||||||
| r11b | r12 | r12d | r12w | r12b | r13 | r13d | r13w | r13b
|
| r14b | r15 | r15d | r15w | r15b => true,
|
||||||
| 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
|
xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 | xmm8 | xmm9 | xmm10 | xmm11
|
||||||
| xmm9 | xmm10 | xmm11 | xmm12 | xmm13 | xmm14 | xmm15 | ymm0
|
| xmm12 | xmm13 | xmm14 | xmm15 | ymm0 | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6
|
||||||
| ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 | ymm7 | ymm8 | ymm9
|
| ymm7 | ymm8 | ymm9 | ymm10 | ymm11 | ymm12 | ymm13 | ymm14 | ymm15 => true,
|
||||||
| ymm10 | ymm11 | ymm12 | ymm13 | ymm14 | ymm15 => true,
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
60
src/ast.rs
60
src/ast.rs
|
@ -1,9 +1,6 @@
|
||||||
use std::num::NonZero;
|
use std::num::NonZero;
|
||||||
|
|
||||||
use crate::{
|
use crate::string_table::{self, ImmOrIndex};
|
||||||
ast2::intern,
|
|
||||||
string_table::{self, ImmOrIndex},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub type Node = NonZero<u32>;
|
pub type Node = NonZero<u32>;
|
||||||
|
|
||||||
|
@ -36,8 +33,8 @@ pub enum Tag {
|
||||||
PointerQualifier {
|
PointerQualifier {
|
||||||
constness: bool,
|
constness: bool,
|
||||||
},
|
},
|
||||||
IntegralType(intern::Index),
|
IntegralType(IntegralType),
|
||||||
PrimitiveType(intern::Index),
|
PrimitiveType(PrimitiveType),
|
||||||
FunctionDecl {
|
FunctionDecl {
|
||||||
/// FunctionProto
|
/// FunctionProto
|
||||||
proto: Node,
|
proto: Node,
|
||||||
|
@ -45,11 +42,10 @@ pub enum Tag {
|
||||||
body: Node,
|
body: Node,
|
||||||
},
|
},
|
||||||
Ident {
|
Ident {
|
||||||
name: intern::Index,
|
name: string_table::Index,
|
||||||
},
|
},
|
||||||
/// bytes might be an integer, float, double, or Bytes
|
|
||||||
Constant {
|
Constant {
|
||||||
bytes: intern::Index,
|
bytes: ImmOrIndex,
|
||||||
ty: Type,
|
ty: Type,
|
||||||
},
|
},
|
||||||
Block {
|
Block {
|
||||||
|
@ -298,21 +294,14 @@ impl core::fmt::Display for Type {
|
||||||
Type::Integer(t) => t.fmt(f),
|
Type::Integer(t) => t.fmt(f),
|
||||||
Type::Floating(t) => t.fmt(f),
|
Type::Floating(t) => t.fmt(f),
|
||||||
Type::Pointer { constness, pointee } => {
|
Type::Pointer { constness, pointee } => {
|
||||||
write!(
|
write!(f, "*{}{}", if *constness { "const " } else { "" }, pointee)
|
||||||
f,
|
|
||||||
"*{}{}",
|
|
||||||
if *constness { "const " } else { "" },
|
|
||||||
pointee
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Type::Fn {
|
Type::Fn {
|
||||||
parameter_types,
|
parameter_types,
|
||||||
return_type,
|
return_type,
|
||||||
} => {
|
} => {
|
||||||
write!(f, "fn (")?;
|
write!(f, "fn (")?;
|
||||||
for param in
|
for param in parameter_types.iter().map(|p| Some(p)).intersperse(None) {
|
||||||
parameter_types.iter().map(|p| Some(p)).intersperse(None)
|
|
||||||
{
|
|
||||||
match param {
|
match param {
|
||||||
Some(param) => param.fmt(f)?,
|
Some(param) => param.fmt(f)?,
|
||||||
None => write!(f, ", ")?,
|
None => write!(f, ", ")?,
|
||||||
|
@ -351,13 +340,8 @@ impl Type {
|
||||||
parameter_types: r_parameter_types,
|
parameter_types: r_parameter_types,
|
||||||
return_type: r_return_type,
|
return_type: r_return_type,
|
||||||
},
|
},
|
||||||
) => {
|
) => l_parameter_types == r_parameter_types && l_return_type == r_return_type,
|
||||||
l_parameter_types == r_parameter_types
|
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
|
||||||
&& l_return_type == r_return_type
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
core::mem::discriminant(self) == core::mem::discriminant(other)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn as_primitive_type(&self) -> Option<PrimitiveType> {
|
pub fn as_primitive_type(&self) -> Option<PrimitiveType> {
|
||||||
|
@ -476,10 +460,9 @@ impl Type {
|
||||||
|
|
||||||
pub fn can_add_sub(&self) -> bool {
|
pub fn can_add_sub(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Type::ComptimeNumber
|
Type::ComptimeNumber | Type::Pointer { .. } | Type::Floating(_) | Type::Integer(_) => {
|
||||||
| Type::Pointer { .. }
|
true
|
||||||
| Type::Floating(_)
|
}
|
||||||
| Type::Integer(_) => true,
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -501,10 +484,9 @@ impl Type {
|
||||||
}
|
}
|
||||||
pub fn can_cmp(&self) -> bool {
|
pub fn can_cmp(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Type::ComptimeNumber
|
Type::ComptimeNumber | Type::Pointer { .. } | Type::Floating(_) | Type::Integer(_) => {
|
||||||
| Type::Pointer { .. }
|
true
|
||||||
| Type::Floating(_)
|
}
|
||||||
| Type::Integer(_) => true,
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -613,12 +595,7 @@ pub mod tree_visitor {
|
||||||
pub fn new_range(start: Node, end: Node, pre: F1, post: F2) -> Self {
|
pub fn new_range(start: Node, end: Node, pre: F1, post: F2) -> Self {
|
||||||
Self::new_inner(start, End::Exclusive(end), pre, post)
|
Self::new_inner(start, End::Exclusive(end), pre, post)
|
||||||
}
|
}
|
||||||
pub fn new_range_inclusive(
|
pub fn new_range_inclusive(start: Node, end: Node, pre: F1, post: F2) -> Self {
|
||||||
start: Node,
|
|
||||||
end: Node,
|
|
||||||
pre: F1,
|
|
||||||
post: F2,
|
|
||||||
) -> Self {
|
|
||||||
Self::new_inner(start, End::Inclusive(end), pre, post)
|
Self::new_inner(start, End::Inclusive(end), pre, post)
|
||||||
}
|
}
|
||||||
pub fn new_seek(tree: &Tree, start: Node, pre: F1, post: F2) -> Self {
|
pub fn new_seek(tree: &Tree, start: Node, pre: F1, post: F2) -> Self {
|
||||||
|
@ -717,10 +694,7 @@ pub mod tree_visitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// short-circuits on the first E
|
/// short-circuits on the first E
|
||||||
pub fn visit_ok<T, E>(
|
pub fn visit_ok<T, E>(mut self, tree: &Tree) -> core::result::Result<T, E>
|
||||||
mut self,
|
|
||||||
tree: &Tree,
|
|
||||||
) -> core::result::Result<T, E>
|
|
||||||
where
|
where
|
||||||
F1: FnMut(&Tree, Node) -> core::result::Result<T, E>,
|
F1: FnMut(&Tree, Node) -> core::result::Result<T, E>,
|
||||||
F2: FnMut(&Tree, Node) -> core::result::Result<T, E>,
|
F2: FnMut(&Tree, Node) -> core::result::Result<T, E>,
|
||||||
|
|
1541
src/ast2/intern.rs
1541
src/ast2/intern.rs
File diff suppressed because it is too large
Load diff
2209
src/ast2/mod.rs
2209
src/ast2/mod.rs
File diff suppressed because it is too large
Load diff
|
@ -1,8 +1,7 @@
|
||||||
use std::{io::Read, path::PathBuf, sync::Arc};
|
use std::{io::Read, path::PathBuf};
|
||||||
|
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
use compiler::{
|
use compiler::{
|
||||||
ast2::intern::InternPool,
|
|
||||||
lexer::Tokenizer,
|
lexer::Tokenizer,
|
||||||
parser::Tree,
|
parser::Tree,
|
||||||
triples::{MirBuilder, IR},
|
triples::{MirBuilder, IR},
|
||||||
|
@ -12,7 +11,6 @@ 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
|
||||||
}
|
}
|
||||||
|
@ -29,8 +27,7 @@ fn main() {
|
||||||
.subcommands([
|
.subcommands([
|
||||||
Command::new("ast").about("output AST."),
|
Command::new("ast").about("output AST."),
|
||||||
Command::new("ast2").about("output AST."),
|
Command::new("ast2").about("output AST."),
|
||||||
Command::new("mir")
|
Command::new("mir").about("output machine-level intermediate representation."),
|
||||||
.about("output machine-level intermediate representation."),
|
|
||||||
Command::new("ir").about("output intermediate representation."),
|
Command::new("ir").about("output intermediate representation."),
|
||||||
Command::new("asm").about("output x86-64 assembly (intel syntax)."),
|
Command::new("asm").about("output x86-64 assembly (intel syntax)."),
|
||||||
]);
|
]);
|
||||||
|
@ -75,34 +72,28 @@ 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.intern_pool);
|
let mut mir = MirBuilder::new(&ir, tree.strings);
|
||||||
mir.build();
|
mir.build();
|
||||||
|
|
||||||
let MirBuilder {
|
let MirBuilder {
|
||||||
intern_pool: strings,
|
strings, functions, ..
|
||||||
functions,
|
|
||||||
..
|
|
||||||
} = mir;
|
} = mir;
|
||||||
|
|
||||||
for (name, mir) in functions {
|
for (name, mir) in functions {
|
||||||
println!(
|
println!("{}:\n{}", strings.get_str(name), mir.display(&strings));
|
||||||
"{}:\n{}",
|
|
||||||
strings.get_str(name),
|
|
||||||
mir.display(&strings)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"asm" => {
|
"asm" => {
|
||||||
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.intern_pool);
|
let mut mir = MirBuilder::new(&ir, tree.strings);
|
||||||
mir.build();
|
mir.build();
|
||||||
|
|
||||||
let MirBuilder {
|
let MirBuilder {
|
||||||
globals,
|
globals,
|
||||||
intern_pool: strings,
|
strings,
|
||||||
functions,
|
functions,
|
||||||
..
|
..
|
||||||
} = mir;
|
} = mir;
|
||||||
|
|
|
@ -41,8 +41,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
eprintln!(":");
|
eprintln!(":");
|
||||||
for error in &errors {
|
for error in &errors {
|
||||||
let lines =
|
let lines = tokens.src().get_lines(error.range.start, error.range.end);
|
||||||
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);
|
||||||
|
|
|
@ -72,9 +72,7 @@ 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)
|
('0'..='9').contains(&ch) || ('a'..='f').contains(&ch) || ('A'..='F').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
|
||||||
|
|
402
src/comptime.rs
402
src/comptime.rs
|
@ -12,10 +12,7 @@ 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>>(
|
pub fn parse_digits<C: IntoIterator<Item = char>>(text: C, radix: Radix) -> BigInt {
|
||||||
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 {
|
||||||
|
@ -240,13 +237,9 @@ 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!(
|
println!("extending self by {} zeroes", rhs.0.len() - self.0.len());
|
||||||
"extending self by {} zeroes",
|
self.0
|
||||||
rhs.0.len() - self.0.len()
|
.extend(core::iter::repeat(0).take(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);
|
||||||
|
@ -504,10 +497,7 @@ pub mod bigint {
|
||||||
_ => {
|
_ => {
|
||||||
if scalar.is_power_of_two() {
|
if scalar.is_power_of_two() {
|
||||||
lhs.push(0);
|
lhs.push(0);
|
||||||
shl_bitint(
|
shl_bitint(lhs.as_mut_slice(), scalar.trailing_zeros() as usize);
|
||||||
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() {
|
||||||
|
@ -593,10 +583,7 @@ 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(
|
pub fn div_rem_bigint_ref(divident: &BigInt, divisor: &BigInt) -> (BigInt, BigInt) {
|
||||||
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!");
|
||||||
}
|
}
|
||||||
|
@ -614,8 +601,7 @@ 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) =
|
let (div, rem) = divident.0.split_at(exp.div_floor(u32::BITS as usize));
|
||||||
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);
|
||||||
|
@ -641,10 +627,7 @@ 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(
|
let (q, r) = div_rem_core(divident.clone() << shift, &(divisor.clone() << shift).0);
|
||||||
divident.clone() << shift,
|
|
||||||
&(divisor.clone() << shift).0,
|
|
||||||
);
|
|
||||||
|
|
||||||
(q, r >> shift)
|
(q, r >> shift)
|
||||||
}
|
}
|
||||||
|
@ -653,10 +636,7 @@ 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(
|
pub fn div_rem_bigint(divident: BigInt, divisor: BigInt) -> (BigInt, 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();
|
||||||
|
|
||||||
|
@ -677,8 +657,7 @@ 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) =
|
let (div, rem) = divident.0.split_at(exp.div_floor(u32::BITS as usize));
|
||||||
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);
|
||||||
|
@ -810,9 +789,7 @@ 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
|
while r <= u32::MAX as u64 && from_lo_hi_dwords(r as u32, a2) < q0 as u64 * b1 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;
|
||||||
}
|
}
|
||||||
|
@ -1041,10 +1018,7 @@ pub mod bigint {
|
||||||
carry
|
carry
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_bigint(
|
pub fn parse_bigint(text: impl Iterator<Item = char>, radix: Radix) -> Vec<u32> {
|
||||||
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,
|
||||||
|
@ -1112,20 +1086,14 @@ pub mod bigint {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse() {
|
fn parse() {
|
||||||
let bigint = BigInt::parse_digits(
|
let bigint = BigInt::parse_digits("2_cafe_babe_dead_beef".chars(), Radix::Hex);
|
||||||
"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(
|
let a = BigInt::parse_digits("2_0000_0000_0000_0000".chars(), Radix::Hex);
|
||||||
"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);
|
||||||
|
@ -1143,10 +1111,7 @@ pub mod bigint {
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn overflowing_sub() {
|
fn overflowing_sub() {
|
||||||
let a = BigInt::parse_digits(
|
let a = BigInt::parse_digits("2_0000_0000_0000_0000".chars(), Radix::Hex);
|
||||||
"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);
|
||||||
|
@ -1155,8 +1120,7 @@ pub mod bigint {
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn shr() {
|
fn shr() {
|
||||||
let mut a =
|
let mut a = BigInt::parse_digits("cafe_babe_0000".chars(), Radix::Hex);
|
||||||
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);
|
||||||
|
@ -1188,9 +1152,7 @@ pub mod bigint {
|
||||||
pub mod bigsint {
|
pub mod bigsint {
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
ops::{
|
ops::{Add, AddAssign, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub, SubAssign},
|
||||||
Add, AddAssign, Div, Mul, Neg, Not, Rem, Shl, Shr, Sub, SubAssign,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::bigint::{self, *};
|
use super::bigint::{self, *};
|
||||||
|
@ -1333,13 +1295,11 @@ 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::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => Self {
|
||||||
| (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::Positive, Sign::Negative) | (Sign::Negative, Sign::Positive) => {
|
||||||
| (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,
|
||||||
|
@ -1361,13 +1321,11 @@ 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 => {
|
Sign::Negative => match self.bigint.partial_cmp(&rhs).unwrap() {
|
||||||
match self.bigint.partial_cmp(&rhs).unwrap() {
|
|
||||||
Ordering::Less => Self::positive(rhs - self.bigint),
|
Ordering::Less => Self::positive(rhs - self.bigint),
|
||||||
Ordering::Equal => Self::zero(),
|
Ordering::Equal => Self::zero(),
|
||||||
Ordering::Greater => -Self::positive(self.bigint - rhs),
|
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),
|
||||||
}
|
}
|
||||||
|
@ -1379,13 +1337,11 @@ 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 => {
|
Sign::Negative => match self.bigint.partial_cmp(&rhs).unwrap() {
|
||||||
match self.bigint.partial_cmp(&rhs).unwrap() {
|
|
||||||
Ordering::Less => Self::positive(rhs - self.bigint),
|
Ordering::Less => Self::positive(rhs - self.bigint),
|
||||||
Ordering::Equal => Self::zero(),
|
Ordering::Equal => Self::zero(),
|
||||||
Ordering::Greater => -Self::positive(self.bigint - rhs),
|
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),
|
||||||
}
|
}
|
||||||
|
@ -1406,13 +1362,11 @@ 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::Positive, Sign::Negative) | (Sign::Negative, Sign::Positive) => Self {
|
||||||
| (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::Positive, Sign::Positive) | (Sign::Negative, Sign::Negative) => {
|
||||||
| (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,
|
||||||
|
@ -1585,20 +1539,14 @@ 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 {
|
||||||
|
@ -1607,9 +1555,7 @@ impl ComptimeInt {
|
||||||
Ok(Self::BigInt { bits, ty })
|
Ok(Self::BigInt { bits, ty })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => {
|
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a + b)),
|
||||||
Ok(Self::Comptime(a + b))
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1619,20 +1565,14 @@ 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 {
|
||||||
|
@ -1641,9 +1581,7 @@ impl ComptimeInt {
|
||||||
Ok(Self::BigInt { bits, ty })
|
Ok(Self::BigInt { bits, ty })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => {
|
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a - b)),
|
||||||
Ok(Self::Comptime(a - b))
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1653,20 +1591,14 @@ 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 {
|
||||||
|
@ -1675,9 +1607,7 @@ impl ComptimeInt {
|
||||||
Ok(Self::BigInt { bits, ty })
|
Ok(Self::BigInt { bits, ty })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => {
|
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a * b)),
|
||||||
Ok(Self::Comptime(a * b))
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1687,20 +1617,14 @@ 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 {
|
||||||
|
@ -1709,9 +1633,7 @@ impl ComptimeInt {
|
||||||
Ok(Self::BigInt { bits, ty })
|
Ok(Self::BigInt { bits, ty })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => {
|
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a / b)),
|
||||||
Ok(Self::Comptime(a / b))
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1721,20 +1643,14 @@ 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 {
|
||||||
|
@ -1743,9 +1659,7 @@ impl ComptimeInt {
|
||||||
Ok(Self::BigInt { bits, ty })
|
Ok(Self::BigInt { bits, ty })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => {
|
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a % b)),
|
||||||
Ok(Self::Comptime(a % b))
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1755,23 +1669,15 @@ 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)) => {
|
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a & b)),
|
||||||
Ok(Self::Comptime(a & b))
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1781,23 +1687,15 @@ 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)) => {
|
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a | b)),
|
||||||
Ok(Self::Comptime(a | b))
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1807,23 +1705,15 @@ 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)) => {
|
(ComptimeInt::Comptime(a), ComptimeInt::Comptime(b)) => Ok(Self::Comptime(a ^ b)),
|
||||||
Ok(Self::Comptime(a ^ b))
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1832,14 +1722,8 @@ 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::Native { bits: a, .. },
|
(ComptimeInt::BigInt { bits: a, .. }, ComptimeInt::BigInt { bits: b, .. }) => a.cmp(&b),
|
||||||
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!()
|
||||||
|
@ -1857,13 +1741,11 @@ 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)?
|
.ok_or(Error::IntegerOverflow)? as u128
|
||||||
as u128
|
|
||||||
} else {
|
} else {
|
||||||
(bits as u128)
|
(bits as u128)
|
||||||
.checked_shl(shift)
|
.checked_shl(shift)
|
||||||
.ok_or(Error::IntegerOverflow)?
|
.ok_or(Error::IntegerOverflow)? as u128
|
||||||
as u128
|
|
||||||
} & ty.u128_bitmask();
|
} & ty.u128_bitmask();
|
||||||
|
|
||||||
Ok(Self::Native { bits, ty })
|
Ok(Self::Native { bits, ty })
|
||||||
|
@ -1888,13 +1770,11 @@ 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)?
|
.ok_or(Error::IntegerOverflow)? as u128
|
||||||
as u128
|
|
||||||
} else {
|
} else {
|
||||||
(bits as u128)
|
(bits as u128)
|
||||||
.checked_shr(shift)
|
.checked_shr(shift)
|
||||||
.ok_or(Error::IntegerOverflow)?
|
.ok_or(Error::IntegerOverflow)? as u128
|
||||||
as u128
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Self::Native { bits, ty })
|
Ok(Self::Native { bits, ty })
|
||||||
|
@ -1913,9 +1793,7 @@ impl ComptimeInt {
|
||||||
if ty.signed {
|
if ty.signed {
|
||||||
return Err(Error::UnsignedNegation);
|
return Err(Error::UnsignedNegation);
|
||||||
}
|
}
|
||||||
let bits =
|
let bits = (a as i128).checked_neg().ok_or(Error::IntegerOverflow)? as u128;
|
||||||
(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);
|
||||||
|
@ -1933,9 +1811,7 @@ impl ComptimeInt {
|
||||||
bits: !bits | ty.u128_bitmask(),
|
bits: !bits | ty.u128_bitmask(),
|
||||||
ty,
|
ty,
|
||||||
}),
|
}),
|
||||||
ComptimeInt::BigInt { bits, ty } => {
|
ComptimeInt::BigInt { bits, ty } => Ok(Self::BigInt { bits: !bits, ty }),
|
||||||
Ok(Self::BigInt { bits: !bits, ty })
|
|
||||||
}
|
|
||||||
ComptimeInt::Comptime(bigint) => Ok(Self::Comptime(!bigint)),
|
ComptimeInt::Comptime(bigint) => Ok(Self::Comptime(!bigint)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1951,14 +1827,8 @@ 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, .. },
|
| (lhs @ ComptimeInt::Native { ty: a_ty, .. }, ComptimeInt::BigInt { bits: b, .. }) => {
|
||||||
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);
|
||||||
|
@ -1975,14 +1845,8 @@ 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::Comptime(b),
|
| (ComptimeInt::BigInt { bits: b, .. }, rhs @ ComptimeInt::Native { ty: a_ty, .. }) => {
|
||||||
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);
|
||||||
|
@ -1999,10 +1863,7 @@ 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);
|
||||||
|
@ -2014,10 +1875,7 @@ 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);
|
||||||
|
@ -2029,20 +1887,14 @@ 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 {
|
||||||
|
@ -2063,56 +1915,36 @@ 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)) => {
|
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a + b)),
|
||||||
Ok(Self::Binary32(a + b))
|
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(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)) => {
|
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a - b)),
|
||||||
Ok(Self::Binary32(a - b))
|
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(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)) => {
|
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a * b)),
|
||||||
Ok(Self::Binary32(a * b))
|
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(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)) => {
|
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a / b)),
|
||||||
Ok(Self::Binary32(a / b))
|
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(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)) => {
|
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => Ok(Self::Binary32(a % b)),
|
||||||
Ok(Self::Binary32(a % b))
|
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => Ok(Self::Binary64(a % b)),
|
||||||
}
|
|
||||||
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
|
|
||||||
Ok(Self::Binary64(a % b))
|
|
||||||
}
|
|
||||||
_ => Err(Error::IncompatibleTypes),
|
_ => Err(Error::IncompatibleTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2124,12 +1956,8 @@ 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)) => {
|
(ComptimeFloat::Binary32(a), ComptimeFloat::Binary32(b)) => a.partial_cmp(&b),
|
||||||
a.partial_cmp(&b)
|
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => a.partial_cmp(&b),
|
||||||
}
|
|
||||||
(ComptimeFloat::Binary64(a), ComptimeFloat::Binary64(b)) => {
|
|
||||||
a.partial_cmp(&b)
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::IncompatibleTypes);
|
return Err(Error::IncompatibleTypes);
|
||||||
}
|
}
|
||||||
|
@ -2281,9 +2109,7 @@ 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)) => {
|
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a.bitand(b))),
|
||||||
Ok(Self::Bool(a.bitand(b)))
|
|
||||||
}
|
|
||||||
_ => Err(Error::IncompatibleTypes),
|
_ => Err(Error::IncompatibleTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2295,9 +2121,7 @@ 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)) => {
|
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a.bitor(b))),
|
||||||
Ok(Self::Bool(a.bitor(b)))
|
|
||||||
}
|
|
||||||
_ => Err(Error::IncompatibleTypes),
|
_ => Err(Error::IncompatibleTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2309,9 +2133,7 @@ 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)) => {
|
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a.bitxor(b))),
|
||||||
Ok(Self::Bool(a.bitxor(b)))
|
|
||||||
}
|
|
||||||
_ => Err(Error::IncompatibleTypes),
|
_ => Err(Error::IncompatibleTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2347,9 +2169,7 @@ 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)) => {
|
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a || b)),
|
||||||
Ok(Self::Bool(a || b))
|
|
||||||
}
|
|
||||||
_ => Err(Error::IncompatibleTypes),
|
_ => Err(Error::IncompatibleTypes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2361,35 +2181,23 @@ 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)) => {
|
(ComptimeNumber::Bool(a), ComptimeNumber::Bool(b)) => Ok(Self::Bool(a && 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)) => {
|
(ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => Ok(Self::Bool(a == 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)),
|
||||||
(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)) => {
|
(ComptimeNumber::Integral(a), ComptimeNumber::Integral(b)) => a.cmp(b)?,
|
||||||
a.cmp(b)?
|
(ComptimeNumber::Floating(a), ComptimeNumber::Floating(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);
|
||||||
|
@ -2429,17 +2237,12 @@ 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::Comptime(bits) | ComptimeInt::BigInt { bits, .. } => {
|
||||||
| ComptimeInt::BigInt { bits, .. } => {
|
|
||||||
Ok((bits.sign() != Sign::NoSign).into())
|
Ok((bits.sign() != Sign::NoSign).into())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ComptimeNumber::Floating(ComptimeFloat::Binary32(f)) => {
|
ComptimeNumber::Floating(ComptimeFloat::Binary32(f)) => Ok((f != 0.0).into()),
|
||||||
Ok((f != 0.0).into())
|
ComptimeNumber::Floating(ComptimeFloat::Binary64(f)) => Ok((f != 0.0).into()),
|
||||||
}
|
|
||||||
ComptimeNumber::Floating(ComptimeFloat::Binary64(f)) => {
|
|
||||||
Ok((f != 0.0).into())
|
|
||||||
}
|
|
||||||
a => Ok(a),
|
a => Ok(a),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2447,29 +2250,19 @@ 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, .. } => {
|
ComptimeInt::Native { bits, .. } => Ok((bits & ty.u128_bitmask(), ty).into()),
|
||||||
Ok((bits & ty.u128_bitmask(), ty).into())
|
ComptimeInt::Comptime(bits) | ComptimeInt::BigInt { bits, .. } => {
|
||||||
}
|
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) => {
|
ComptimeNumber::Bool(b) => Ok((b as u128 & ty.u128_bitmask(), ty).into()),
|
||||||
Ok((b as u128 & ty.u128_bitmask(), ty).into())
|
|
||||||
}
|
|
||||||
ComptimeNumber::Floating(f) => match f {
|
ComptimeNumber::Floating(f) => match f {
|
||||||
ComptimeFloat::Binary32(f) => {
|
ComptimeFloat::Binary32(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()),
|
||||||
}
|
|
||||||
ComptimeFloat::Binary64(f) => {
|
|
||||||
Ok((f as u128 & ty.u128_bitmask(), ty).into())
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
ComptimeNumber::Void => {
|
ComptimeNumber::Void => {
|
||||||
return Err(Error::VoidConversion);
|
return Err(Error::VoidConversion);
|
||||||
|
@ -2480,8 +2273,7 @@ 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::Comptime(bits) | ComptimeInt::BigInt { bits, .. } => {
|
||||||
| ComptimeInt::BigInt { bits, .. } => {
|
|
||||||
bits.to_f64().unwrap_or(f64::NAN)
|
bits.to_f64().unwrap_or(f64::NAN)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
97
src/lexer.rs
97
src/lexer.rs
|
@ -83,11 +83,7 @@ impl<'a> Chars<'a> {
|
||||||
SourceLocation::new(start_l, start_c)
|
SourceLocation::new(start_l, start_c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_source_span(
|
pub fn get_source_span(&self, start: u32, end: u32) -> std::ops::Range<SourceLocation> {
|
||||||
&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| {
|
||||||
|
@ -138,18 +134,12 @@ 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(
|
core::str::from_utf8_unchecked(&self.bytes[range.start as usize..range.end as usize])
|
||||||
&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 {
|
unsafe { core::str::from_utf8_unchecked(&self.bytes[start as usize..end as usize]) }
|
||||||
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> {
|
||||||
|
@ -215,12 +205,7 @@ impl DelimitorConditions {
|
||||||
|| self.semis > cond.semis
|
|| self.semis > cond.semis
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_i32s(
|
fn from_i32s(braces: i32, parens: i32, brackets: i32, semis: Option<u32>) -> Self {
|
||||||
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),
|
||||||
|
@ -231,10 +216,7 @@ impl DelimitorConditions {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TokenIterator<'a> {
|
impl<'a> TokenIterator<'a> {
|
||||||
pub fn advance_until_before_token(
|
pub fn advance_until_before_token(&mut self, token: Token) -> Option<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);
|
||||||
|
@ -244,10 +226,7 @@ impl<'a> TokenIterator<'a> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn advance_until_before_one_of(
|
pub fn advance_until_before_one_of(&mut self, tokens: &[Token]) -> Option<Token> {
|
||||||
&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());
|
||||||
|
@ -325,19 +304,13 @@ impl<'a> TokenIterator<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn advance_until_condition(
|
fn advance_until_condition(&mut self, cond: DelimitorConditions) -> Option<()> {
|
||||||
&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(
|
fn advance_past_condition(&mut self, cond: DelimitorConditions) -> Option<()> {
|
||||||
&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;
|
||||||
|
@ -368,12 +341,8 @@ impl<'a> TokenIterator<'a> {
|
||||||
_ => { /* nada */ }
|
_ => { /* nada */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
let current = DelimitorConditions::from_i32s(
|
let current =
|
||||||
braces,
|
DelimitorConditions::from_i32s(braces, parens, brackets, cond.semis.map(|_| semis));
|
||||||
parens,
|
|
||||||
brackets,
|
|
||||||
cond.semis.map(|_| semis),
|
|
||||||
);
|
|
||||||
if cond == current {
|
if cond == current {
|
||||||
return Some(());
|
return Some(());
|
||||||
}
|
}
|
||||||
|
@ -408,16 +377,13 @@ impl<'a> TokenIterator<'a> {
|
||||||
.next()
|
.next()
|
||||||
.map(|i| i.source_location())
|
.map(|i| i.source_location())
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
self.tokenizer.source.offset_to_source_location(
|
self.tokenizer
|
||||||
self.tokenizer.source.num_bytes() as u32,
|
.source
|
||||||
)
|
.offset_to_source_location(self.tokenizer.source.num_bytes() as u32)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expect_token(
|
pub fn expect_token(&mut self, token: Token) -> crate::parser::Result<TokenItem<'a>> {
|
||||||
&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))
|
||||||
}
|
}
|
||||||
|
@ -429,18 +395,13 @@ 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(
|
pub fn peek_token_or_err(&mut self) -> crate::parser::Result<TokenItem<'a>> {
|
||||||
&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(
|
pub fn peek_expect_token(&mut self, token: Token) -> crate::parser::Result<TokenItem<'a>> {
|
||||||
&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))
|
||||||
|
@ -683,16 +644,9 @@ impl<'a> Tokenizer<'a> {
|
||||||
// .unwrap_or(false);
|
// .unwrap_or(false);
|
||||||
let end = this.source.position();
|
let end = this.source.position();
|
||||||
|
|
||||||
if this
|
if this.source.peek().map(|c| crate::common::is_whitespace(c)) != Some(true) {
|
||||||
.source
|
|
||||||
.peek()
|
|
||||||
.map(|c| crate::common::is_whitespace(c))
|
|
||||||
!= Some(true)
|
|
||||||
{
|
|
||||||
this.source
|
this.source
|
||||||
.take_while_ref(|&c| {
|
.take_while_ref(|&c| !crate::common::is_whitespace(c))
|
||||||
!crate::common::is_whitespace(c)
|
|
||||||
})
|
|
||||||
.count();
|
.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -759,10 +713,7 @@ 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('.')
|
Some('.') if peeking.next().map(|c| crate::common::is_digit(c)) == Some(true) => {
|
||||||
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,
|
||||||
|
@ -845,11 +796,7 @@ impl<'a> Tokenizer<'a> {
|
||||||
.count()
|
.count()
|
||||||
.gt(&0)
|
.gt(&0)
|
||||||
{
|
{
|
||||||
return self.push_token(
|
return self.push_token(Token::Ident, start, self.source.position());
|
||||||
Token::Ident,
|
|
||||||
start,
|
|
||||||
self.source.position(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1099,9 +1046,7 @@ fn parse_constant_inner(source: &mut Chars) -> Result<Token> {
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
if let Some(_) =
|
if let Some(_) = source.try_parse_result(|source| try_parse_integral_type(source))? {
|
||||||
source.try_parse_result(|source| try_parse_integral_type(source))?
|
|
||||||
{
|
|
||||||
return Ok(Token::IntegerConstant);
|
return Ok(Token::IntegerConstant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
44
src/lib.rs
44
src/lib.rs
|
@ -9,8 +9,7 @@
|
||||||
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)]
|
||||||
|
|
||||||
|
@ -31,45 +30,6 @@ pub mod triples;
|
||||||
|
|
||||||
pub fn tokenize<'a>(
|
pub fn tokenize<'a>(
|
||||||
bytes: &'a [u8],
|
bytes: &'a [u8],
|
||||||
) -> Result<
|
) -> Result<lexer::Tokenizer<'a>, (lexer::Tokenizer<'a>, Vec<lexer::TokenizeError>)> {
|
||||||
lexer::Tokenizer<'a>,
|
|
||||||
(lexer::Tokenizer<'a>, Vec<lexer::TokenizeError>),
|
|
||||||
> {
|
|
||||||
lexer::Tokenizer::new_with_errors(bytes)
|
lexer::Tokenizer::new_with_errors(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
1210
src/mir.rs
1210
src/mir.rs
File diff suppressed because it is too large
Load diff
577
src/parser.rs
577
src/parser.rs
File diff suppressed because it is too large
Load diff
|
@ -55,10 +55,7 @@ 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(
|
core::slice::from_raw_parts(bytes.as_ptr().cast::<u32>(), bytes.len() / 4)
|
||||||
bytes.as_ptr().cast::<u32>(),
|
|
||||||
bytes.len() / 4,
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
bigint::count_bits(ints) as u32
|
bigint::count_bits(ints) as u32
|
||||||
}
|
}
|
||||||
|
@ -120,10 +117,7 @@ mod display {
|
||||||
str: Option<&'a str>,
|
str: Option<&'a str>,
|
||||||
}
|
}
|
||||||
impl<'a> Debug for Test<'a> {
|
impl<'a> Debug for Test<'a> {
|
||||||
fn fmt(
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
&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)?;
|
||||||
|
|
|
@ -35,25 +35,13 @@ 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!(
|
_ = write!(&mut buf, "V{}::", tree.get_ident_str(*name).unwrap());
|
||||||
&mut buf,
|
|
||||||
"V{}::",
|
|
||||||
tree.get_ident_str(*name).unwrap()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Tag::GlobalDecl { name, .. } => {
|
Tag::GlobalDecl { name, .. } => {
|
||||||
_ = write!(
|
_ = write!(&mut buf, "G{}::", tree.get_ident_str(*name).unwrap());
|
||||||
&mut buf,
|
|
||||||
"G{}::",
|
|
||||||
tree.get_ident_str(*name).unwrap()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Tag::FunctionProto { name, .. } => {
|
Tag::FunctionProto { name, .. } => {
|
||||||
_ = write!(
|
_ = write!(&mut buf, "F{}::", tree.get_ident_str(*name).unwrap());
|
||||||
&mut buf,
|
|
||||||
"F{}::",
|
|
||||||
tree.get_ident_str(*name).unwrap()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -142,12 +130,7 @@ impl Drop for InnerSymbolTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InnerSymbolTable {
|
impl InnerSymbolTable {
|
||||||
fn insert_symbol(
|
fn insert_symbol(&mut self, name: &str, node: AstNode, kind: SymbolKind) -> &SymbolRecord {
|
||||||
&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 {
|
||||||
|
@ -160,11 +143,7 @@ impl InnerSymbolTable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_orderless_symbol(
|
fn insert_orderless_symbol(&mut self, name: &str, node: AstNode) -> &SymbolRecord {
|
||||||
&mut self,
|
|
||||||
name: &str,
|
|
||||||
node: AstNode,
|
|
||||||
) -> &SymbolRecord {
|
|
||||||
self.orderless_identifiers.insert(
|
self.orderless_identifiers.insert(
|
||||||
name.to_owned(),
|
name.to_owned(),
|
||||||
SymbolRecord {
|
SymbolRecord {
|
||||||
|
@ -175,11 +154,7 @@ impl InnerSymbolTable {
|
||||||
self.orderless_identifiers.get(name).unwrap()
|
self.orderless_identifiers.get(name).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_symbol_or_insert_with<'a, F>(
|
fn find_symbol_or_insert_with<'a, F>(&'a mut self, name: &str, cb: F) -> &'a SymbolRecord
|
||||||
&'a mut self,
|
|
||||||
name: &str,
|
|
||||||
cb: F,
|
|
||||||
) -> &'a SymbolRecord
|
|
||||||
where
|
where
|
||||||
F: FnOnce() -> (AstNode, SymbolKind),
|
F: FnOnce() -> (AstNode, SymbolKind),
|
||||||
{
|
{
|
||||||
|
@ -202,9 +177,7 @@ impl InnerSymbolTable {
|
||||||
.find(|(_, v)| v.decl == decl)
|
.find(|(_, v)| v.decl == decl)
|
||||||
.map(|(_, v)| v)
|
.map(|(_, v)| v)
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
.or_else(|| self.parent_ref().and_then(|p| p.find_symbol_by_decl(decl)))
|
||||||
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> {
|
||||||
|
@ -219,9 +192,7 @@ 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(|| {
|
.or_else(|| self.parent_ref().and_then(|p| p.find_ordered_symbol(name)))
|
||||||
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> {
|
||||||
|
@ -315,12 +286,7 @@ impl SymbolTableWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SymbolTableWrapper {
|
impl SymbolTableWrapper {
|
||||||
pub fn insert_symbol(
|
pub fn insert_symbol(&mut self, name: &str, node: AstNode, kind: SymbolKind) -> &SymbolRecord {
|
||||||
&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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,27 +294,15 @@ impl SymbolTableWrapper {
|
||||||
self.root_mut().find_orderless_symbol(name)
|
self.root_mut().find_orderless_symbol(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_root_symbol(
|
pub fn insert_root_symbol(&mut self, name: &str, node: AstNode) -> &SymbolRecord {
|
||||||
&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(
|
pub fn insert_orderless_symbol(&mut self, name: &str, node: AstNode) -> &SymbolRecord {
|
||||||
&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>(
|
pub fn find_symbol_or_insert_with<'a, F>(&'a mut self, name: &str, cb: F) -> &'a SymbolRecord
|
||||||
&'a mut self,
|
|
||||||
name: &str,
|
|
||||||
cb: F,
|
|
||||||
) -> &'a SymbolRecord
|
|
||||||
where
|
where
|
||||||
F: FnOnce() -> (AstNode, SymbolKind),
|
F: FnOnce() -> (AstNode, SymbolKind),
|
||||||
{
|
{
|
||||||
|
@ -526,9 +480,7 @@ 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 { .. } => {
|
Key::ScopeByIndex { .. } => ExpandedPayload::Intern(val.as_intern()),
|
||||||
ExpandedPayload::Intern(val.as_intern())
|
|
||||||
}
|
|
||||||
_ => ExpandedPayload::Ast(val.as_ast()),
|
_ => ExpandedPayload::Ast(val.as_ast()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -637,10 +589,8 @@ pub mod syms2 {
|
||||||
kind: SymbolKind,
|
kind: SymbolKind,
|
||||||
ast: AstIndex,
|
ast: AstIndex,
|
||||||
) {
|
) {
|
||||||
self.inner.insert(
|
self.inner
|
||||||
Key::Symbol { scope, name, kind },
|
.insert(Key::Symbol { scope, name, kind }, Payload::new_ast(ast));
|
||||||
Payload::new_ast(ast),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,11 +172,7 @@ impl Token {
|
||||||
}
|
}
|
||||||
pub fn is_unary_op(self) -> bool {
|
pub fn is_unary_op(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Token::Plus
|
Token::Plus | Token::Minus | Token::Star | Token::Ampersand | Token::Bang => true,
|
||||||
| Token::Minus
|
|
||||||
| Token::Star
|
|
||||||
| Token::Ampersand
|
|
||||||
| Token::Bang => true,
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,16 +264,15 @@ 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(
|
char::from_u32_unchecked(tok.lexeme().unwrap().as_bytes()[self.len - 1] as u32)
|
||||||
tok.lexeme().unwrap().as_bytes()[self.len - 1] as u32,
|
== ch
|
||||||
) == 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
|
||||||
|
|
1016
src/triples.rs
1016
src/triples.rs
File diff suppressed because it is too large
Load diff
4
test.sh
4
test.sh
|
@ -1,4 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
cargo run --bin main -- -i "$1" asm > asm.S
|
|
||||||
clang asm.S -c && clang asm.o -o asm && ./asm; echo $?
|
|
|
@ -2,4 +2,4 @@ fn main() -> i32 {
|
||||||
return RANDOM;
|
return RANDOM;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RANDOM: i32 = 4i32 + (1i32 << 3i32);
|
const RANDOM: i32 = 4 + (1 << 3);
|
||||||
|
|
Loading…
Reference in a new issue