support numerical comparisons

This commit is contained in:
Sebastien Bourdeauducq 2020-03-29 16:56:07 +08:00
parent 37f7140bb8
commit ea699fb46f
1 changed files with 66 additions and 2 deletions

View File

@ -20,6 +20,7 @@ use inkwell::targets::*;
use inkwell::types; use inkwell::types;
use inkwell::types::BasicType; use inkwell::types::BasicType;
use inkwell::values; use inkwell::values;
use inkwell::{IntPredicate, FloatPredicate};
#[derive(Debug)] #[derive(Debug)]
@ -193,7 +194,7 @@ impl<'ctx> CodeGen<'ctx> {
}, },
ast::ExpressionType::Number { value: ast::Number::Float { value } } => { ast::ExpressionType::Number { value: ast::Number::Float { value } } => {
Ok(self.context.f64_type().const_float(*value).into()) Ok(self.context.f64_type().const_float(*value).into())
} },
ast::ExpressionType::Identifier { name } => { ast::ExpressionType::Identifier { name } => {
match self.namespace.get(name) { match self.namespace.get(name) {
Some(value) => Ok(*value), Some(value) => Ok(*value),
@ -223,7 +224,70 @@ impl<'ctx> CodeGen<'ctx> {
=> Ok(self.builder.build_float_mul(a, b, "tmpmul").into()), => Ok(self.builder.build_float_mul(a, b, "tmpmul").into()),
_ => return Err(self.compile_error(CompileErrorKind::Unsupported("unimplemented operation"))), _ => return Err(self.compile_error(CompileErrorKind::Unsupported("unimplemented operation"))),
} }
} },
ast::ExpressionType::Compare { vals, ops } => {
let mut vals = vals.iter();
let mut ops = ops.iter();
let mut result = None;
let mut a = self.compile_expression(vals.next().unwrap())?;
loop {
if let Some(op) = ops.next() {
let b = self.compile_expression(vals.next().unwrap())?;
if a.get_type() != b.get_type() {
return Err(self.compile_error(CompileErrorKind::IncompatibleTypes));
}
let this_result = match (a, b) {
(values::BasicValueEnum::IntValue(a), values::BasicValueEnum::IntValue(b)) => {
match op {
ast::Comparison::Equal
=> self.builder.build_int_compare(IntPredicate::EQ, a, b, "tmpeq"),
ast::Comparison::NotEqual
=> self.builder.build_int_compare(IntPredicate::NE, a, b, "tmpne"),
ast::Comparison::Less
=> self.builder.build_int_compare(IntPredicate::SLT, a, b, "tmpslt"),
ast::Comparison::LessOrEqual
=> self.builder.build_int_compare(IntPredicate::SLE, a, b, "tmpsle"),
ast::Comparison::Greater
=> self.builder.build_int_compare(IntPredicate::SGT, a, b, "tmpsgt"),
ast::Comparison::GreaterOrEqual
=> self.builder.build_int_compare(IntPredicate::SGE, a, b, "tmpsge"),
_ => return Err(self.compile_error(CompileErrorKind::Unsupported("special comparison"))),
}
},
(values::BasicValueEnum::FloatValue(a), values::BasicValueEnum::FloatValue(b)) => {
match op {
ast::Comparison::Equal
=> self.builder.build_float_compare(FloatPredicate::OEQ, a, b, "tmpoeq"),
ast::Comparison::NotEqual
=> self.builder.build_float_compare(FloatPredicate::UNE, a, b, "tmpune"),
ast::Comparison::Less
=> self.builder.build_float_compare(FloatPredicate::OLT, a, b, "tmpolt"),
ast::Comparison::LessOrEqual
=> self.builder.build_float_compare(FloatPredicate::OLE, a, b, "tmpole"),
ast::Comparison::Greater
=> self.builder.build_float_compare(FloatPredicate::OGT, a, b, "tmpogt"),
ast::Comparison::GreaterOrEqual
=> self.builder.build_float_compare(FloatPredicate::OGE, a, b, "tmpoge"),
_ => return Err(self.compile_error(CompileErrorKind::Unsupported("special comparison"))),
}
},
_ => return Err(self.compile_error(CompileErrorKind::Unsupported("comparison of non-numerical types"))),
};
match result {
Some(last) => {
result = Some(self.builder.build_and(last, this_result, "tmpand"));
}
None => {
result = Some(this_result);
}
}
a = b;
} else {
return Ok(result.unwrap().into())
}
}
},
_ => return Err(self.compile_error(CompileErrorKind::Unsupported("unimplemented expression"))), _ => return Err(self.compile_error(CompileErrorKind::Unsupported("unimplemented expression"))),
} }
} }