Compare commits

...

7 Commits

20 changed files with 315 additions and 101 deletions

View File

@ -1,17 +1,6 @@
// Arithmetic, function calls and imports!
import std::print;
import std::from_str;
import std::add_num_to_str;
import std::free_string;
fn main() -> u32 {
for i in 0 .. 15 {
let mut text = from_str("num: ");
add_num_to_str(&mut text, i);
print(text);
free_string(&text);
}
let mut num = 0;
while num < 10 {

10
examples/or_bitwise.reid Normal file
View File

@ -0,0 +1,10 @@
// Arithmetic, function calls and imports!
fn main() -> bool {
let bwand = (0xff & 0xf0) >> 4;
let bwor = (0x0fu32 | 0x00) << 4;
let bwxor = (0xf0 | 0x0f);
return (bwxor == 255) && ((bwand == 15) || false) && (bwor == 240);
}

7
examples/test.reid Normal file
View File

@ -0,0 +1,7 @@
// Arithmetic, function calls and imports!
fn main() -> bool {
return 5.0 > -1;
}

View File

@ -410,6 +410,8 @@ impl Builder {
}
}
Instr::And(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
Instr::Or(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
Instr::XOr(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
Instr::ICmp(_, lhs, rhs) => {
let t = match_types(&lhs, &rhs, self)?;
if t.category().comparable() || !t.category().integer() {
@ -528,6 +530,30 @@ impl Builder {
Instr::PtrToInt(instr, ty) => instr.cast_to(self, &ty).map(|_| ()),
Instr::IntToPtr(instr, ty) => instr.cast_to(self, &ty).map(|_| ()),
Instr::BitCast(..) => Ok(()),
Instr::ShiftRightLogical(_, rhs) => {
let rhs_ty = rhs.get_type(&self)?;
if rhs_ty.category() == TypeCategory::UnsignedInteger {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::ShiftRightArithmetic(_, rhs) => {
let rhs_ty = rhs.get_type(&self)?;
if rhs_ty.category() == TypeCategory::UnsignedInteger {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::ShiftLeft(_, rhs) => {
let rhs_ty = rhs.get_type(&self)?;
if rhs_ty.category() == TypeCategory::UnsignedInteger {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
}
}
}
@ -614,6 +640,8 @@ impl InstructionValue {
SRem(lhs, rhs) => match_types(lhs, rhs, &builder),
FRem(lhs, rhs) => match_types(lhs, rhs, &builder),
And(lhs, rhs) => match_types(lhs, rhs, &builder),
Or(lhs, rhs) => match_types(lhs, rhs, &builder),
XOr(lhs, rhs) => match_types(lhs, rhs, &builder),
ICmp(_, _, _) => Ok(Type::Bool),
FCmp(_, _, _) => Ok(Type::Bool),
FunctionCall(function_value, _) => Ok(builder.function_data(function_value).ret),
@ -674,6 +702,9 @@ impl InstructionValue {
PtrToInt(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()),
IntToPtr(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()),
BitCast(_, ty) => Ok(ty.clone()),
ShiftRightLogical(lhs, _) => lhs.get_type(builder),
ShiftRightArithmetic(lhs, _) => lhs.get_type(builder),
ShiftLeft(lhs, _) => lhs.get_type(builder),
}
}
}

View File

@ -975,6 +975,31 @@ impl InstructionHolder {
ty.as_llvm(module.context_ref, &module.types),
name.as_ptr(),
),
Or(lhs, rhs) => {
let lhs_val = module.values.get(&lhs).unwrap().value_ref;
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
LLVMBuildOr(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
}
XOr(lhs, rhs) => {
let lhs_val = module.values.get(&lhs).unwrap().value_ref;
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
LLVMBuildXor(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
}
ShiftRightLogical(lhs, rhs) => {
let lhs_val = module.values.get(&lhs).unwrap().value_ref;
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
LLVMBuildLShr(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
}
ShiftRightArithmetic(lhs, rhs) => {
let lhs_val = module.values.get(&lhs).unwrap().value_ref;
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
LLVMBuildAShr(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
}
ShiftLeft(lhs, rhs) => {
let lhs_val = module.values.get(&lhs).unwrap().value_ref;
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
LLVMBuildShl(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
}
}
};
if let Some(record) = &self.record {

View File

@ -9,10 +9,10 @@ use crate::{
CmpPredicate, Context, Instr, InstructionData, TerminatorKind,
builder::*,
debug_information::{
DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable,
DebugLocation, DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable,
DebugPointerType, DebugPosition, DebugProgramValue, DebugRecordKind, DebugScopeValue,
DebugStructType, DebugSubprogramType, DebugTypeData, DebugTypeHolder, DebugTypeValue,
DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable, DebugLocation,
DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable, DebugPointerType, DebugPosition,
DebugProgramValue, DebugRecordKind, DebugScopeValue, DebugStructType, DebugSubprogramType, DebugTypeData,
DebugTypeHolder, DebugTypeValue,
},
pad_adapter::PadAdapter,
};
@ -68,11 +68,7 @@ impl FunctionHolder {
.map(|p| format!("{:?}", p))
.collect::<Vec<_>>()
.join(", ");
write!(
f,
"fn {}({}) -> {:?} ",
self.data.name, params, self.data.ret
)?;
write!(f, "fn {}({}) -> {:?} ", self.data.name, params, self.data.ret)?;
writeln!(f, "{{")?;
let mut state = Default::default();
@ -116,11 +112,7 @@ impl BlockHolder {
terminator.builder_fmt(&mut inner, builder, debug)?;
}
if let Some(location) = self.data.terminator_location {
writeln!(
inner,
" ^ (At {}) ",
debug.as_ref().unwrap().get_location(location)
)?;
writeln!(inner, " ^ (At {}) ", debug.as_ref().unwrap().get_location(location))?;
}
Ok(())
@ -148,11 +140,7 @@ impl InstructionHolder {
writeln!(f, " (Debug {} {})", record.variable.hr(debug), kind)?;
}
}
writeln!(
f,
"{:?} ({}) = {:?} ",
self.value, self.name, self.data.kind
)?;
writeln!(f, "{:?} ({}) = {:?} ", self.value, self.name, self.data.kind)?;
if let Some(debug) = debug {
if let Some(location) = self.data.location {
writeln!(f, " ^ (At {}) ", debug.get_location(location))?;
@ -188,9 +176,9 @@ impl TerminatorKind {
impl DebugMetadataValue {
fn hr(&self, debug: &DebugInformation) -> String {
let kind = match debug.get_metadata(*self) {
DebugMetadata::ParamVar(DebugParamVariable {
name, arg_idx, ty, ..
}) => format!("param {} (idx {}) (type {:?}) ", name, arg_idx, ty),
DebugMetadata::ParamVar(DebugParamVariable { name, arg_idx, ty, .. }) => {
format!("param {} (idx {}) (type {:?}) ", name, arg_idx, ty)
}
DebugMetadata::LocalVar(DebugLocalVariable { name, ty, .. }) => {
format!("var {} (type {:?}) ", name, ty)
}
@ -253,14 +241,11 @@ impl Debug for FunctionHolder {
impl Debug for BlockHolder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let deleted = if self.data.deleted { " (deleted)" } else { "" };
f.debug_tuple(&format!(
"{}[{:?}]{} ",
&self.data.name, &self.value, deleted
))
.field(&self.instructions)
.field(&self.data.terminator)
.field(&self.data.terminator_location)
.finish()
f.debug_tuple(&format!("{}[{:?}]{} ", &self.data.name, &self.value, deleted))
.field(&self.instructions)
.field(&self.data.terminator)
.field(&self.data.terminator_location)
.finish()
}
}
@ -303,11 +288,7 @@ impl Debug for BlockValue {
impl Debug for InstructionValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"%{}.{}.{}.{}",
self.0.0.0.0, self.0.0.1, self.0.1, self.1
)
write!(f, "%{}.{}.{}.{}", self.0.0.0.0, self.0.0.1, self.0.1, self.1)
}
}
@ -369,9 +350,7 @@ impl Debug for Instr {
fmt_index(f, instruction_value, &index.to_string())?;
write!(f, ")")
}
Instr::ExtractValue(instruction_value, index) => {
fmt_index(f, instruction_value, &index.to_string())
}
Instr::ExtractValue(instruction_value, index) => fmt_index(f, instruction_value, &index.to_string()),
Instr::Trunc(instr_val, ty) => {
write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name())
}
@ -408,6 +387,11 @@ impl Debug for Instr {
Instr::BitCast(instr_val, ty) => {
write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name())
}
Instr::Or(lhs, rhs) => fmt_binop(f, lhs, &"||", rhs),
Instr::XOr(lhs, rhs) => fmt_binop(f, lhs, &"^", rhs),
Instr::ShiftRightLogical(lhs, rhs) => fmt_binop(f, lhs, &">>l", rhs),
Instr::ShiftRightArithmetic(lhs, rhs) => fmt_binop(f, lhs, &">>a", rhs),
Instr::ShiftLeft(lhs, rhs) => fmt_binop(f, lhs, &"<<", rhs),
}
}
}
@ -579,11 +563,7 @@ impl Debug for DebugScopeValue {
write!(
f,
"Scope[{}]",
self.0
.iter()
.map(|v| v.to_string())
.collect::<Vec<_>>()
.join(", ")
self.0.iter().map(|v| v.to_string()).collect::<Vec<_>>().join(", ")
)
}
}

View File

@ -251,6 +251,11 @@ impl Instr {
Instr::PtrToInt(_, _) => "ptrtoint",
Instr::IntToPtr(_, _) => "inttoptr",
Instr::BitCast(_, _) => "bitcast",
Instr::Or(..) => "or",
Instr::XOr(..) => "xor",
Instr::ShiftRightLogical(..) => "lshr",
Instr::ShiftRightArithmetic(..) => "ashr",
Instr::ShiftLeft(..) => "shl",
}
}
}
@ -369,7 +374,14 @@ pub enum Instr {
SRem(InstructionValue, InstructionValue),
/// Get the remainder from two floats
FRem(InstructionValue, InstructionValue),
And(InstructionValue, InstructionValue),
Or(InstructionValue, InstructionValue),
XOr(InstructionValue, InstructionValue),
ShiftRightLogical(InstructionValue, InstructionValue),
ShiftRightArithmetic(InstructionValue, InstructionValue),
ShiftLeft(InstructionValue, InstructionValue),
Phi(Vec<InstructionValue>),
Alloca(Type),

View File

@ -88,6 +88,10 @@ pub enum Token {
LessThan,
/// `&`
Et,
/// `|`
Pipe,
/// `^`
Hat,
/// `!`
Exclamation,
@ -174,6 +178,8 @@ impl ToString for Token {
Token::GreaterThan => String::from('>'),
Token::LessThan => String::from('<'),
Token::Et => String::from('&'),
Token::Pipe => String::from('|'),
Token::Hat => String::from('^'),
Token::Exclamation => String::from('!'),
Token::ParenOpen => String::from('('),
Token::ParenClose => String::from(')'),
@ -411,6 +417,8 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error
'>' => Token::GreaterThan,
'<' => Token::LessThan,
'&' => Token::Et,
'|' => Token::Pipe,
'^' => Token::Hat,
'!' => Token::Exclamation,
'(' => Token::ParenOpen,
')' => Token::ParenClose,

View File

@ -116,7 +116,14 @@ pub enum BinaryOperator {
Div,
Mod,
BitshiftRight,
BitshiftLeft,
And,
Or,
Xor,
BWAnd,
BWOr,
LT,
LE,
GT,
@ -126,7 +133,7 @@ pub enum BinaryOperator {
}
impl BinaryOperator {
pub fn get_precedence(&self) -> i8 {
pub fn get_precedence(&self) -> u8 {
use BinaryOperator::*;
match &self {
Minus => 5,
@ -134,13 +141,20 @@ impl BinaryOperator {
Mult => 15,
Div => 20,
Mod => 20,
And => 100,
LT => 100,
LE => 100,
GT => 100,
GE => 100,
EQ => 100,
NE => 100,
BWAnd => 90,
BWOr => 90,
BWXor => 90,
BitshiftLeft => 100,
BitshiftRight => 100,
And => 150,
Or => 150,
Xor => 150,
LT => 150,
LE => 150,
GT => 150,
GE => 150,
EQ => 150,
NE => 150,
}
}
}

View File

@ -488,6 +488,10 @@ impl Parse for BinaryOperator {
stream.next();
BinaryOperator::And
}
(Some(Token::Pipe), Some(Token::Pipe)) => {
stream.next();
BinaryOperator::Or
}
(Some(Token::LessThan), Some(Token::Equals)) => {
stream.next();
BinaryOperator::LE
@ -504,6 +508,18 @@ impl Parse for BinaryOperator {
stream.next();
BinaryOperator::NE
}
(Some(Token::GreaterThan), Some(Token::GreaterThan)) => {
stream.next();
BinaryOperator::BitshiftRight
}
(Some(Token::LessThan), Some(Token::LessThan)) => {
stream.next();
BinaryOperator::BitshiftLeft
}
(Some(Token::Hat), _) => BinaryOperator::Xor,
(Some(Token::Et), _) => BinaryOperator::BWAnd,
(Some(Token::Pipe), _) => BinaryOperator::BWOr,
(Some(Token::LessThan), _) => BinaryOperator::LT,
(Some(Token::GreaterThan), _) => BinaryOperator::GT,

View File

@ -446,15 +446,21 @@ impl ast::BinaryOperator {
ast::BinaryOperator::Add => mir::BinaryOperator::Add,
ast::BinaryOperator::Minus => mir::BinaryOperator::Minus,
ast::BinaryOperator::Mult => mir::BinaryOperator::Mult,
ast::BinaryOperator::And => mir::BinaryOperator::And,
ast::BinaryOperator::Div => mir::BinaryOperator::Div,
ast::BinaryOperator::Mod => mir::BinaryOperator::Mod,
ast::BinaryOperator::And => mir::BinaryOperator::And,
ast::BinaryOperator::Or => mir::BinaryOperator::Or,
ast::BinaryOperator::LT => mir::BinaryOperator::Cmp(mir::CmpOperator::LT),
ast::BinaryOperator::LE => mir::BinaryOperator::Cmp(mir::CmpOperator::LE),
ast::BinaryOperator::GT => mir::BinaryOperator::Cmp(mir::CmpOperator::GT),
ast::BinaryOperator::GE => mir::BinaryOperator::Cmp(mir::CmpOperator::GE),
ast::BinaryOperator::EQ => mir::BinaryOperator::Cmp(mir::CmpOperator::EQ),
ast::BinaryOperator::NE => mir::BinaryOperator::Cmp(mir::CmpOperator::NE),
ast::BinaryOperator::BitshiftRight => mir::BinaryOperator::BitshiftRight,
ast::BinaryOperator::BitshiftLeft => mir::BinaryOperator::BitshiftLeft,
ast::BinaryOperator::Xor => mir::BinaryOperator::Xor,
ast::BinaryOperator::BWAnd => mir::BinaryOperator::BitAnd,
ast::BinaryOperator::BWOr => mir::BinaryOperator::BitOr,
}
}
}

View File

@ -1,3 +1,5 @@
use std::ops::BitAnd;
use reid_lib::{builder::InstructionValue, CmpPredicate, ConstValue, Instr, Type};
use crate::{
@ -84,6 +86,21 @@ where
}
}
fn complex_binop_def<T: Clone + 'static>(op: BinaryOperator, lhs: &TypeKind, rhs: &TypeKind, fun: T) -> BinopDefinition
where
T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue,
{
BinopDefinition {
lhs: ("lhs".to_owned(), lhs.clone()),
op,
rhs: ("rhs".to_owned(), rhs.clone()),
return_type: lhs.clone(),
fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr(fun))),
meta: Default::default(),
exported: false,
}
}
fn boolean_binop_def<T: Clone + 'static>(op: BinaryOperator, ty: &TypeKind, fun: T) -> BinopDefinition
where
T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue,
@ -145,6 +162,39 @@ pub fn form_intrinsic_binops() -> Vec<BinopDefinition> {
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::LE), &ty, |scope, lhs, rhs| {
scope.block.build(Instr::ICmp(CmpPredicate::LE, lhs, rhs)).unwrap()
}));
// Bitwise operations
intrinsics.push(simple_binop_def(BitOr, &ty, |scope, lhs, rhs| {
scope.block.build(Instr::Or(lhs, rhs)).unwrap()
}));
intrinsics.push(simple_binop_def(BitAnd, &ty, |scope, lhs, rhs| {
scope.block.build(Instr::And(lhs, rhs)).unwrap()
}));
intrinsics.push(complex_binop_def(Xor, &ty, &TypeKind::U64, |scope, lhs, rhs| {
scope.block.build(Instr::XOr(lhs, rhs)).unwrap()
}));
if ty.signed() {
intrinsics.push(complex_binop_def(
BitshiftRight,
&ty,
&TypeKind::U64,
|scope, lhs, rhs| scope.block.build(Instr::ShiftRightArithmetic(lhs, rhs)).unwrap(),
));
} else {
intrinsics.push(complex_binop_def(
BitshiftRight,
&ty,
&TypeKind::U64,
|scope, lhs, rhs| scope.block.build(Instr::ShiftRightLogical(lhs, rhs)).unwrap(),
));
}
intrinsics.push(complex_binop_def(
BitshiftLeft,
&ty,
&TypeKind::U64,
|scope, lhs, rhs| scope.block.build(Instr::ShiftLeft(lhs, rhs)).unwrap(),
));
}
for ty in INTEGERS.iter().chain(&[TypeKind::Bool, TypeKind::Char]) {
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::EQ), &ty, |scope, lhs, rhs| {
@ -195,6 +245,12 @@ pub fn form_intrinsic_binops() -> Vec<BinopDefinition> {
intrinsics.push(boolean_binop_def(And, &TypeKind::Bool, |scope, lhs, rhs| {
scope.block.build(Instr::And(lhs, rhs)).unwrap()
}));
intrinsics.push(boolean_binop_def(Or, &TypeKind::Bool, |scope, lhs, rhs| {
scope.block.build(Instr::Or(lhs, rhs)).unwrap()
}));
intrinsics.push(boolean_binop_def(Xor, &TypeKind::Bool, |scope, lhs, rhs| {
scope.block.build(Instr::XOr(lhs, rhs)).unwrap()
}));
intrinsics
}

View File

@ -885,6 +885,30 @@ impl mir::Expression {
.maybe_location(&mut scope.block, location);
Instr::Sub(lhs, mul)
}
(mir::BinaryOperator::Or, true, true) => todo!(),
(mir::BinaryOperator::Or, true, false) => todo!(),
(mir::BinaryOperator::Or, false, true) => todo!(),
(mir::BinaryOperator::Or, false, false) => todo!(),
(mir::BinaryOperator::Xor, true, true) => todo!(),
(mir::BinaryOperator::Xor, true, false) => todo!(),
(mir::BinaryOperator::Xor, false, true) => todo!(),
(mir::BinaryOperator::Xor, false, false) => todo!(),
(mir::BinaryOperator::BitOr, true, true) => todo!(),
(mir::BinaryOperator::BitOr, true, false) => todo!(),
(mir::BinaryOperator::BitOr, false, true) => todo!(),
(mir::BinaryOperator::BitOr, false, false) => todo!(),
(mir::BinaryOperator::BitAnd, true, true) => todo!(),
(mir::BinaryOperator::BitAnd, true, false) => todo!(),
(mir::BinaryOperator::BitAnd, false, true) => todo!(),
(mir::BinaryOperator::BitAnd, false, false) => todo!(),
(mir::BinaryOperator::BitshiftRight, true, true) => todo!(),
(mir::BinaryOperator::BitshiftRight, true, false) => todo!(),
(mir::BinaryOperator::BitshiftRight, false, true) => todo!(),
(mir::BinaryOperator::BitshiftRight, false, false) => todo!(),
(mir::BinaryOperator::BitshiftLeft, true, true) => todo!(),
(mir::BinaryOperator::BitshiftLeft, true, false) => todo!(),
(mir::BinaryOperator::BitshiftLeft, false, true) => todo!(),
(mir::BinaryOperator::BitshiftLeft, false, false) => todo!(),
};
Some(StackValue(
StackValueKind::Immutable(

View File

@ -352,6 +352,12 @@ impl Display for BinaryOperator {
BinaryOperator::Cmp(op) => Display::fmt(op, f),
BinaryOperator::Div => write!(f, "/"),
BinaryOperator::Mod => write!(f, "%"),
BinaryOperator::Or => write!(f, "||"),
BinaryOperator::Xor => write!(f, "^"),
BinaryOperator::BitOr => write!(f, "|"),
BinaryOperator::BitAnd => write!(f, "&"),
BinaryOperator::BitshiftRight => write!(f, ">>"),
BinaryOperator::BitshiftLeft => write!(f, "<<"),
}
}
}

View File

@ -26,40 +26,6 @@ enum BlockReturn<'b> {
}
impl TypeKind {
/// Return the type that is the result of a binary operator between two
/// values of this type
pub fn simple_binop_type(&self, op: &BinaryOperator) -> Option<TypeKind> {
if !self.category().is_simple_maths() {
return None;
}
Some(match op {
BinaryOperator::Add => self.clone(),
BinaryOperator::Minus => self.clone(),
BinaryOperator::Mult => self.clone(),
BinaryOperator::And => TypeKind::Bool,
BinaryOperator::Cmp(_) => TypeKind::Bool,
BinaryOperator::Div => self.clone(),
BinaryOperator::Mod => self.clone(),
})
}
/// Reverse of binop_type, where the given hint is the known required output
/// type of the binop, and the output is the hint for the lhs/rhs type.
pub fn simple_binop_hint(&self, op: &BinaryOperator) -> Option<TypeKind> {
if !self.category().is_simple_maths() {
return None;
}
match op {
BinaryOperator::Add
| BinaryOperator::Minus
| BinaryOperator::Mult
| BinaryOperator::Div
| BinaryOperator::Mod => Some(self.clone()),
BinaryOperator::And => None,
BinaryOperator::Cmp(_) => None,
}
}
pub fn signed(&self) -> bool {
match self {
TypeKind::Bool => false,
@ -240,6 +206,12 @@ impl BinaryOperator {
CmpOperator::EQ => true,
CmpOperator::NE => true,
},
BinaryOperator::Or => true,
BinaryOperator::Xor => true,
BinaryOperator::BitOr => true,
BinaryOperator::BitAnd => true,
BinaryOperator::BitshiftRight => false,
BinaryOperator::BitshiftLeft => false,
}
}
}
@ -507,6 +479,12 @@ impl Expression {
}
maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a % b)
}
BinaryOperator::Or => None,
BinaryOperator::Xor => maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a ^ b),
BinaryOperator::BitOr => maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a | b),
BinaryOperator::BitAnd => maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a & b),
BinaryOperator::BitshiftRight => maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a >> b),
BinaryOperator::BitshiftLeft => maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a << b),
},
ExprKind::FunctionCall(..) => None,
ExprKind::If(_) => None,

