[checkpoint] Start the switch to type inference.

This commit is contained in:
2023-06-19 21:16:28 -07:00
parent b931ba5b17
commit 3687785540
10 changed files with 424 additions and 284 deletions

View File

@@ -125,7 +125,7 @@ impl<M: Module> Backend<M> {
// Print statements are fairly easy to compile: we just lookup the
// output buffer, the address of the string to print, and the value
// of whatever variable we're printing. Then we just call print.
Statement::Print(ann, var) => {
Statement::Print(ann, t, var) => {
// Get the output buffer (or null) from our general compilation context.
let buffer_ptr = self.output_buffer_ptr();
let buffer_ptr = builder.ins().iconst(types::I64, buffer_ptr as i64);
@@ -137,7 +137,7 @@ impl<M: Module> Backend<M> {
// Look up the value for the variable. Because this might be a
// global variable (and that requires special logic), we just turn
// this into an `Expression` and re-use the logic in that implementation.
let (val, vtype) = ValueOrRef::Ref(ann, var).into_crane(
let (val, vtype) = ValueOrRef::Ref(ann, t, var).into_crane(
&mut builder,
&variable_table,
&pre_defined_symbols,
@@ -163,7 +163,7 @@ impl<M: Module> Backend<M> {
}
// Variable binding is a little more con
Statement::Binding(_, var_name, value) => {
Statement::Binding(_, var_name, _, value) => {
// Kick off to the `Expression` implementation to see what value we're going
// to bind to this variable.
let (val, etype) =
@@ -254,50 +254,62 @@ impl Expression {
Expression::Atomic(x) => x.into_crane(builder, local_variables, global_variables),
Expression::Cast(_, target_type, expr) => {
let (val, val_type) = expr.into_crane(builder, local_variables, global_variables)?;
let (val, val_type) =
expr.into_crane(builder, local_variables, global_variables)?;
match (val_type, &target_type) {
(ConstantType::I8, Type::Primitive(PrimitiveType::I8)) => Ok((val, val_type)),
(ConstantType::I8, Type::Primitive(PrimitiveType::I16)) =>
Ok((builder.ins().sextend(types::I16, val), ConstantType::I16)),
(ConstantType::I8, Type::Primitive(PrimitiveType::I32)) =>
Ok((builder.ins().sextend(types::I32, val), ConstantType::I32)),
(ConstantType::I8, Type::Primitive(PrimitiveType::I64)) =>
Ok((builder.ins().sextend(types::I64, val), ConstantType::I64)),
(ConstantType::I8, Type::Primitive(PrimitiveType::I16)) => {
Ok((builder.ins().sextend(types::I16, val), ConstantType::I16))
}
(ConstantType::I8, Type::Primitive(PrimitiveType::I32)) => {
Ok((builder.ins().sextend(types::I32, val), ConstantType::I32))
}
(ConstantType::I8, Type::Primitive(PrimitiveType::I64)) => {
Ok((builder.ins().sextend(types::I64, val), ConstantType::I64))
}
(ConstantType::I16, Type::Primitive(PrimitiveType::I16)) => Ok((val, val_type)),
(ConstantType::I16, Type::Primitive(PrimitiveType::I32)) =>
Ok((builder.ins().sextend(types::I32, val), ConstantType::I32)),
(ConstantType::I16, Type::Primitive(PrimitiveType::I64)) =>
Ok((builder.ins().sextend(types::I64, val), ConstantType::I64)),
(ConstantType::I16, Type::Primitive(PrimitiveType::I32)) => {
Ok((builder.ins().sextend(types::I32, val), ConstantType::I32))
}
(ConstantType::I16, Type::Primitive(PrimitiveType::I64)) => {
Ok((builder.ins().sextend(types::I64, val), ConstantType::I64))
}
(ConstantType::I32, Type::Primitive(PrimitiveType::I32)) => Ok((val, val_type)),
(ConstantType::I32, Type::Primitive(PrimitiveType::I64)) =>
Ok((builder.ins().sextend(types::I64, val), ConstantType::I64)),
(ConstantType::I32, Type::Primitive(PrimitiveType::I64)) => {
Ok((builder.ins().sextend(types::I64, val), ConstantType::I64))
}
(ConstantType::I64, Type::Primitive(PrimitiveType::I64)) => Ok((val, val_type)),
(ConstantType::U8, Type::Primitive(PrimitiveType::U8)) => Ok((val, val_type)),
(ConstantType::U8, Type::Primitive(PrimitiveType::U16)) =>
Ok((builder.ins().uextend(types::I16, val), ConstantType::U16)),
(ConstantType::U8, Type::Primitive(PrimitiveType::U32)) =>
Ok((builder.ins().uextend(types::I32, val), ConstantType::U32)),
(ConstantType::U8, Type::Primitive(PrimitiveType::U64)) =>
Ok((builder.ins().uextend(types::I64, val), ConstantType::U64)),
(ConstantType::U8, Type::Primitive(PrimitiveType::U16)) => {
Ok((builder.ins().uextend(types::I16, val), ConstantType::U16))
}
(ConstantType::U8, Type::Primitive(PrimitiveType::U32)) => {
Ok((builder.ins().uextend(types::I32, val), ConstantType::U32))
}
(ConstantType::U8, Type::Primitive(PrimitiveType::U64)) => {
Ok((builder.ins().uextend(types::I64, val), ConstantType::U64))
}
(ConstantType::U16, Type::Primitive(PrimitiveType::U16)) => Ok((val, val_type)),
(ConstantType::U16, Type::Primitive(PrimitiveType::U32)) =>
Ok((builder.ins().uextend(types::I32, val), ConstantType::U32)),
(ConstantType::U16, Type::Primitive(PrimitiveType::U64)) =>
Ok((builder.ins().uextend(types::I64, val), ConstantType::U64)),
(ConstantType::U16, Type::Primitive(PrimitiveType::U32)) => {
Ok((builder.ins().uextend(types::I32, val), ConstantType::U32))
}
(ConstantType::U16, Type::Primitive(PrimitiveType::U64)) => {
Ok((builder.ins().uextend(types::I64, val), ConstantType::U64))
}
(ConstantType::U32, Type::Primitive(PrimitiveType::U32)) => Ok((val, val_type)),
(ConstantType::U32, Type::Primitive(PrimitiveType::U64)) =>
Ok((builder.ins().uextend(types::I64, val), ConstantType::U64)),
(ConstantType::U32, Type::Primitive(PrimitiveType::U64)) => {
Ok((builder.ins().uextend(types::I64, val), ConstantType::U64))
}
(ConstantType::U64, Type::Primitive(PrimitiveType::U64)) => Ok((val, val_type)),
_ => Err(BackendError::InvalidTypeCast {
from: val_type.into(),
to: target_type,
@@ -305,7 +317,7 @@ impl Expression {
}
}
Expression::Primitive(_, prim, mut vals) => {
Expression::Primitive(_, _, prim, mut vals) => {
let mut values = vec![];
let mut first_type = None;
@@ -357,7 +369,7 @@ impl ValueOrRef {
match self {
// Values are pretty straightforward to compile, mostly because we only
// have one type of variable, and it's an integer type.
ValueOrRef::Value(_, val) => match val {
ValueOrRef::Value(_, _, val) => match val {
Value::I8(_, v) => {
Ok((builder.ins().iconst(types::I8, v as i64), ConstantType::I8))
}
@@ -387,7 +399,7 @@ impl ValueOrRef {
)),
},
ValueOrRef::Ref(_, name) => {
ValueOrRef::Ref(_, _, name) => {
// first we see if this is a local variable (which is nicer, from an
// optimization point of view.)
if let Some((local_var, etype)) = local_variables.get(&name) {