Get unary negation working.
This commit is contained in:
@@ -308,28 +308,39 @@ impl Expression {
|
||||
}
|
||||
|
||||
Expression::Primitive(_, prim, mut vals) => {
|
||||
// we're going to use `pop`, so we're going to pull and compile the right value ...
|
||||
let (right, rtype) =
|
||||
vals.pop()
|
||||
.unwrap()
|
||||
.into_crane(builder, local_variables, global_variables)?;
|
||||
// ... and then the left.
|
||||
let (left, ltype) =
|
||||
vals.pop()
|
||||
.unwrap()
|
||||
.into_crane(builder, local_variables, global_variables)?;
|
||||
let mut values = vec![];
|
||||
let mut first_type = None;
|
||||
|
||||
for val in vals.drain(..) {
|
||||
let (compiled, compiled_type) =
|
||||
val.into_crane(builder, local_variables, global_variables)?;
|
||||
|
||||
if let Some(leftmost_type) = first_type {
|
||||
assert_eq!(leftmost_type, compiled_type);
|
||||
} else {
|
||||
first_type = Some(compiled_type);
|
||||
}
|
||||
|
||||
values.push(compiled);
|
||||
}
|
||||
|
||||
let first_type = first_type.expect("primitive op has at least one argument");
|
||||
|
||||
assert_eq!(rtype, ltype, "primitive argument types match");
|
||||
// then we just need to tell Cranelift how to do each of our primitives! Much
|
||||
// like Statements, above, we probably want to eventually shuffle this off into
|
||||
// a separate function (maybe something off `Primitive`), but for now it's simple
|
||||
// enough that we just do the `match` here.
|
||||
match prim {
|
||||
Primitive::Plus => Ok((builder.ins().iadd(left, right), ltype)),
|
||||
Primitive::Minus => Ok((builder.ins().isub(left, right), ltype)),
|
||||
Primitive::Times => Ok((builder.ins().imul(left, right), ltype)),
|
||||
Primitive::Divide if rtype.is_signed() => Ok((builder.ins().sdiv(left, right), ltype)),
|
||||
Primitive::Divide => Ok((builder.ins().udiv(left, right), ltype)),
|
||||
Primitive::Plus => Ok((builder.ins().iadd(values[0], values[1]), first_type)),
|
||||
Primitive::Minus if values.len() == 2 => {
|
||||
Ok((builder.ins().isub(values[0], values[1]), first_type))
|
||||
}
|
||||
Primitive::Minus => Ok((builder.ins().ineg(values[0]), first_type)),
|
||||
Primitive::Times => Ok((builder.ins().imul(values[0], values[1]), first_type)),
|
||||
Primitive::Divide if first_type.is_signed() => {
|
||||
Ok((builder.ins().sdiv(values[0], values[1]), first_type))
|
||||
}
|
||||
Primitive::Divide => Ok((builder.ins().udiv(values[0], values[1]), first_type)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user