View File

@ -222,6 +222,12 @@ pub enum BinaryOperator {
Div,
Mod,
And,
Or,
Xor,
BitOr,
BitAnd,
BitshiftRight,
BitshiftLeft,
Cmp(CmpOperator),
}

View File

@ -135,7 +135,14 @@ impl TypeKind {
| TypeKind::U16
| TypeKind::U32
| TypeKind::U64
| TypeKind::U128 => Ok(other.clone()),
| TypeKind::U128
| TypeKind::F16
| TypeKind::F32B
| TypeKind::F32
| TypeKind::F64
| TypeKind::F80
| TypeKind::F128
| TypeKind::F128PPC => Ok(other.clone()),
_ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())),
},
(TypeKind::Vague(Vague::Decimal), other) | (other, TypeKind::Vague(Vague::Decimal)) => match other {

View File

@ -431,6 +431,7 @@ impl Expression {
params: (lhs_type.clone(), rhs_type.clone()),
operator: *op,
});
// dbg!(&lhs_type, &rhs_type, &binops, &ret_ty, &expected_return_ty);
if let Some(binop) = binops
.iter()
.filter(|f| f.1.return_ty.narrow_into(&expected_return_ty).is_ok())

View File

@ -390,6 +390,9 @@ impl Expression {
widened_rhs = widened_rhs.widen_into(&binop.hands.1);
}
let binop_res = type_refs.from_binop(*op, &lhs_ref, &rhs_ref);
// dbg!(&return_ty);
// dbg!(&binop_res);
// dbg!(&lhs_ref, &rhs_ref, &binops, &widened_lhs, &widened_rhs);
lhs_ref.narrow(&type_refs.from_type(&widened_lhs).unwrap());
rhs_ref.narrow(&type_refs.from_type(&widened_rhs).unwrap());
*return_ty = binop_res.as_type();

View File

@ -332,21 +332,56 @@ impl<'outer> ScopeTypeRefs<'outer> {
.widen(self.types);
self.narrow_to_type(&hint1, &ty)?;
let hint1_typeref = self.types.retrieve_typeref(*hint1.0.borrow()).unwrap();
let hint2_typeref = self.types.retrieve_typeref(*hint2.0.borrow()).unwrap();
match (&hint1_typeref, &hint2_typeref) {
(TypeRefKind::Direct(ret_ty), TypeRefKind::BinOp(op, lhs, rhs)) => {
let mut lhs_ref = self.from_type(&lhs).unwrap();
let mut rhs_ref = self.from_type(&rhs).unwrap();
let binops = self.available_binops(op, &mut lhs_ref, &mut rhs_ref);
let mut binops = binops
.iter()
.filter(|b| b.return_ty.narrow_into(ret_ty).is_ok())
.into_iter();
if let Some(binop) = binops.next() {
let mut lhs_widened = binop.hands.0.clone();
let mut rhs_widened = binop.hands.1.clone();
while let Some(binop) = binops.next() {
lhs_widened = lhs_widened.widen_into(&binop.hands.0);
rhs_widened = rhs_widened.widen_into(&binop.hands.1);
}
lhs_ref.narrow(&self.from_type(&lhs_widened).unwrap());
rhs_ref.narrow(&self.from_type(&rhs_widened).unwrap());
}
}
_ => {}
}
for idx in self.types.type_refs.borrow_mut().iter_mut() {
match hint1_typeref {
TypeRefKind::Direct(_) => {
match (&hint1_typeref, &hint2_typeref) {
(TypeRefKind::Direct(_), TypeRefKind::Direct(_)) => {
if *idx == hint2.0 && idx != &hint1.0 {
*idx.borrow_mut() = *hint1.0.borrow();
}
}
TypeRefKind::BinOp(_, _, _) => {
(TypeRefKind::Direct(_), TypeRefKind::BinOp(..)) => {}
(TypeRefKind::BinOp(..), TypeRefKind::Direct(..)) => {
// TODO may not be good ?
// if *idx == hint2.0 && idx != &hint1.0 {
// *idx.borrow_mut() = *hint1.0.borrow();
// }
}
(TypeRefKind::BinOp(..), TypeRefKind::BinOp(..)) => {
// TODO may not be good ?
if *idx == hint2.0 && idx != &hint1.0 {
*idx.borrow_mut() = *hint1.0.borrow();
}
}
}
}
Some(TypeRef(hint1.0.clone(), self))
}
}